Source code for /engineering/2XTILE/Testing/BACKUPX.ASMOriginal file BACKUPX.ASM
   1 ; XTile  Assembler routine lib
   2 ;
   3 ; COPYRIGHT (C) 1993 Erich P Gatejen 1993  All Rights Reserved
   4 ;
   5 ; File: XTILE.ASM
   6 ;
   7 ; Mode X graphics manager.
   8 
   9 ; Ver 1.1 : Add sprites
  10 ;           Add 4-Pixel font   
  11 ;		  Add mouse interface		
  12 ;           Add put pixel
  13 
  14 ; Ver 2.0 : Major rewrite!
  15 ;		  Add virtual size
  16 ;		  Split-screen
  17 ;           More modes
  18 
  19 
  20 IDEAL
  21 
  22 
  23 INCLUDE "XTILE20!.USE"
  24 
  25 
  26 DOSSEG
  27 
  28 ; LARGE memory model.
  29 			MODEL 	LARGE
  30 
  31 ; ------------------------------------------------------------------------
  32 ; ----------------------------- Data Seg ---------------------------------
  33 ; ------------------------------------------------------------------------
  34 			FARDATA
  35 
  36 ; --- Mode set tables ----------------------------------------------------
  37 
  38 ; - CRTC Values
  39 CRTC_Single_Scan:       ; Single scan per line (400/480 Line modes)
  40 	   dw  04009H      ; 1 Scan Line
  41 	   dw  00014H      ; Dword Mode off
  42 	   dw  0E317H      ; Byte Mode
  43 
  44 CRTC_Double_Scan:       ; Double scan per line (200/240 Line modes)
  45 	   dw  04109H      ; Cell Height (2 Scan Lines)
  46 	   dw  00014H      ; Dword Mode off
  47 	   dw  0E317H      ; turn on Byte Mode
  48 
  49 CRTC_320_Wide:          ; CRTC Setup Data for 320 Horz Pixels
  50 	   dw  05F00H      ; Horz total
  51 	   dw  04F01H      ; Horz Displayed
  52 	   dw  05002H      ; Start Horz Blanking
  53 	   dw  08203H      ; End Horz Blanking
  54 	   dw  05404H      ; Start H Sync
  55 	   dw  08005H      ; End H Sync
  56  
  57 CRTC_360_Wide:          ; CRTC Setup Data for 360 Horz Pixels
  58 	   dw  06B00H      ; Horz total
  59 	   dw  05901H      ; Horz Displayed
  60 	   dw  05A02H      ; Start Horz Blanking
  61 	   dw  08E03H      ; End Horz Blanking
  62 	   dw  05E04H      ; Start H Sync
  63 	   dw  08A05H      ; End H Sync
  64 
  65 CRTC_200_Tall:
  66 CRTC_400_Tall:          ; CRTC Setup Data for 200/400 Line modes
  67 	   dw  0BF06H      ; Vertical Total
  68 	   dw  01F07H      ; Overflow
  69 	   dw  09C10H      ; V Sync Start
  70 	   dw  08E11H      ; V Sync End/Prot Cr0 Cr7
  71 	   dw  08F12H      ; Vertical Displayed
  72 	   dw  09615H      ; V Blank Start
  73 	   dw  0B916H      ; V Blank End
  74 	   dw  0           ; End table
  75 
  76 CRTC_240_Tall:
  77 CRTC_480_Tall:          ; CRTC Setup Data for 240/480 Line modes
  78 	   dw  00D06H      ; Vertical Total
  79 	   dw  03E07H      ; Overflow
  80 	   dw  0EA10H      ; V Sync Start
  81 	   dw  08C11H      ; V Sync End/Prot Cr0 Cr7
  82 	   dw  0DF12H      ; Vertical Displayed
  83 	   dw  0E715H      ; V Blank Start
  84 	   dw  00616H      ; V Blank End
  85 	   dw  0           ; End table
  86 
  87 
  88 ; - Tables for each mode
  89 XMODE_320x240:          ; 320 by 240 Pixels | Standard ModeX
  90 	dw  0E3h        ; 480 scan Lines & 28 Mhz Clock
  91 	dw  320, 240    ; View size 
  92 	dw  OFFSET CRTC_320_Wide 
  93 	dw  OFFSET CRTC_240_Tall
  94 	dw  OFFSET CRTC_Double_Scan
  95 
  96 XMODE_320x200:          ; 320 by 200 mode
  97 	dw  063h        ; 400 scan Lines & 25 Mhz Clock
  98 	dw  320, 200    ; View size 
  99 	dw  OFFSET CRTC_320_Wide 
 100 	dw  OFFSET CRTC_200_Tall
 101 	dw  OFFSET CRTC_Double_Scan
 102 
 103 XMODE_320x400:          ; 320 by 200 Pixels
 104 	dw  063h        ; 400 scan Lines & 25 Mhz Clock
 105 	dw  320, 400    ; View size 
 106 	dw  OFFSET CRTC_320_Wide
 107 	dw  OFFSET CRTC_400_Tall
 108 	dw  OFFSET CRTC_Single_Scan
 109  
 110 XMODE_360x240:          ; 360 by 240 Pixels
 111 	dw  0E7h        ; 480 scan Lines & 28 Mhz Clock
 112 	dw  360, 240    ; View size 
 113 	dw  OFFSET CRTC_360_Wide
 114 	dw  OFFSET CRTC_240_Tall
 115 	dw  OFFSET CRTC_Double_Scan
 116 
 117 XMODE_360x480:          ; 360 by 480 Pixels
 118 	dw  0E7h        ; 480 scan Lines & 28 Mhz Clock
 119 	dw  360, 480    ; View size 
 120 	dw  OFFSET CRTC_360_Wide 
 121 	dw  OFFSET CRTC_480_Tall
 122 	dw  OFFSET CRTC_Single_Scan
 123   
 124 XMODE_320x480:          ; 320 by 480 Pixels
 125 	dw  0E3h        ; 480 scan Lines & 28 Mhz Clock
 126 	dw  320, 480    ; View size 
 127 	dw  OFFSET CRTC_320_Wide 
 128 	dw  OFFSET CRTC_480_Tall
 129 	dw  OFFSET CRTC_Single_Scan
 130 
 131 XMODE_360x200:          ; 360 by 200 Pixels
 132 	dw  067h        ; 400 scan Lines & 28 Mhz Clock
 133 	dw  360, 200    ; View size
 134 	dw  OFFSET CRTC_360_Wide 
 135 	dw  OFFSET CRTC_200_Tall
 136 	dw  OFFSET CRTC_Double_Scan
 137 
 138 XMODE_360x400:          ; 360 by 200 Pixels
 139 	dw  067h        ; 400 scan Lines & 28 Mhz Clock
 140 	dw  360, 400    ; View size 
 141 	dw  OFFSET CRTC_360_Wide 
 142 	dw  OFFSET CRTC_400_Tall
 143 	dw  OFFSET CRTC_Single_Scan
 144 
 145 ; Structure to access mode tables
 146 STRUC MODE_TABLE   
 147      MiscTiming    dw  ?
 148      XSizeM	   dw  ?
 149      YSizeM	   dw  ?
 150      WidthDataO	   dw  ?
 151 	HightDataO	   dw  ?
 152      ScanDataO	   dw  ?
 153 										
 154 ENDS MODE_TABLE
 155 
 156  
 157 ; - Table of available modes.  Position relates to mode number
 158 XMODE_TABLE:
 159 	dw  OFFSET 	XMODE_320x240		; Mode 0.  Standard mode X
 160 	dw  OFFSET 	XMODE_320x200		; Mode 1.
 161 	dw  OFFSET 	XMODE_320x400		; Mode 2.
 162 	dw  OFFSET 	XMODE_360x400		; Mode 3.
 163 	dw  OFFSET 	XMODE_360x200		; Mode 4.
 164 	dw  OFFSET 	XMODE_360x240		; Mode 5.
 165 	dw  OFFSET 	XMODE_320x480		; Mode 6.
 166 	dw  OFFSET 	XMODE_360x480		; Mode 7.
 167 
 168 
 169 ; --- Other Tables --------------------------------------------------------
 170 
 171 ; Pixel mask table for pixel put.
 172 LABEL	PMask_Table	BYTE
 173 	db		00000001b ; Plane 0, first pix of XBlock
 174 	db		00000010b ; Plane 1, second pix of XBlock
 175 	db		00000100b ; Plane 2, third pix of XBlock
 176 	db		00001000b ; Plane 3, forth pix of XBlock
 177 
 178 
 179 ; ---- Copyright notice --------------------------------------------------
 180 Banner  db	   'COPYRIGHT (C) 1993 Erich P Gatejen' ; Do not remove
 181 	   db        ' All Rights Reserved '              ; Do not remove
 182 ID	   db	   ' !!!!'
 183 
 184 
 185 ; ---- XTile local data -------------------------------------------------- 
 186 
 187 ; --- Define the current write page
 188 Write_Page	dw	?	; Offset into current write page
 189 WLine_Offset	dw	?	; Line size in the current write page
 190 
 191 ; --- Define the current display page
 192 Display_Page   dw	?	; Offset into display page
 193 DLine_Offset	dw	?	; Line size in current display page
 194 DisplaySizeX	dw	?	; Size of display page (X)
 195 DisplaySizeY	dw	?	; Size of display page (Y)
 196 ViewXLoc   	dw	?	; Starting X of view
 197 ViewYLoc  	dw	?	; Starting Y of view
 198 MaxViewX  	dw	?	; Maximum View X
 199 MaxViewY  	dw   ?	; Max     View Y
 200 SplitY		dw	?	; 0 = no split screen.  Else, Y size.
 201 ScreenSizeX	dw   ?	; Actual screen size
 202 ScreenSizeY    dw	?	; Actual screen size
 203 
 204 
 205 ; --- Font data
 206 ; 8-pix font
 207 UpLoaded8		dw	1	; Is it uploaded?  Assume not.
 208 Font_SiteU8	dw	?	; Offset of registered uploaded font
 209 LABEL Font_Addr8	DWORD  ; For loading the address of an non-uploaded font
 210 Font_SiteD8	dw	?	; Offset of registered not-uploaded font
 211 FSS8			dw	?	; Segment.  Don't change
 212 Char_Base8	dw	?	; Base character for font
 213 Font_Mask_S8	dw	?	; Seg with masks for font set
 214 Font_Mask_O8	dw	?	; Offset
 215 
 216 ; 4-pix font
 217 UpLoaded4		dw	1	; Is it uploaded?  Assume not.
 218 Font_SiteU4	dw	?	; Offset of registered uploaded font
 219 LABEL Font_Addr4	DWORD  ; For loading the address of an non-uploaded font
 220 Font_SiteD4	dw	?	; Offset of registered not-uploaded font
 221 FSS4			dw	?	; Segment.  Don't change
 222 Char_Base4	dw	?	; Base character for font
 223 Font_Mask_S4	dw	?	; Seg with masks for font set
 224 Font_Mask_O4	dw	?	; Offset
 225 
 226 
 227 ; --- Mouse data
 228 Mouse_Hndlr_O  dd  FAR	?    ; Address of the user defined mouse handler
 229 LABEL MPointerMask DWORD      ; Address of the S:O for the next  two
 230 MPointerMask_O dw	?    ; Location in user data of the mouse pntr mask
 231 MPointerMask_S dw	?    ; Segment ^
 232 MUEventMask    dw	?    ; Events user wishes to be reported
 233 MLastX	     dw	?    ; Last known X location of the mouse
 234 MLastY         dw   ?    ; Last known Y location of the mouse
 235 LockHandler	dw	0	; Block re-entry into mouse handler
 236 
 237 ; --- Clip Values
 238 ClipXS		dw	?	; Clip starting X
 239 ClipYS		dw	?	; Clip starting Y
 240 ClipXE		dw	?	; Clip ending	 X
 241 ClipYE		dw	?	; Clip ending	 Y
 242 
 243 
 244 
 245 ENDS
 246 
 247 
 248 
 249 ; ------------------------------------------------------------------------
 250 ; ---------------------------- Code Seg ----------------------------------
 251 ; ------------------------------------------------------------------------
 252 			SEGMENT 	CODE	   WORD	PUBLIC  'CODE'
 253 
 254 
 255 			ASSUME	cs:CODE
 256 
 257 ; --------------------------- _XInit_Mode -------------------------------
 258 ; - This will initialize Mode X.
 259 ; -
 260 public	  _XInit_Mode
 261 
 262 PROC	  _XInit_Mode   FAR
 263 
 264 	ARG	Mode:WORD
 265 
 266 	  push		bp
 267 	  mov		bp,   sp    ; Save Stack frame
 268 	  push         si di ds    ; Save calling frame
 269 
 270 	  ASSUME   ds:  @fardata
 271 	  mov	 ax,  @fardata    ; Set DS to segment w/ Table
 272 	  mov	 ds,  ax
 273 
 274 	  ; Load SI with pointer to table entry
 275 	  mov	   bx,	[Mode]	         ; Get mode number
 276 	  shl	   bx,  1	         ; Find table offset
 277 		; FIX THIS
 278 	  mov	   di,	OFFSET XMODE_TABLE ; Point to the entry
 279 	  add        di,  bx
 280 	  mov	   si,  [di]
 281 
 282 	  ; Set mode
 283 	  mov      ax,  13H         ; First, setup as Mode 13H
 284 	  int      10h              ; Let BIOS do it
 285  
 286 	  mov	   dx,  SC_INDEX    ; Modify the Sequence Controller
 287 	  mov	   ax,	0604h	    ; Disable CHAIN-4
 288 	  out	   dx,	ax
 289 	  				
 290 	  mov	   ax,	0100h	    ; Synch reset 
 291 	  out	   dx,	ax			
 292 
 293 	  mov	   dx,	MISC_OUTPUT 	; Modify the Misc Output
 294 	  mov	   ax,	[(MODE_TABLE PTR si).MiscTiming] ; Set timing and size
 295 	  out	   dx,	al
 296 
 297 	  mov	   dx,	SC_INDEX	; Modify the Sequence Cont.
 298 	  mov	   ax,  0300h		; Resart the sequencer
 299 	  out	   dx,  ax
 300 		
 301        ; Unprotect the CRTC registers
 302 	  mov	   dx,	CRTC_INDEX
 303 	  mov	   al,  011h
 304 	  out	   dx,  al
 305 	  inc 	   dx
 306 	  in	   al,	dx
 307 	  and      al,  07Fh	; Mask out protect bit
 308 	  out	   dx,  al	; Unprotect
 309 
 310     ; --- Set up the CRT controller
 311 	  mov	   dx,  CRTC_INDEX
 312 	  
 313 	  ; - Set width
 314 	  mov	   cx,  6
 315 	  mov      di,  [(MODE_TABLE PTR si).WidthDataO] ;Get width table off
 316    @@LoopWidth:
 317 	  mov	   ax,  [di]		; Load ax with table vaule
 318 	  out	   dx,  ax
 319 	  add	   di,  2		; Point to next item
 320 	  loop	   @@LoopWidth
 321 	  
 322        ; - Set hight	 	   	  					
 323 	  mov	   di,  [(MODE_TABLE PTR si).HightDataO] ;Get hight table off
 324    @@LoopHight:
 325 	  mov	   ax,  [di]
 326 	  or	   ax,  ax		; Is it the end of table
 327 	  jz	   @@Scans		; Yes, move on		
 328 	  add	   di,  2		; Point to next item
 329 	  out	   dx,  ax		; Send current one out
 330 	  jmp	   @@LoopHight
 331 	  
 332        ; - Set scans
 333    @@Scans:
 334 	  mov	   cx,  3
 335 	  mov      di,  [(MODE_TABLE PTR si).ScanDataO] ; Get width table offset
 336    @@LoopScans:
 337 	  mov	   ax,  [di]		; Load ax with table vaule
 338 	  out	   dx,  ax
 339 	  add	   di,  2		; Point to next item
 340 	  loop	   @@LoopScans
 341 
 342     ; --- Set default page information
 343 
 344 	  ; - Write page
 345 	  mov	ax,           0
 346 	  mov   [Write_Page], ax	   ; Write page offset 0000
 347 	  mov   ax,	     [(MODE_TABLE PTR si).XSizeM]  ; Default XBlocks p/line is X size
 348 	  shr   ax, 1
 349 	  shr   ax, 1
 350 	  mov   [WLine_Offset], ax	   ; Set line size in XBlocks
 351 
 352 	  ; - Display Page.  Same page as the default writepage
 353 	  mov   [DLine_Offset], ax	   ; Set line size in XBlocks
 354 	  mov   ax,		0
 355 	  mov   [Display_Page], ax	   ; Display offset 0000
 356 	  mov   [SplitY],	ax	   ; No split screen
 357 	  mov   [ViewX],	ax	   ; View at base
 358 	  mov   [ViewY],	ax	   ; View at base
 359 	  mov   [MaxViewX],	ax	   ; No room to move
 360 	  mov   [MaxViewY],	ax
 361 	  mov   ax,	         [(MODE_TABLE PTR si).XSizeM] ; Display size X
 362 	  mov   [DisplaySizeX], ax
 363 	  mov   [ScreenSizeX],  ax
 364 	  mov   ax,	         [(MODE_TABLE PTR si).YSizeM] ; Display size Y
 365 	  mov   [DisplaySizeY], ax
 366 	  mov   [ScreenSizeY],  ax
 367 
 368 
 369 	  ; !!DONE!!
 370 	  pop	  ds di si             ; Return state
 371 	  pop	  bp
 372 	  ret
 373 
 374 
 375 
 376 ENDP			_XInit_Mode
 377 
 378 
 379 ; --------------------------- _XSet_Write_Page ------------------------------
 380 ; - This will set a write page.  It will be the current write page for 
 381 ; - most write operations ( the ones that don't use this page will say
 382 ; - so in thier discription )
 383 ; -
 384 public		_XSet_Write_Page
 385 
 386 PROC			_XSet_Write_Page   FAR
 387 
 388 	ARG	Offst:WORD, XSize:WORD
 389 
 390 	push		bp
 391 	mov		bp,	sp		; Save Stack frame
 392 	push		ds
 393 
 394 	; Set the DS to local data
 395 	ASSUME	ds:  @fardata
 396 	mov	ax,  @fardata
 397 	mov	ds, 	ax
 398 
 399 	; First, load the page offset
 400 	mov	ax,           [Offst]	; Get offset from pass
 401 	mov	[Write_Page], ax	; Put it in var
 402 
 403 	; Calculate the line offset
 404 	mov     ax,	[XSize]		; Get the total size
 405 	shr     ax, 1                   ; divided by 4 to make XBlocks
 406 	shr     ax, 1			   
 407 	mov     [WLine_Offset], ax	; Set line size in XBlocks
 408 
 409      ; !!DONE!!
 410 	pop	ds             ; Return state
 411 	pop	bp
 412 	ret
 413 
 414 ENDP			_XSet_Write_Page
 415 
 416 
 417 ; --------------------------- _XSet_Display_Page -------------------------------
 418 ; - This function set will set the display page.  The view will also be set
 419 ; -
 420 public	_XSet_Display_Page
 421 
 422 PROC	_XSet_Display_Page   FAR
 423 
 424 	ARG   Offst:WORD, XSize:WORD, YSize:WORD, ViewX:WORD, ViewY:WORD
 425 
 426 
 427 	push		bp
 428 	mov		bp,	sp	; Set up stack frame
 429 	push		ds 
 430 
 431 
 432      ; Set DS to local data
 433 	ASSUME	ds:  @fardata
 434 	mov	ax,  @fardata
 435 	mov	ds,  ax		      
 436 
 437      ; Wait for retrace to end
 438 	mov     dx, IN_STATUS1  ; Input Status #1 Register
 439    @Wait:
 440 	in      al, dx           
 441 	and     al, 08h         
 442 	jnz     @Wait           
 443  
 444    ; Set line offset.  CRTC Offset register
 445      ; Calculate the line offset
 446 	mov     ax,	        [XSize]  ; Get the total size
 447 	mov     [DisplaySizeX], ax      ; Save it
 448 	shr     ax, 1                   ; divide by 4 to make XBlocks
 449 	shr     ax, 1
 450 	mov     [DLine_Offset], ax	; Save XBlocks per line
 451 	shr	   ax, 1			; divide by 2 to get register value
 452 	
 453 	; Set it
 454 	mov	   dx, CRTC_INDEX  ; Set port
 455 	mov     ah, 13h         ; CRTC Offset Register Index
 456 	xchg    al, ah          ; Swap format
 457 	out     dx, ax          ; Send it
 458 
 459    ; Set the Start Display Address to the new window
 460 	mov     cx, [ViewX]     ; Get X start for the view
 461 	mov     [ViewXLoc], cx  ; Save it for later
 462 	mov     ax, [ViewY]     ; Get Y start for the view
 463 	mov     [ViewYLoc], ax  ; Save it for later
 464 
 465 	; Compute proper Display start address to use
 466 	mul     [DLine_Offset]  ; AX = Y size (AX) * XBlocks per line
 467 	shr     cx, 1
 468 	shr     cx, 1    	    ; Convert CX to XBlocks.  Figure pan later
 469 	add     cx, ax          ; Find view upper left pixel
 470 	add     cx, [Offst]     ; Add page offset
 471 	; NOTE: This will leave any 0-3 pan  for later
 472 
 473 	; Change CRTC
 474 	mov	   dx, CRTC_INDEX  ; Set port
 475 	mov     al, 0Dh   	; Start display low.
 476 	mov     ah, cl		; Load low 8 bits
 477 	out     dx, ax          
 478 	mov     al, 0Ch	; Start display high
 479 	mov     ah, ch      ; Load high 8 Bits
 480 	out     dx, ax
 481  
 482    ; Wait for a Vertical Retrace
 483 	mov     dx, IN_STATUS1  
 484    @@Wait2:
 485 	in      al, dx 
 486 	and     al, 08h    	; Vertical Retrace Start?
 487 	jz      @@Wait2         ; If Not, loop until it is
 488  
 489    ; Now Set the Horizontal Pixel Pan values
 490 	mov	dx, 03C0h	; The Attribute controller
 491 	mov	al, 033h	; Select Pixel Pan Register
 492 	out  dx, al
 493 
 494      ; Get the pan value and send it 
 495 	mov     ax, [ViewX]     ; Get raw X View start
 496 	and     al, 03          ; Peel off the significant bits
 497 	shl     al, 1           ; Shift for 256 Color Mode
 498 	out     dx, al          ; Send it
 499 
 500    ; Set some data values for this display page
 501 	
 502      ; Max View limits
 503 	mov	ax, [XSize]	   ; Get the page size
 504 	sub  ax, [ScreenSizeX] ; subtract the actual screen size
 505 	dec	ax		        ; Adjust for count from 0
 506 	mov	[MaxViewX], ax	   ; Save	
 507 
 508 	mov	ax, [YSize]	    ; Get the page size
 509 	mov  [DisplaySizeY], ax ; Save this
 510 	sub  ax, [ScreenSizeY]  ; subtract the actual screen size
 511 	dec	ax		         ; Adjust for count from 0
 512 	mov	[MaxViewY], ax	    ; Save
 513 
 514      ; Save page offset
 515 	mov	ax, [Offst]
 516 	mov  [Display_Page], ax
 517 
 518    ; DONE!!
 519    @@Done:
 520 	pop     ds             ; Return state
 521 	pop     bp
 522 	ret
 523 
 524 ENDP			_XSet_Display_Page
 525 
 526 
 527 ; --------------------------- _XSet_View ----------------------------------
 528 ; - This function set will set the view port within the current page
 529 ; - Return 0 if successful, else 1 (TRUE for C)
 530 public	_XSet_View
 531 
 532 PROC	_XSet_View   FAR
 533 
 534 	ARG   ViewX:WORD, ViewY:WORD
 535 
 536 
 537 	push		bp
 538 	mov		bp,	sp	; Set up stack frame
 539 	push		ds 
 540 
 541 
 542 	; Set DS to local data
 543 	ASSUME	ds:  @fardata
 544 	mov	ax,  @fardata
 545 	mov	ds,  ax
 546 
 547      ; Wait for retrace to end
 548 	mov     dx, IN_STATUS1  ; Input Status #1 Register
 549    @@Wait:
 550 	in      al, dx           
 551 	and     al, 08h         
 552 	jnz     @@Wait           
 553  
 554 
 555    ; Set the Start Display Address to the new window
 556 	mov     cx, [ViewX]      ; Get X start for the view
 557 	cmp     cx, [MaxViewX]	; Is it within range
 558 	ja      @@Error		; No, jump out.
 559 	mov     [ViewXLoc], cx   ; Save the view location
 560 
 561 	mov     ax, [ViewY]      ; Get Y start for the view
 562 	cmp     ax, [MaxViewY]	; Is it within range
 563 	ja      @@Error		; No, jump out.
 564 	mov     [ViewYLoc], ax	; Save the view loc
 565 
 566      ; Compute proper Display start address to use
 567 	mul     [DLine_Offset]  ; AX = Y size (AX) * XBlocks per line
 568 	shr     cx, 1           
 569 	shr     cx, 1    	    ; Conver CX to XBlocks.  Figure pan later
 570 	add     cx, ax             ; Find view upper left pixel
 571 	add     cx, [Display_Page] ; Add page offset
 572 	; NOTE: This will leave any 0-3 pan  for later
 573 
 574      ; Change CRTC
 575 	mov	   dx, CRTC_INDEX  ; Set port
 576 	mov     al, 0Dh   	    ; Start display low.
 577 	mov     ah, cl		    ; Load low 8 bits
 578 	out     dx, ax
 579 	mov     al, 0Ch	    ; Start display high
 580 	mov     ah, ch          ; Load high 8 Bits
 581 	out     dx, ax
 582 
 583    ; Wait for a Vertical Retrace
 584 	mov     dx, IN_STATUS1
 585    @@Wait2:
 586 	in      al, dx
 587 	and     al, 08h    	; Vertical Retrace Start?
 588 	jz      @@Wait2     ; If Not, loop until it is
 589 
 590    ; Now Set the Horizontal Pixel Pan values
 591 	mov	dx, 03C0h	; The Attribute controller
 592 	mov	al, 033h	; Select Pixel Pan Register
 593 	out  dx, al
 594 
 595 	; Get the pan value and send it
 596 	mov     ax, [ViewX]     ; Get raw X View start
 597 	and     al, 03          ; Peel off the significant bits
 598 	shl     al, 1           ; Shift for 256 Color Mode
 599 	out     dx, al          ; Send it
 600 
 601    ; DONE!!
 602 	mov	ax,	0       ; No Error, Get outta here
 603 	jmp     @@Done
 604 
 605    @@Error:			
 606 	mov	ax,	1       ; Error
 607 
 608    @@Done:
 609 	pop     ds             ; Return state
 610 	pop     bp
 611 	ret
 612 
 613 ENDP	_XSet_View
 614 
 615 
 616 ; --------------------------- _XWait_Retrace -------------------------------
 617 ; - Wait for vertical retrace
 618 public	_XWait_Retrace
 619 
 620 PROC	_XWait_Retrace   FAR
 621 
 622    ; Wait for a Vertical Retrace
 623 	mov     dx, IN_STATUS1
 624    @@Wait1:
 625 	in      al, dx
 626 	and     al, 08h    	; Vertical Retrace Start?
 627 	jz      @@Wait1     ; If Not, loop until it is
 628 
 629 	ret
 630 
 631 ENDP	_XWait_Retrace
 632 
 633 
 634 ; --------------------------- _XSet_Box --------------------------------
 635 ; - This function will draw a box to the passed value.  The X coord must
 636 ; - be MOD 4 aligned.  
 637 ; -
 638 public	_XSet_Box
 639 
 640 PROC	_XSet_Box   FAR
 641 
 642 	ARG   X_S:WORD,	Y_S:WORD, X_D:WORD, Y_D:WORD, COLOR:BYTE
 643 
 644 	push		bp
 645 	mov		bp,	sp			; Save Stack frame
 646 	push		ds di si
 647 
 648 	; Set DS to local data
 649 	ASSUME	ds:  @fardata
 650 	mov	ax,  @fardata	       
 651 	mov	ds,  ax
 652 
 653 	cld
 654 
 655      ; Set ES to display mem and DI to start of rectangle on screen
 656 	mov	ax,  SCREEN_SEG
 657 	mov	es,  ax
 658 
 659 	mov 	ax,  [WLine_Offset]  ; Get the line length for write page
 660 	mov     bx,  ax		     ; Save in BX for later		
 661 	mul	[Y_S]		     ; Find Y offset value. Place in AX
 662 
 663 	mov	di,  [X_S]     ; Find X offset value. Place in DI
 664 	shr	di,  1
 665 	shr	di,  1	       ; Adjust for planes
 666 
 667 	add	di,  ax		    ; Add X and Y offsets
 668 	add	di,  [Write_Page]   ; Add in page offset
 669 
 670      ; Set all data from CPU and non from latches
 671 	mov	dx,  GC_INDEX
 672 	mov	ax,  0FF00h + BIT_MASK  ; Set all CPU writes
 673 	out	dx,  ax
 674 
 675 	; Insure Map Mask is set to all planes
 676 	mov	ax,  0F02h	; 0F sets all planes. 02 is Map Mask
 677 	mov	dx,  SC_INDEX
 678 	out	dx,  ax
 679 
 680      ; Insure X dist isn't 0 and put number of XBlocks in CX
 681 	mov	cx,  [X_D]
 682 	shr	cx,  1		; Div by 4 so we have
 683 	shr	cx,  1          ; the actual number addresses to fill
 684 				; per line
 685 	cmp	cx,  0
 686 	jle	@@Done		; Jump to stop if invalid
 687 
 688 
 689      ; SI will contain the number lines
 690 	mov	si,	[Y_D]
 691 
 692      ; Load color into al
 693 	mov	al,  [COLOR]
 694 
 695      ; Set BX to contain the distance from one scan line to next
 696 	sub 	bx,	cx    ; BX was already loaded with line length
 697 
 698    @@Rowloop:
 699 	push	cx	; Push cx so we can restore for each iteration
 700 
 701      ; Do the actual line.  REP STOSB.
 702 	rep	stosb
 703 
 704      ; Adjust for next iteration
 705 	pop	cx		; Restore CX. ( [Pix/line]/4 )
 706 	add	di,	bx	; Point DI to start of next line
 707 
 708      ; End of Rowloop.  Dec SI, if it is NOT 0 then do next line
 709 	dec	si
 710 	jnz	@@Rowloop
 711 
 712      ; Else DONE!!
 713 
 714    @@Done:
 715 	pop	si di ds
 716 	pop     bp
 717 	ret
 718 
 719 ENDP			_XSet_Box
 720 
 721 
 722 ; --------------------------- _XClear -------------------------------
 723 ; - This will clear all memory on the video card to the passed value
 724 ; -
 725 public	_XClear
 726 
 727 PROC	_XClear   FAR
 728 
 729 	ARG	COLOR:WORD
 730 
 731 	push	bp
 732 	mov	bp,	sp			; Save Stack frame
 733 	push	di
 734 
 735      ; Set MAP MASK to all planes
 736 	mov	dx,	SC_INDEX		
 737 	mov	ax,	0F02h
 738 	out	dx,	ax
 739 
 740      ; Clear the screen
 741 	mov	ax,  SCREEN_SEG
 742 	mov	es,  ax
 743 	sub	di,  di
 744 	sub	ax,  ax
 745 	mov	ax,  [COLOR]
 746 	mov     ah,  al
 747 	mov	cx,  8000h
 748 	rep	stosw
 749 
 750      ; DONE!
 751 	pop	di   ; Return state
 752 	pop	bp
 753 	ret
 754 
 755 ENDP			_XClear
 756 
 757 
 758 ; --------------------------- _XPut_Tile -------------------------------
 759 ; - This function will place a tile on the current write screen
 760 ; - It will be done a plane at a time and will expect the image data
 761 ; - to be laid out one plane at a time.
 762 ; - If there is an even number of XBlocks then a word write will be used
 763 ; -
 764 public		_XPut_Tile
 765 
 766 PROC			_XPut_Tile   FAR
 767 
 768 	ARG	X_S:WORD,	Y_S:WORD, X_D:WORD,	Y_D:WORD,	IMAGE_OFF:DWORD
 769 
 770 			push		bp
 771 			mov		bp,	sp			; Save Stack frame
 772 			push		ds di si
 773 
 774 			cld
 775 
 776 		; Set all data from CPU and non from latches
 777 			mov		dx,	GC_INDEX
 778 			mov		ax,	0FF00h + BIT_MASK  ; Set all CPU writes
 779 			out		dx, 	ax
 780 
 781 		; Get the Screen Seg and put it in es and load ds to fardata
 782 			mov		ax,  SCREEN_SEG
 783 			mov		es,  ax
 784 
 785 			ASSUME	ds:  @fardata
 786 			mov		ax,  @fardata
 787 			mov		ds,  ax			; Set DS to local fardata
 788 
 789 		; Load CX with the number of XBlocks per image line
 790 			mov		cx,	  [X_D]
 791 			shr		cx,	  1
 792 			shr		cx,	  1         ; Divide by 4 to get
 793 			mov		[X_D], cx		  ; Save CX as new Delta
 794 
 795 		; Load di with destination offset and save it in DEST
 796 			mov		ax,       [WLine_Offset]	; Size of line in XBlocks
 797 			mov		bx,	ax				; Save in DX
 798 			mul		[Y_S]
 799 
 800 			mov		di,	[X_S]
 801 			shr		di,  1
 802 			shr		di,	1
 803 
 804 			add       di,	[Write_Page]
 805 			add		di,	ax            ; Di is now loaded
 806 
 807 			mov       [X_S],	di       ; Store it.  Steal X start
 808 
 809 		; Set [Y_S] to the distance from one scan line to next
 810 			sub		bx,		cx		     ; minus number of XBlocks
 811 			mov	     [Y_S],    bx			; Move to store
 812 
 813 		; Set BX to the number of scan lines
 814 			mov		bx,  	[Y_D]
 815 
 816 		; Load ds:si with source
 817 			lds		si,	[IMAGE_OFF]
 818 
 819 		; Set up DX and AX for plane selection
 820 			mov		al,  02h		; Select Map Mask
 821 			mov		dx,	SC_INDEX
 822 			out		dx,	al
 823 			inc		dx
 824 			mov		al,	011h		; Set for plane selection
 825 
 826 		; Save CX in AH
 827 			mov		ah,	cl
 828 
 829 		; This section is for the WRITES ------------------------------
 830 
 831 	@@PlanesW:          ; Master plane loop.
 832 
 833 			out		dx,  al        ; Set map mask
 834 			mov		dx,	[Y_S]     ; Steal DX to speed up add
 835 
 836 	@@RowloopW:         	; Scan line loop
 837 
 838 		; Do the actual line.  REP MOVSW.
 839 			shr		cx,	1		; Shift for word
 840 			rep		movsw
 841 			adc		cx,	0		; Add 1(carry) to CX if dangling byte
 842 			rep 		movsb		; Write dangle if there
 843 
 844 		; Adjust for next iteration
 845 			mov		cl,  ah		; Restore CX
 846 			add		di,	dx		; Point DI to start of next line
 847 
 848 		; !!End of Rowloop.  Dec BX, if it is NOT 0 then do next line
 849 			dec		bx
 850 			jnz		@@RowloopW
 851 
 852 		; Done with plane.  Reset Destination pointers.  Adjst plane
 853 			mov		di,	[X_S]     ; Restore destination
 854 			mov		bx,	[Y_D]	; Restore scan line count
 855 
 856 		; !!End of Plane loop.
 857 			mov		dx, (SC_INDEX+1) ; Restore DX for next plane
 858 			shl       al, 1            ; Shift up a plane.  Carry set = done
 859 			jnc		@@PlanesW		  ; If carry set, drop out
 860 
 861 		; !!!DONE
 862 			pop		si di ds             ; Return state
 863 			pop		bp
 864 			ret
 865 
 866 ENDP			_XPut_Tile
 867 
 868 
 869 ; --------------------------- _XTile_Size -----------------------------------
 870 ; - This function will return the total number of bytes an image requires
 871 ; - Div by 4 will yield the number of XBlocks
 872 public		_XTile_Size
 873 
 874 PROC			_XTile_Size   FAR
 875 
 876 	ARG	 X_D:WORD,	Y_D:WORD
 877 
 878 
 879 			push		bp
 880 			mov		bp,	sp		; Save Stack frame
 881 
 882 		; Load AX with the total number of bytes
 883 			mov		cx,	[X_D]
 884 			mov		ax,	[Y_D]
 885 			mul		cx	  	  ; Yield is total bytes
 886 
 887 		; AX holds return
 888 			pop		bp
 889                ret
 890 
 891 ENDP			_XTile_Size
 892 
 893 
 894 ; --------------------------- _XUpload_Tile -------------------------------
 895 ; - This function will place a tile in the display memory
 896 ; - It will be done a plane at a time and will expect the image data
 897 ; - to be laid out one plane at a time.
 898 ; - The tile will be laid out in a linear manner and even though it may be
 899 ; - sent to the current screen it will not be correctly displayed
 900 ; -
 901 public		_XUpload_Tile
 902 public		_XUpload_Sprite
 903 LABEL          _XUpload_Sprite	FAR
 904 
 905 PROC			_XUpload_Tile   FAR
 906 
 907 	ARG 	  DEST:WORD, ISIZE:WORD, IMAGE_OFF:DWORD
 908 
 909 			push		bp
 910 			mov		bp,	sp			; Save Stack frame
 911 			push		ds di si
 912 
 913 			cld
 914 
 915 		; Get the Screen Seg and put it in es
 916 			mov		ax,  SCREEN_SEG
 917 			mov		es,  ax
 918 
 919 
 920 		; Load di with destination offset and save it in DEST
 921 			mov		di,		[DEST]
 922 			mov       bx,		di       ; Store it
 923 
 924 		; Load ds:si with source
 925 			lds		si,	[IMAGE_OFF]
 926 
 927 		; Get number of XBlocks per plane.
 928 			mov		cx,  [ISIZE]
 929 			shr		cx,  1
 930 			shr		cx,  1
 931 			mov		bp,  cx	; Save size in BP
 932 
 933 		; Set all data from CPU and non from latches
 934 			mov		dx,	GC_INDEX
 935 			mov		ax,	0FF00h + BIT_MASK  ; Set all CPU writes
 936 			out		dx, 	ax
 937 
 938 		; Set up DX and AX for plane selection
 939 			mov		al,	02h		; Select the MAP MASK
 940 			mov		dx,	SC_INDEX
 941 			out		dx,  al
 942 			inc		dx
 943 			mov		al,	11h		; Plane 0
 944 
 945 		; This section is for WRITES ------------------------------
 946 	@@BeginWrite:
 947 
 948 	@@PlanesW:       		; Master plane loop.
 949 
 950 			out	     dx,	al	; Set the plane
 951 
 952 		; Do the actual line.  REP MOVSW.
 953 			shr		cx,	1	; Set for word writes
 954 			rep		movsw
 955 			adc		cx,	0	; Add 1(carry) to CX to see if dangle
 956 			rep       movsb	; Write the dangle if there.
 957 
 958 		; Done with plane.  Reset Destination pointers.  Adjst plane
 959 			mov		di,	bx		; Restore Destination
 960 			mov		cx,  bp		; Restore CX.
 961 
 962 		; !!End of Plane loop.
 963 			shl		al,	1		; Shift plane selector
 964 			jnc		@@PlanesW		; If no carry, then more to do
 965 
 966 
 967 		; !!DONE!!
 968 			pop		si di ds            ; Return state
 969 			pop		bp
 970 			ret
 971 
 972 ENDP			_XUpload_Tile
 973 
 974 
 975 ; --------------------------- _XPaste_Tile -------------------------------
 976 ; - This function will place a tile from the display memory to current screen
 977 ; -
 978 public		_XPaste_Tile
 979 
 980 PROC			_XPaste_Tile   FAR
 981 
 982 
 983 	ARG	X_S:WORD,	Y_S:WORD, X_D:WORD,	Y_D:WORD,	TILE:WORD
 984 
 985 			push		bp
 986 			mov		bp,	sp		; Save Stack frame
 987 			push		ds di si
 988 
 989                cld
 990 
 991 		; Load DS.
 992 
 993 			ASSUME	ds:  @fardata
 994 			mov		ax,  @fardata
 995 			mov		ds,  ax			; Set DS to segment XTile data
 996 
 997 		; Set DI to start of rectangle on screen
 998 			mov 		ax,  [WLine_Offset]
 999 			mul		[Y_S]		   ; Find Y offset value. Place in AX
1000 
1001 			mov		di,  [X_S]        ; Find X offset value. Place in DI
1002 			shr		di,  1
1003 			shr		di,  1
1004 
1005 			add		di,  ax		   ; Add X and Y offsets
1006 			add		di,  [Write_Page] ; Add in page offset
1007 
1008 		; Set all data from latches
1009 			mov		dx,	GC_INDEX
1010 			mov		ax,	00000h + BIT_MASK  ; Set all latch writes
1011 			out		dx, 	ax
1012 
1013 		; Insure Map Mask is set to all planes
1014 			mov		ax,  0F02h	; 0F sets all planes. 02 is Map Mask
1015 			mov		dx,	SC_INDEX
1016 			out		dx,	ax
1017 
1018 		; Load CX with XBlocks per scan line
1019 			mov		cx,  [X_D]
1020 			shr		cx,  1		; Div by 4 so we have
1021 			shr		cx,  1         ; Xblock count
1022 
1023 		; Set AX to the distance from one scan line to next
1024 			mov		ax,		[WLine_Offset]
1025 			sub		ax,		cx
1026 
1027 		; Set SI to source
1028 			mov		si,		[TILE]
1029 
1030 		; Get the Screen Seg and put it in DS and ES
1031 			mov		dx,  SCREEN_SEG
1032 			mov		ds,  dx
1033 			mov		es,	dx
1034 
1035 		; Set DX to the number of scan lines
1036 			mov		dx,  	[Y_D]
1037 
1038 		; Save the CX in BP
1039 			mov		bp,		cx
1040 
1041 		; This section is for WRITES ------------------------------
1042 	@@Rowloop:
1043 
1044 		; Do the actual line.  REP MOVSB.
1045 			rep		movsb
1046 
1047 		; Adjust for next iteration
1048 			mov		cx,  bp	; Restore CX.
1049 			add		di,	ax	; Point DI to start of next line
1050 
1051 		; End of Rowloop.  Dec DX, if it is NOT 0 then do next line
1052 			dec		dx
1053 			jnz		@@Rowloop
1054 
1055 		; !!DONE!!
1056 			pop		si di ds             ; Return state
1057 			pop		bp
1058 			ret
1059 
1060 ENDP			_XPaste_Tile; 
1061 
1062 
1063 ;-------------------------- _XPaste_Sprite ------------------------------
1064 ; - This function will place a sprite from the display memory to current screen
1065 ; - It will NOT do masking
1066 public		_XPaste_Sprite
1067 
1068 PROC			_XPaste_Sprite   FAR
1069 
1070 
1071 	ARG	X_S:WORD,	Y_S:WORD, X_D:WORD,	Y_D:WORD,	TILE:WORD
1072 
1073 			push		bp
1074 			mov		bp,	sp		; Save Stack frame
1075 			push		ds di si
1076 
1077                cld
1078 
1079 		; Load DS.
1080 
1081 			ASSUME	ds:  @fardata
1082 			mov		ax,  @fardata
1083 			mov		ds,  ax			; Set DS to segment XTile data
1084 
1085 		; Set DI to start of rectangle on screen
1086 			mov 		ax,  [WLine_Offset]
1087 			mul		[Y_S]		   ; Find Y offset value. Place in AX
1088 
1089 			mov		di,  [X_S]        ; Find X offset value. Place in DI
1090 			shr		di,  1
1091 			shr		di,  1		
1092 
1093 			add		di,  ax		   ; Add X and Y offsets
1094 			add		di,  [Write_Page] ; Add in page offset
1095 
1096 		; Set SI to source
1097 			mov		si,		[TILE]
1098 
1099 		; Find adjustment to source for alignment
1100 			mov		ax,	[X_D]
1101 			mov		cx,	[X_S]
1102 
1103 			shr		ax,	1	   ; Number of XBlocks a line	
1104 			shr		ax,	1
1105 			mul		[Y_D]        ; Find size of each sprite alignment
1106 			
1107 			and		cx,	3	   ; Mask all but 2 LSBs
1108 			
1109 			mul		cx		   ; Find new offset				
1110 
1111 			add		si,	ax	   ; Adjust SI	
1112 
1113 		; Get the Screen Seg and put it in DS and ES
1114 			mov		ax,  SCREEN_SEG
1115 			mov		ds,  ax
1116 			mov		es,	ax
1117 
1118 		; Set all data from latches
1119 			mov		dx,	GC_INDEX
1120 			mov		ax,	00000h + BIT_MASK  ; Set all latch writes
1121 			out		dx, 	ax
1122 
1123 		; Insure Map Mask is set to all planes
1124 			mov		ax,  0F02h	; 0F sets all planes. 02 is Map Mask
1125 			mov		dx,	SC_INDEX
1126 			out		dx,	ax
1127 
1128 		; Load CX with XBlocks per scan line
1129 			mov		cx,  [X_D]
1130 			shr		cx,  1		; Div by 4 so we have
1131 			shr		cx,  1         ; Xblock count
1132 
1133 		; Set AX to the distance from one scan line to next
1134 			mov		ax,		[WLine_Offset]
1135 			sub		ax,		cx
1136 
1137 		; Set DX to the number of scan lines
1138 			mov		dx,  	[Y_D]
1139 
1140 		; Save CX in BP
1141 			mov		bp, 		cx
1142 
1143 		; This section is for WRITES ------------------------------
1144 	@@Rowloop:
1145 
1146 		; Do the actual line.  REP MOVSB.
1147 			rep		movsb
1148 
1149 		; Adjust for next iteration
1150 			mov		cx,  bp	; Restore CX.
1151 			add		di,	ax	; Point DI to start of next line
1152 
1153 		; End of Rowloop.  Dec DX, if it is NOT 0 then do next line
1154 			dec		dx
1155 			jnz		@@Rowloop
1156 
1157 		; !!DONE!!
1158 			pop		si di ds             ; Return state
1159 			pop		bp
1160 			ret
1161 
1162 ENDP			_XPaste_Sprite
1163 
1164 
1165 ; --------------------------- _XPut_Tile_M -------------------------------
1166 ; - This function will place a tile on the current write screen
1167 ; - It will be done a plane at a time and will expect the image data
1168 ; - to be laid out one plane at a time.
1169 ; - All 0 pixels will leave the screen intact.
1170 ; -
1171 public		_XPut_Tile_M
1172 
1173 PROC			_XPut_Tile_M   FAR
1174 
1175 	ARG	X_S:WORD,	Y_S:WORD, X_D:WORD,	Y_D:WORD,	IMAGE_OFF:DWORD
1176 
1177 			push		bp
1178 			mov		bp,	sp			; Save Stack frame
1179 			push		ds di si
1180 
1181 			cld
1182 
1183 		; Get the Screen Seg and put it in es
1184 			mov		ax,  SCREEN_SEG
1185 			mov		es,  ax
1186 
1187 
1188 		; Load CX with the number of XBlocks per scan line
1189 			mov		cx,	[X_D]
1190 			shr		cx,	1
1191 			shr		cx,	1         ; Divide by 4 to get
1192 
1193 		; Set [X_D] to the distance from one scan line to next
1194 			mov		ax,		[WLine_Offset]
1195 			sub		ax,		cx
1196 			mov		[X_D],	ax
1197 
1198 		; Save number of XBlocks a line in upper cx
1199 			mov		ch,		cl
1200 
1201 		; Set BL to the number of scan lines and save
1202 			mov		bx,  	[Y_D]
1203 
1204 		; Load DS.
1205 			ASSUME	ds:  @fardata
1206 			mov		ax,  @fardata
1207 			mov		ds,  ax			; Set DS to fardata segment
1208 
1209 		; Load di with destination offset and save it in DEST
1210 			mov		ax,		[WLine_Offset]
1211 			mul		[Y_S]
1212 
1213 			mov		di,	[X_S]
1214 			shr		di,  1
1215 			shr		di,	1             ; Adjust to number of XBlocks
1216 
1217 			add       di,	[Write_Page]
1218 			add		di,	ax            ; Di is now loaded
1219 
1220 			mov       [X_S],	di       ; Store it
1221 
1222 		; Load ds:si with source
1223 			lds		si,	[IMAGE_OFF]
1224 
1225 		; Set all data from CPU and non from latches
1226 			mov		dx,	GC_INDEX
1227 			mov		ax,	0FF00h + BIT_MASK  ; Set all CPU writes
1228 			out		dx, 	ax
1229 
1230 		; Set up DX and AX for plane selection
1231 			mov		al,	02h	; Plane 0 selected
1232 			mov		dx,	SC_INDEX
1233 			inc		dx
1234 			mov		ax,	0101h	; Set up AX
1235 
1236 		; This section is for the WRITE ------------------------------
1237 	@@PlanesB:          ; Master plane loop.
1238 
1239 			out		dx,	al   ; Set the plane
1240 	@@RowloopB:         	; Scan line line
1241 
1242 		; Do the actual line.
1243 	@@PixelLoop:
1244 			lodsb				; Get the pixel
1245 			or		al,	al		; Is it zero
1246 			jz		@@NoDraw       ; If zero, don't draw it
1247 			mov		[es:di],	al	; Else, do draw it
1248 
1249 	@@NoDraw:
1250 			inc		si             ; Move to next pixel
1251 			inc		di
1252 			dec       cl
1253 			jnz		@@PixelLoop
1254 
1255 		; Adjust for next iteration
1256 			mov		cl,  ch		; Restore CL. ( [Pix/line]/4 )
1257 			add		di,	[X_D]	; Point DI to start of next line
1258 
1259 		; !!End of Rowloop.  Dec SI, if it is NOT 0 then do next line
1260 			dec		bx
1261 			jnz		@@RowloopB
1262 
1263 		; Done with plane.  Reset Destination pointers.  Adjst plane
1264 			mov		di,	[X_S]     ; Restore destination
1265 			mov		bx,	[Y_D]	; Restore scan line count
1266 			shl		ah,	1		; Adjust plane
1267 			mov		ah,  al		; Save the
1268 			jnc		@@PlanesB      ; If no carry, then more planes
1269 
1270 		; !!!DONE
1271 			pop		si di ds             ; Return state
1272 			ret
1273 
1274 ENDP			_XPut_Tile_M
1275 
1276 
1277 ; --------------------------- _XMove_Tile ----------------------------------
1278 ; - This function will move a tile about on the current write page
1279 ; - Coord, Size, and destination must be givin
1280 public		_XMove_Tile
1281 
1282 PROC			_XMove_Tile   FAR
1283 
1284   ARG  X_S:WORD, Y_S:WORD, X_E:WORD, Y_E:WORD, X_D:WORD, Y_D:WORD
1285 
1286 			push		bp
1287 			mov		bp,	sp		; Save Stack frame
1288 			push		ds si di
1289 
1290 			cld
1291 
1292 		; Load DS.
1293 			ASSUME	ds:  @fardata
1294 			mov		ax,  @fardata
1295 			mov		ds,  ax			; Set DS to fardata segment
1296 
1297 		; Load si with source X in XBlocks
1298 			mov		si,	[X_S]
1299 			shr		si,  1
1300 			shr		si,  1
1301 
1302 		; Load di with destination X in XBlocks
1303 			mov		di,	[X_D]
1304 			shr		di,  1
1305 			shr		di,  1
1306 
1307 		; Convert [X_E] to width in XBlocks
1308 			mov		bx,  [X_E]
1309 			shr		bx,  1
1310 			shr		bx,  1
1311 
1312 			mov		ax,     bx	; Save in AX
1313 			mov		[X_E],  bx	; Put back
1314 
1315 		; Determine the X direction
1316 			cmp		si,     di
1317 			jge		@@GoLeft
1318 
1319 		; Going right.  Copy right to left
1320 			add		si,	   ax	; Source starts at right edge
1321 			add		di,	   ax	; Same with destination
1322 			neg		bx			; Make negative
1323 			std					; Move backwards on string instructions
1324 
1325 		; Determine the Y direction
1326 	@@GoLeft:
1327 			mov		cx,  [WLine_Offset]
1328 			mov		ax,  [Y_S]     ; Get the Y source start
1329 			mov		dx,  [Y_D]	; Get the Y destination
1330 
1331 			cmp		ax,	dx		; Going up or down
1332 			jge       @@GoUp
1333 
1334 		; Rectangle going down.  Copy bottom to top
1335 			mov		ax,  [Y_E]	; Get the bottom coord
1336 			add		dx,	ax		; Add it to the destination, so
1337 								; it points to end of destination blk
1338 			neg		cx			; Make CX negative
1339 			add		ax,	[Y_S]	; Point AX to end of source blk
1340 								; By adding size to start
1341 
1342 		; Calcuate the offsets
1343 	@@GoUp:
1344 			push		dx			; Save DX the torment of a multiply
1345 			mul		[WLine_Offset]	; Find Y adder for source
1346 			add		si,	ax		; Add it
1347 
1348 			pop		ax			; Pop off the destination Y into AX
1349 			mul		[WLine_Offset]	; Find Y adder for destination
1350 			add		di,	ax		; Add it
1351 
1352 			sub		cx, 	bx		; Find the scan line data
1353 
1354 		; Add in the write page offset
1355 			add		si,	[Write_Page]
1356 			add		di,	[Write_Page]
1357 
1358 		; Get the Screen Seg and put it in DS and ES
1359 			mov		ax,  SCREEN_SEG
1360 			mov		ds,  ax
1361 			mov		es,	ax
1362 
1363 		; Set all data from latches
1364 			mov		dx,	GC_INDEX
1365 			mov		ax,	00000h + BIT_MASK  ; Set all latch writes
1366 			out		dx, 	ax
1367 
1368 		; Insure Map Mask is set to all planes
1369 			mov		ax,  0F02h	; 0F sets all planes. 02 is Map Mask
1370 			mov		dx,	SC_INDEX
1371 			out		dx,	ax
1372 
1373 		; Set AX to the Scan line lenghth
1374 			mov		ax,	[X_E]
1375 
1376 		; Set BX to the Y size
1377 			mov		bx,	[Y_E]
1378 
1379 		; Set DX to the Scan line differential
1380 			mov		dx,  cx
1381 
1382 	  ; Do the WRITES---------------------
1383 	@@ScanLoop:
1384 
1385 			mov	    	cx,  ax	; Set cx to the Scan size
1386 			rep 		movsb	; Do the line
1387 
1388 		; Add the scan line differential to source and dest
1389 			add		si,	dx
1390 			add		di,	dx
1391 
1392 		; See if done with all lines
1393 			dec		bx
1394 			jnz		@@ScanLoop	; No, then go and do another line
1395 
1396 		; !!DONE!!
1397 			pop		di si ds
1398 			pop		bp			; Return state
1399 			ret
1400 
1401 ENDP			_XMove_Tile
1402 
1403 
1404 ; --------------------------- _XRegister_Font8 ------------------------------
1405 ; - This function will register a 8-font.
1406 ; - The function will return in AX the actual number of bytes used.
1407 ; - The function expects each character to be laid out as for Upload_Tile,
1408 ; - one character at a time.  Each character is 8x by 10y.
1409 
1410 public		_XRegister_Font8
1411 
1412 PROC			_XRegister_Font8   FAR
1413 
1414 	ARG 	  DEST:WORD, NUMBER:WORD, BASE:WORD, UPLOAD:WORD, FONT_OFF:DWORD
1415 
1416 			push		bp
1417 			mov		bp,	sp			; Save Stack frame
1418 			push		ds di si
1419 
1420 			cld
1421 
1422 		; Load DS.
1423 			ASSUME	ds:  @fardata
1424 			mov		ax,  @fardata
1425 			mov		ds,  ax			; Set DS to fardata segment
1426 
1427 		; Save the base char
1428 			mov		ax,			[BASE]
1429 			mov		[Char_Base8],	ax
1430 
1431 		; Will we upload this font?
1432 			mov		cx,	[UPLOAD]
1433 			mov		[UpLoaded8], cx	; Flag it	( 0 is uploaded )
1434 			jcxz		@@UploadFont		; Yes!, then jump to it
1435 
1436 		; Don't upload this font.  Just register and return.
1437 			les		si,			  [FONT_OFF]
1438 			mov		[Font_SiteD8],   si
1439 			mov		ax,			  es
1440 			mov		[Font_SiteD8+2], ax
1441 			jmp       @@DONE
1442 
1443 	@@UploadFont:
1444 		; Check font size to insure no overrun
1445 			mov		dx,	20
1446 			mov		ax,	[NUMBER]
1447 			mul		dx		  	; Mul number of chars by 20bytes
1448 			add		ax,  [DEST]	; Add destination to get proposed end
1449 			cmp		ax,	STORE	; Where is it in relation to begin
1450 			ja		@@CONT		; If above, no wrap of AX, OK
1451 			mov		ax,	0		; Else leave 0 in AX, indicating ERR
1452 			jmp		@@DONE		; And jump out
1453 
1454 	@@CONT:
1455 		; Save the size and location
1456 			mov		ax,            [DEST]
1457 			mov		[Font_SiteU8],	ax
1458 
1459 		; Load di with destination offset and save it in DX
1460 			mov		di,		ax	    ; AX retains it from prev action
1461 			mov       dx,       ax       ; Store it
1462 
1463 		; Load ds:si with source
1464 			lds		si,  [FONT_OFF]
1465 
1466 		; Load es with SCREEN SEG
1467 			mov		ax,  SCREEN_SEG
1468 			mov		es,	ax
1469 
1470 		; This section iterates for each char----------------------------
1471 			mov		bx,	[NUMBER]	; Set BL to number of characters
1472 
1473 		; Set BP to destination, as was in DX
1474 			mov		bp,  dx
1475 
1476 		; Set all data from CPU and non from latches
1477 			mov		dx,	GC_INDEX
1478 			mov		ax,	0FF00h + BIT_MASK  ; Set all CPU writes
1479 			out		dx, 	ax
1480 
1481 		; Set up DX plane selection
1482 			mov		dx,	SC_INDEX
1483 
1484 		; Set CX to number of scan lines in a char
1485 			mov		cx,	10        ; Set CX to 10 scan lines
1486 
1487 	@@BeginWrite:
1488 
1489 		; Set AX up for plane selection
1490 			mov		ax,	1102h	; Plane 0 selected
1491 
1492 		; This section loops through the planes for each char -----------
1493 	@@PlanesW:       			; Master plane loop.
1494 
1495 			out	     dx,	ax	; Set the plane
1496 
1497 		; Do the actual line.  REP MOVSW.  Move both XBlocks on each line
1498 			rep		movsw
1499 
1500 	  ; Done with plane.  Reset Destination pointers.  Adjst plane
1501 			mov		di,	bp
1502 			shl		ah,	1		; Adjust plane. Carry set if done
1503 			mov		cx,  10	     ; Restore CX.
1504 
1505 		; !!End of Plane loop.
1506 			jnc		@@PlanesW      ; If no carry, not done with char
1507 
1508 		; !!End of Char loop.
1509 
1510 			add		bp,	20		; Adjust destination for next char
1511 			mov		di,	bp		; Store it in DI
1512 
1513 			dec		bx             ; Another char done
1514 			jnz		@@BeginWrite   ; If not zero, not done with font set
1515 
1516 		; !!DONE!!
1517 		@@DONE:
1518 			pop		si di ds            ; Return state
1519 			pop		bp
1520 			ret
1521 
1522 ENDP			_XRegister_Font8
1523 
1524 
1525 ; ----------------------------- _XChar8 ----------------------------------
1526 ; - This function will place a char from the current font to current screen
1527 ; - Uses the 8pix font
1528 public		_XChar8
1529 
1530 PROC			_XChar8   FAR
1531 
1532 	ARG	X_S:WORD,	Y_S:WORD, CHAR:WORD
1533 
1534 			push		bp
1535 			mov		bp,	sp		; Save Stack frame
1536 			push		ds di si
1537 
1538 			cld
1539 
1540 		; Load DS.
1541 			ASSUME	ds:  @fardata
1542 			mov		ax,  @fardata
1543 			mov		ds,  ax			; Set DS to segment w/ Table
1544 
1545 		; Set DI to start of character on screen
1546 			mov 		ax,  [WLine_Offset]
1547 			mul		[Y_S]		   ; Find Y offset value. Place in AX
1548 
1549 			mov		di,  [X_S]        ; Find X offset value. Place in DI
1550 			shr		di,  1
1551 			shr		di,  1		   ; Adjust to number of XBlocks
1552 
1553 			add		di,  ax		   ; Add X and Y offsets
1554 			add		di,  [Write_Page] ; Add in page offset
1555 
1556 		; Is the font uploaded or not
1557 			mov		ax,	[UpLoaded8]
1558 			cmp		ax,	UPLOADFONT
1559 			je		@@FontIsUploaded	; The font is uploaded
1560 
1561 	  ; - Font is not uploaded
1562 		; Set CX to the scan line differential
1563 			mov		cx,  [WLine_Offset]
1564 			sub		cx,  2			; Subtract the XBlocks of a char
1565 
1566 		; Figure character offset and add to load ds:si font site
1567 			mov		ax,	80			; Put font size in ax
1568 			xor		bx,	bx			; Clear bx
1569 			mov		bx,	[CHAR]         ; Put character place in BX
1570 			sub		bx,	[Char_Base8]	; Subtract base char
1571 			mul		bx				; Mul size by place
1572 			lds		si,  [Font_Addr8]
1573 			add		si,  ax
1574 
1575 		; Move the scan line differential from CX to BP
1576 			mov		bp,  cx
1577 
1578 		; Save the base destination in CX
1579 			mov		cx,  di
1580 
1581 		; Get the Screen Seg and put it in ES
1582 			mov		ax,  SCREEN_SEG
1583 			mov		es,	ax
1584 
1585 		; Set all data from CPU and non from latches
1586 			mov		dx,	GC_INDEX
1587 			mov		ax,	0FF00h + BIT_MASK  ; Set all CPU writes
1588 			out		dx, 	ax
1589 
1590 		; Set up DX and AX for plane selection
1591 			mov		ax,	1102h	; Plane 0 selected
1592 			mov		dx,	SC_INDEX
1593 
1594 		; This section is for WRITES ------------------------------
1595 
1596 		; Set BH to number of lines to do
1597 			mov       bx,  10		; 10 scan lines per 8-pix font
1598 
1599 	@@PlanesW:          ; Master plane loop.
1600 
1601 			out		dx,	ax	; Set the plane
1602 
1603 	@@RowloopW:         	; Scan line loop
1604 
1605 		; Do the actual line.  MOVSW.
1606 			movsw
1607 
1608 		; Adjust for next iteration
1609 			add		di,	bp		; Point DI to start of next line
1610 
1611 		; !!End of Rowloop.  Dec BH, if it is NOT 0 then do next line
1612 			dec		bx
1613 			jnz		@@RowloopW
1614 
1615 		; Done with plane.  Reset Destination pointers.  Adjst plane
1616 			mov		di,	cx		; Restore the destination start
1617 			mov		bx,	10		; Restore scan line count
1618 			shl		ah,	1		; Adjust plane
1619 
1620 		; !!End of Plane loop.
1621 			jnc		@@PlanesW		; If no carry, then more to do.
1622 
1623 
1624 
1625 		; Done with this
1626 			jmp		@@DONE
1627 
1628 
1629 	  ; - Font is uploaded
1630 	  @@FontIsUploaded:
1631 		; Calc the source and put in SI
1632 			mov		si,	[Font_SiteU8]	; Get base location
1633 			mov		ax,	20			; Put font size in ax (in XBlock)
1634 			mov		bx,	[CHAR]         ; Put character place in BX
1635 			sub		bx,	[Char_Base8]	; Subtract base char
1636 			mul		bx				; Mul size by place
1637 			add		si,	ax			; Put in SI
1638 
1639 		; Insure Map Mask is set to all planes
1640 			mov		ax,  0F02h	; 0F sets all planes. 02 is Map Mask
1641 			mov		dx,	SC_INDEX
1642 			out		dx,	ax
1643 
1644 		; Set all data from latches
1645 			mov		dx,	GC_INDEX
1646 			mov		ax,	00000h + BIT_MASK  ; Set all latch writes
1647 			out		dx, 	ax
1648 
1649 		; Set AX to line dif.
1650 			mov		ax,	[WLine_Offset]		; Page width
1651 			sub	     ax,  2                   ; minus XBlocks per char
1652 
1653 		; Get the Screen Seg and put it in DS and ES
1654 			mov		dx,  SCREEN_SEG
1655 			mov		ds,  dx
1656 			mov		es,	dx
1657 
1658 		; Set CX to the number of scan lines
1659 			mov		cx,		10
1660 
1661 		; This section is for WRITES ------------------------------
1662 	@@Rowloop:
1663 
1664 		; Do the actual line.  MOVSB.
1665 					movsb
1666 					movsb
1667 
1668 		; Adjust for next iteration
1669 			add		di,	ax	; Point DI to start of next line
1670 
1671 		; End of Rowloop.
1672 			loop		@@Rowloop
1673 
1674 		; !!DONE!!
1675 	@@DONE:
1676 			pop		si di ds             ; Return state
1677 			pop		bp
1678 			ret
1679 
1680 ENDP			_XChar8;
1681 
1682 
1683 ; ------------------------ _Register_Font_Masks8 ---------------------------
1684 ; - This function registers a font mask for the current 8pix font
1685 ; - This mask can be used for MFont character drawing
1686 public		_Register_Font_Masks8
1687 
1688 PROC			_Register_Font_Masks8   FAR
1689 
1690   	ARG	MASK_OFF:WORD, MASK_SEG:WORD  
1691 
1692 			push		bp
1693 			mov		bp,	sp		; Save Stack frame
1694 			push		ds
1695 
1696 		; Load DS.
1697  			ASSUME	ds:  @fardata
1698 			mov		ax,  @fardata
1699 			mov		ds,  ax			; Set DS to fardata segment 
1700 
1701 		; Move location to local
1702 			mov		ax,			[MASK_OFF]
1703 			mov       [Font_Mask_O8], ax
1704 
1705 			mov		ax,			[MASK_SEG]
1706 			mov       [Font_Mask_S8], ax
1707 
1708 		; !!DONE!!
1709 			pop		ds
1710 			pop		bp			; Return state
1711 			ret
1712 
1713 ENDP			_Register_Font_Masks8
1714 
1715 
1716 ; ----------------------------- _XChar8_M ----------------------------------
1717 ; - This function will place a char from the current font to current screen
1718 ; - This function requires a font mask set to be registered.
1719 ; - Uses the 8pix font
1720 public		_XChar8_M
1721 
1722 PROC			_XChar8_M   FAR
1723 
1724 	ARG	X_S:WORD,	Y_S:WORD, CHAR:WORD
1725 
1726 
1727 			push		bp
1728 			mov		bp,	sp			; Save Stack frame
1729 			push		ds di si
1730 
1731 			cld
1732 
1733 		; Load DS.
1734 			ASSUME	ds:  @fardata
1735 			mov		ax,  @fardata
1736 			mov		ds,  ax			; Set DS to fardata segment
1737 
1738 		; Set DI to start of rectangle on screen
1739 			mov 		ax,  [WLine_Offset]
1740 			mov		bx,	ax		   ; Save in BX for later
1741 			mul		[Y_S]		   ; Find Y offset value. Place in AX
1742 
1743 			mov		di,  [X_S]        ; Find X offset value. Place in DI
1744 			shr		di,  1
1745 			shr		di,  1
1746 
1747 			add		di,  ax		   ; Add X and Y offsets
1748 			add		di,  [Write_Page] ; Add in page offset
1749 
1750 		; Is the font uploaded or not
1751 			mov		cx,	[UpLoaded8]  ; UPLOADED is 0!
1752 			jcxz		@@Uploaded	   ; The font is uploaded
1753 
1754 	  ; - Font is not uploaded
1755 
1756 		; Figure character offset and add to load ds:si font site
1757 			mov		ax,	80			; Put font size in ax
1758 			mov		cx,	[CHAR]         ; Put character place in BX
1759 			sub		cx,	[Char_Base8]	; Subtract base char
1760 			mul		cx				; Mul size by place
1761 			lds		si,  [Font_Addr8]
1762 			add		si,  ax
1763 
1764 		; Set BX to the line differential
1765 			dec		bx			; BX was set above - first XBlock
1766 
1767 		; Save the base destination in BP
1768 			mov		bp,  di
1769 
1770 		; Get the Screen Seg and put it in ES
1771 			mov		ax,  SCREEN_SEG
1772 			mov		es,	ax
1773 
1774 		; Set all data from CPU and non from latches
1775 			mov		dx,	GC_INDEX
1776 			mov		ax,	0FF00h + BIT_MASK  ; Set all CPU writes
1777 			out		dx, 	ax
1778 
1779 		; Set up DX and AX for plane selection
1780 			mov		ax,	0102h	; Plane 0 selected
1781 			mov		dx,	SC_INDEX
1782 
1783 		; This section is for WORD WRITES ------------------------------
1784 
1785 		; Set CX to number of lines to do
1786 			mov       cx,  10		; 10 scan lines per 8-pix font
1787 
1788 	@@PlanesW:          ; Master plane loop.
1789 
1790 			out		dx,	ax	; Set the plane
1791 
1792 	@@RowloopW:         	; Scan line loop
1793 
1794 		; Do the actual DRAW.  MOV.
1795 			lodsb	; Get the pixel
1796 			or		al,	al		; Is it zero
1797 			jz		@@NoDraw1       ; If zero, don't draw it
1798 			mov		[es:di],	al	; Else, do draw it
1799 
1800 	@@NoDraw1:
1801 			inc		di
1802 
1803 			lodsb				; Get the pixel
1804 			or		al,	al		; Is it zero
1805 			jz		@@NoDraw2      ; If zero, don't draw it
1806 			mov		[es:di],	al	; Else, do draw it
1807 
1808 	@@NoDraw2:
1809 		; Adjust for next iteration
1810 			add		di,	bx		; Point DI to start of next line
1811 
1812 		; !!End of Rowloop.  Dec CX, if it is NOT 0 then do next line
1813 			loop		@@RowloopW
1814 
1815 		; Done with plane.  Reset Destination pointers.  Adjst plane
1816 			mov		di,	bp		; Restore the destination start
1817 			mov		cx,	10		; Restore scan line count
1818 
1819 			mov		al,  02h		; Restore MAP MASK pointer
1820 			shl		ah,	1		; Adjust plane
1821 
1822 		; !!End of Plane loop. If carry not set, then not done
1823 			jnc		@@PlanesW
1824 
1825 		; Done with this
1826 			jmp		@@DONE
1827 
1828 
1829 	@@Uploaded:
1830 	  ; - Font is uploaded
1831 		; Set SI to mask offset
1832 			mov		ax,	10			; Put mask size in ax
1833 			mov		cx,	[CHAR]         ; Put character place in CX
1834 			sub		cx,	[Char_Base8]	; Subtract base char
1835 			mul		cx				; Mul size by place
1836 			add		ax,	[Font_Mask_O8] ; Find masks offset in mask set
1837 			mov		si,	ax			; Save it
1838 
1839 		; Calc the source and put in BX
1840 			mov		bx,	[Font_SiteU8]	; Get base location
1841 			mov		ax,	20			; Put font size in ax
1842 			mov		cx,	[CHAR]         ; Put character place in BX
1843 			sub		cx,	[Char_Base8]	; Subtract base char
1844 			mul		cx				; Mul size by place
1845 			add		bx,	ax			; Put in SI
1846 
1847 		; Set BP to the scan line differential
1848 			mov		bp,	[WLine_Offset]
1849 			dec		bp
1850 
1851 		; Set DS to mask area
1852 			mov		ax,	[Font_Mask_S8]
1853 			mov 		ds,	ax
1854 
1855 		; Get the Screen Seg and put it in ES
1856 			mov		ax,  SCREEN_SEG
1857 			mov		es,	ax
1858 
1859 		; Set all data from latches
1860 			mov		dx,	GC_INDEX
1861 			mov		ax,	00000h + BIT_MASK  ; Set all latch writes
1862 			out		dx, 	ax
1863 
1864 		; Set up Map Mask
1865 			mov		al,  02h	; 02 is Map Mask
1866 			mov		dx,	SC_INDEX
1867 			out		dx,	al
1868 			inc		dx
1869 
1870 		; Set CH to the number of scan lines
1871 			mov		ch,	10
1872 
1873 		; Set CL to shift spaces
1874 			mov		cl,	4
1875 
1876 		; This section is for WRITES ------------------------------
1877 	@@Rowloop:
1878 		; This section prep the Map Mask
1879 			lodsb				; Get mask byte
1880 
1881 		; Set mask for first write
1882 			out		dx,	al		; Set map mask
1883 
1884 		; Write the first byte
1885 			mov		ah,		[es:bx]
1886 			mov		[es:di],	ah
1887 
1888 		; Adjust di, bx
1889 			inc		di
1890 			inc		bx
1891 
1892 		; Set mask for second write
1893 			shr		al,       cl		; Move upper nibble down
1894 			out		dx,		al        ; Set map mask
1895 
1896 		; Write the second byte
1897 			mov		ah,		[es:bx]
1898 			mov		[es:di],	ah
1899 
1900 		; Adjust bx
1901 			inc		bx
1902 
1903 		; Adjust for next iteration
1904 			add		di,	bp	; Point DI to start of next line
1905 
1906 		; End of Rowloop.
1907 			dec		ch
1908 			jnz		@@Rowloop
1909 
1910 		; !!DONE!!
1911 	@@DONE:
1912 			pop		si di ds             ; Return state
1913 			pop		bp
1914 			ret
1915 
1916 ENDP			_XChar8_M;
1917 
1918 
1919 ;----------------------------- _XString8 ----------------------------------
1920 ; - This function will place a char from the current font to current screen
1921 ; - It will use the masked font on mask flag set to not 0.
1922 public		_XString8
1923 
1924 PROC			_XString8   FAR
1925 
1926 	ARG	X_S:WORD,	Y_S:WORD, MASKIT:WORD, STR_OFF:DWORD
1927 
1928 			push		bp
1929 			mov		bp,	sp		; Save Stack frame
1930 			push		ds di si
1931 
1932 		; Load DS.
1933 			ASSUME	ds:  @fardata
1934 			mov		ax,  @fardata
1935 			mov		ds,  ax			; Set DS to segment w/ Table
1936 
1937 		; Move flag into CX
1938 			mov		cx,  [MASKIT]
1939 
1940 		; Load DS:SI
1941 			lds		si,  [STR_OFF]
1942 
1943 		; !!! This is the master string loop
1944 	@@STRING:
1945 			xor       ax,	ax
1946 			mov	  	al,	[ds:si]		; Get the char
1947 			cmp		al,	0			; Is it the EOS
1948 			je		@@DONE			; If so jump
1949 
1950 		 ; Save cx
1951 			push 	cx
1952 
1953 		 ; Build stack frame
1954 			push		ax				; Push the char
1955 			push		[Y_S]			; Push the Y coor
1956 			push		[X_S]			; Push the X coor
1957 		 ; To mask or not to mask
1958 			jcxz		@@DontMask		; If Flag = 0, dont mask
1959 			call		_XChar8_M			; Put the masked char
1960 			jmp		@@Continue
1961 
1962 	@@DontMask:
1963 			call      _XChar8			; Don't mask
1964 
1965 	@@Continue:
1966 			add		sp,	6			; Adjust the stack
1967 
1968 			pop		cx				; Restore cx
1969 
1970 			add		[X_S],	8		; Move the cursor
1971 			inc		si				; Point to next char
1972 			jmp		@@STRING            ; Continue
1973 
1974 		; !!DONE!!
1975 	@@DONE:
1976 			pop		si di ds             ; Return state
1977 			pop		bp
1978 			ret
1979 
1980 ENDP			_XString8
1981 
1982 
1983 ; --------------------------- _XRegister_Font4 ------------------------------
1984 ; - This function will register a 4-font.
1985 ; - The function will return in AX the actual number of bytes used.
1986 ; - The function expects each character to be laid out as for Upload_Tile,
1987 ; - one character at a time.  Each character is 4x by 6y.
1988 
1989 public		_XRegister_Font4
1990 
1991 PROC			_XRegister_Font4   FAR
1992 
1993 	ARG 	  DEST:WORD, NUMBER:WORD, BASE:WORD, UPLOAD:WORD, FONT_OFF:DWORD
1994 
1995 			push		bp
1996 			mov		bp,	sp			; Save Stack frame
1997 			push		ds di si
1998 
1999 			cld
2000 
2001 		; Load DS.
2002 			ASSUME	ds:  @fardata
2003 			mov		ax,  @fardata
2004 			mov		ds,  ax			; Set DS to fardata segment
2005 
2006 		; Save the base char
2007 			mov		ax,			[BASE]
2008 			mov		[Char_Base4],	ax
2009 
2010 		; Will we upload this font?
2011 			mov		cx,	[UPLOAD]
2012 			mov		[UpLoaded4], cx	; Flag it	( 0 is uploaded )
2013 			jcxz		@@UploadFont		; Yes!, then jump to it
2014 
2015 		; Don't upload this font.  Just register and return.
2016 			les		si,			  [FONT_OFF]
2017 			mov		[Font_SiteD4],   si
2018 			mov		ax,			  es
2019 			mov		[Font_SiteD4+2], ax
2020 			jmp       @@DONE
2021 
2022 	@@UploadFont:
2023 		; Check font size to insure no overrun
2024 			mov		dx,	6
2025 			mov		ax,	[NUMBER]
2026 			mul		dx		  	; Mul number of chars by 20bytes
2027 			add		ax,  [DEST]	; Add destination to get proposed end
2028 			cmp		ax,	STORE	; Where is it in relation to begin
2029 			ja		@@CONT		; If above, no wrap of AX, OK
2030 			mov		ax,	0		; Else leave 0 in AX, indicating ERR
2031 			jmp		@@DONE		; And jump out
2032 
2033 	@@CONT:
2034 		; Save the size and location
2035 			mov		ax,            [DEST]
2036 			mov		[Font_SiteU4],	ax
2037 
2038 		; Load di with destination offset and save it in DX
2039 			mov		di,		ax	    ; AX retains it from prev action
2040 			mov       dx,		di       ; Store it
2041 
2042 		; Load ds:si with source
2043 			lds		si,  [FONT_OFF]
2044 
2045 		; Load es with SCREEN SEG
2046 			mov		ax,  SCREEN_SEG
2047 			mov		es,	ax
2048 
2049 		; This section iterates for each char----------------------------
2050 			mov		bx,	[NUMBER]	; Set BX to number of characters
2051 
2052 		; Set BP to destination
2053 			mov		bp,  dx        ; From above.
2054 
2055 		; Set all data from CPU and non from latches
2056 			mov		dx,	GC_INDEX
2057 			mov		ax,	0FF00h + BIT_MASK  ; Set all CPU writes
2058 			out		dx, 	ax
2059 
2060 		; Set up DX plane selection
2061 			mov		dx,	SC_INDEX
2062 
2063 	@@BeginWrite:
2064 
2065 		; Set AX up for plane selection
2066 			mov		ax,	1102h	; Plane 0 selected
2067 
2068 		; This section loops through the planes for each char -----------
2069 	@@PlanesB:       			; Master plane loop.
2070 
2071 			out	     dx,	ax	; Set the plane
2072 
2073 		; Do the actual write.  MOVSB.  Move 6 single XBlocks on each line
2074 			movsb  ; 1
2075 			movsb  ; 2
2076 			movsb  ; 3
2077 			movsb  ; 4
2078 			movsb  ; 5
2079 			movsb  ; 6
2080 
2081 	@@EndPlane:
2082 		; Done with plane.  Reset Destination pointers.  Adjst plane
2083 			mov		di,	bp
2084 			shl		ah,	1		; Adjust plane. Carry set if done
2085 
2086 		; !!End of Plane loop.
2087 			jnc		@@PlanesB      ; If no carry, not done with char
2088 
2089 		; !!End of Char loop.
2090 
2091 			add		bp,	6		; Adjust destination for next char
2092 			mov		di,	bp		; Store it in DI
2093 
2094 			dec		bx             ; Another char done
2095 			jnz		@@BeginWrite   ; If not zero, not done with font set
2096 
2097 		; !!DONE!!
2098 		@@DONE:
2099 			pop		si di ds            ; Return state
2100 			pop		bp
2101 			ret
2102 
2103 ENDP			_XRegister_Font4
2104 
2105 
2106 ; ----------------------------- _XChar4 ----------------------------------
2107 ; - This function will place a char from the current font to current screen
2108 ; - Uses the 8pix font
2109 public		_XChar4
2110 
2111 PROC			_XChar4   FAR
2112 
2113 	ARG	X_S:WORD,	Y_S:WORD, CHAR:WORD
2114 
2115 			push		bp
2116 			mov		bp,	sp		; Save Stack frame
2117 			push		ds di si
2118 
2119 			cld
2120 
2121 		; Load DS.
2122 			ASSUME	ds:  @fardata
2123 			mov		ax,  @fardata
2124 			mov		ds,  ax			; Set DS to segment w/ Table
2125 
2126 		; Set DI to start of character on screen
2127 			mov 		ax,  [WLine_Offset]
2128 			mul		[Y_S]		   ; Find Y offset value. Place in AX
2129 
2130 			mov		di,  [X_S]        ; Find X offset value. Place in DI
2131 			shr		di,  1
2132 			shr		di,  1		   ; Adjust to number of XBlocks
2133 
2134 			add		di,  ax		   ; Add X and Y offsets
2135 			add		di,  [Write_Page] ; Add in page offset
2136 
2137 		; Is the font uploaded or not
2138 			mov		ax,	[UpLoaded4]
2139 			cmp		ax,	UPLOADFONT
2140 			je		@@FontIsUploaded	; The font is uploaded
2141 
2142 	  ; - Font is not uploaded
2143 		; Set CX to the scan line differential
2144 			mov		cx,  [WLine_Offset]
2145 			dec		cx			; Subtract the XBlock of a char
2146 
2147 		; Figure character offset and add to load ds:si font site
2148 			mov		ax,	24			; Put font size in ax
2149 			mov		bx,	[CHAR]         ; Put character place in BX
2150 			sub		bx,	[Char_Base4]	; Subtract base char
2151 			mul		bx				; Mul size by place
2152 			lds		si,  [Font_Addr4]
2153 			add		si,  ax
2154 
2155 		; Save the base destination in BX
2156 			mov		bx,  di
2157 
2158 		; Get the Screen Seg and put it in ES
2159 			mov		ax,  SCREEN_SEG
2160 			mov		es,	ax
2161 
2162 		; Set all data from CPU and non from latches
2163 			mov		dx,	GC_INDEX
2164 			mov		ax,	0FF00h + BIT_MASK  ; Set all CPU writes
2165 			out		dx, 	ax
2166 
2167 		; Set up DX and AX for plane selection
2168 			mov		ax,	1102h	; Plane 0 selected
2169 			mov		dx,	SC_INDEX
2170 
2171 		; This section is for WRITES ------------------------------
2172 
2173 	@@PlanesW:          ; Master plane loop.
2174 
2175 			out		dx,	ax	; Set the plane
2176 
2177 	; Put a plane.  Completely un-rolled
2178 
2179 		; Do line # 1
2180 			movsb
2181 			add		di,	cx		; Point DI to start of next line
2182 
2183 		; Do line # 2
2184 			movsb
2185 			add		di,	cx		; Point DI to start of next line
2186 
2187 		; Do line # 3
2188 			movsb
2189 			add		di,	cx		; Point DI to start of next line
2190 
2191 		; Do line # 4
2192 			movsb
2193 			add		di,	cx		; Point DI to start of next line
2194 
2195 		; Do line # 5
2196 			movsb
2197 			add		di,	cx		; Point DI to start of next line
2198 
2199 		; Do line # 6
2200 			movsb
2201 
2202 
2203 		; Done with plane.  Reset Destination pointers.  Adjst plane
2204 			mov		di,	bx		; Restore the destination start
2205 			shl		ah,	1		; Adjust plane
2206 
2207 		; !!End of Plane loop.
2208 			jnc		@@PlanesW		; If no carry, then more to do.
2209 
2210 
2211 		; Done with this
2212 			jmp		@@DONE
2213 
2214 
2215 	  ; - Font is uploaded
2216 	  @@FontIsUploaded:
2217 		; Calc the source and put in SI
2218 			mov		si,	[Font_SiteU4]	; Get base location
2219 			mov		ax,	6			; Put font size in ax
2220 			xor		bx,	bx			; Clear bx
2221 			mov		bx,	[CHAR]         ; Put character place in BX
2222 			sub		bx,	[Char_Base4]	; Subtract base char
2223 			mul		bx				; Mul size by place
2224 			add		si,	ax			; Put in SI
2225 
2226 		; Insure Map Mask is set to all planes
2227 			mov		ax,  0F02h	; 0F sets all planes. 02 is Map Mask
2228 			mov		dx,	SC_INDEX
2229 			out		dx,	ax
2230 
2231 		; Set all data from latches
2232 			mov		dx,	GC_INDEX
2233 			mov		ax,	00000h + BIT_MASK  ; Set all latch writes
2234 			out		dx, 	ax
2235 
2236 		; Set AX to line dif.
2237 			mov		ax,	[WLine_Offset]		; Page width
2238 			dec	     ax	                    ; minus XBlocks per char
2239 
2240 		; Get the Screen Seg and put it in DS and ES
2241 			mov		dx,  SCREEN_SEG
2242 			mov		ds,  dx
2243 			mov		es,	dx
2244 
2245 		; This section is for WRITES ------------------------------
2246 
2247 	  ; - Completely un-rolled
2248 
2249 		; Scan line #1
2250 			movsb
2251 			add		di,	ax	; Point DI to start of next line
2252 
2253 		; Scan line #2
2254 			movsb
2255 			add		di,	ax	; Point DI to start of next line
2256 
2257 		; Scan line #3
2258 			movsb
2259 			add		di,	ax	; Point DI to start of next line
2260 
2261 		; Scan line #4
2262 			movsb
2263 			add		di,	ax	; Point DI to start of next line
2264 
2265 		; Scan line #5
2266 			movsb
2267 			add		di,	ax	; Point DI to start of next line
2268 
2269 		; Scan line #6
2270 			movsb
2271 
2272 
2273 		; !!DONE!!
2274 	@@DONE:
2275 			pop		si di ds             ; Return state
2276 			pop		bp
2277 			ret
2278 
2279 ENDP			_XChar4;
2280 
2281 
2282 ; ------------------------ _Register_Font_Masks4 ---------------------------
2283 ; - This function registers a font mask for the current 4pix font
2284 ; - This mask can be used for MFont character drawing
2285 public		_Register_Font_Masks4
2286 
2287 PROC			_Register_Font_Masks4   FAR
2288 
2289 	ARG	MASK_OFF:WORD, MASK_SEG:WORD
2290 
2291 			push		bp
2292 			mov		bp,	sp		; Save Stack frame
2293 			push		ds
2294 
2295 		; Load DS.
2296 			ASSUME	ds:  @fardata
2297 			mov		ax,  @fardata
2298 			mov		ds,  ax			; Set DS to fardata segment
2299 
2300 		; Move location to local
2301 			mov		ax,			[MASK_OFF]
2302 			mov       [Font_Mask_O4], ax
2303 
2304 			mov		ax,			[MASK_SEG]
2305 			mov       [Font_Mask_S4], ax
2306 
2307 		; !!DONE!!
2308 			pop		ds
2309 			pop		bp			; Return state
2310 			ret
2311 
2312 ENDP			_Register_Font_Masks4
2313 
2314 
2315 ; ----------------------------- _XChar4_M ----------------------------------
2316 ; - This function will place a char from the current font to current screen
2317 ; - This function requires a font mask set to be registered.
2318 ; - Uses the 4pix font
2319 public		_XChar4_M
2320 
2321 PROC			_XChar4_M   FAR
2322 
2323 	ARG	X_S:WORD,	Y_S:WORD, CHAR:WORD
2324 
2325 
2326 			push		bp
2327 			mov		bp,	sp			; Save Stack frame
2328 			push		ds di si
2329 
2330 			cld
2331 
2332 		; Load DS.
2333 			ASSUME	ds:  @fardata
2334 			mov		ax,  @fardata
2335 			mov		ds,  ax			; Set DS to fardata segment
2336 
2337 		; Set DI to start of rectangle on screen
2338 			mov 		ax,  [WLine_Offset]
2339 			mov		bx,	ax		   ; Save in BX as S/L differential
2340 			mul		[Y_S]		   ; Find Y offset value. Place in AX
2341 
2342 			mov		di,  [X_S]        ; Find X offset value. Place in DI
2343 			shr		di,  1
2344 			shr		di,  1
2345 
2346 			add		di,  ax		   ; Add X and Y offsets
2347 			add		di,  [Write_Page] ; Add in page offset
2348 
2349 		; Is the font uploaded or not
2350 			mov		cx,	[UpLoaded4]  ; UPLOADED is 0!
2351 			jcxz		@@Uploaded	   ; The font is uploaded
2352 
2353 	  ; - Font is not uploaded
2354 
2355 		; Figure character offset and add to load ds:si font site
2356 			mov		ax,	24			; Put font size in ax
2357 			mov		cx,	[CHAR]         ; Put character place in BX
2358 			sub		cx,	[Char_Base4]	; Subtract base char
2359 			mul		cx				; Mul size by place
2360 			lds		si,  [Font_Addr4]
2361 			add		si,  ax
2362 
2363 		; Save the base destination in CX
2364 			mov		cx,  di
2365 
2366 		; Get the Screen Seg and put it in ES
2367 			mov		ax,  SCREEN_SEG
2368 			mov		es,	ax
2369 
2370 		; Set all data from CPU and non from latches
2371 			mov		dx,	GC_INDEX
2372 			mov		ax,	0FF00h + BIT_MASK  ; Set all CPU writes
2373 			out		dx, 	ax
2374 
2375 		; Set up DX and AX for plane selection
2376 			mov		ax,	0102h	; Plane 0 selected
2377 			mov		dx,	SC_INDEX
2378 
2379 		; This section is for WORD WRITES ------------------------------
2380 
2381 	@@PlanesW:          ; Master plane loop.
2382 
2383 			out		dx,	ax	; Set the plane
2384 
2385 
2386 	  ; Do the actual DRAW.  MOV.  Completely un-rolled!!
2387 
2388 		; Scan line #1
2389 			lodsb	; Get the pixel
2390 			or		al,	al		; Is it zero
2391 			jz		@@NoDraw1       ; If zero, don't draw it
2392 			mov		[es:di],	al	; Else, do draw it
2393 	@@NoDraw1:
2394 			add		di,	bx		; Point DI to start of next line
2395 
2396 		; Scan line #2
2397 			lodsb	; Get the pixel
2398 			or		al,	al		; Is it zero
2399 			jz		@@NoDraw2       ; If zero, don't draw it
2400 			mov		[es:di],	al	; Else, do draw it
2401 	@@NoDraw2:
2402 			add		di,	bx		; Point DI to start of next line
2403 
2404 		; Scan line #3
2405 			lodsb	; Get the pixel
2406 			or		al,	al		; Is it zero
2407 			jz		@@NoDraw3       ; If zero, don't draw it
2408 			mov		[es:di],	al	; Else, do draw it
2409 	@@NoDraw3:
2410 			add		di,	bx		; Point DI to start of next line
2411 
2412 		; Scan line #4
2413 			lodsb	; Get the pixel
2414 			or		al,	al		; Is it zero
2415 			jz		@@NoDraw4       ; If zero, don't draw it
2416 			mov		[es:di],	al	; Else, do draw it
2417 	@@NoDraw4:
2418 			add		di,	bx		; Point DI to start of next line
2419 
2420 		; Scan line #5
2421 			lodsb	; Get the pixel
2422 			or		al,	al		; Is it zero
2423 			jz		@@NoDraw5       ; If zero, don't draw it
2424 			mov		[es:di],	al	; Else, do draw it
2425 	@@NoDraw5:
2426 			add		di,	bx		; Point DI to start of next line
2427 
2428 		; Scan line #6
2429 			lodsb	; Get the pixel
2430 			or		al,	al		; Is it zero
2431 			jz		@@NoDraw6       ; If zero, don't draw it
2432 			mov		[es:di],	al	; Else, do draw it
2433 	@@NoDraw6:
2434 
2435 
2436 		; Done with plane.  Reset Destination pointers.  Adjst plane
2437 			mov		di,	cx		; Restore the destination start
2438 
2439 			mov		al,  02h		; Restore MAP MASK pointer
2440 			shl		ah,	1		; Adjust plane
2441 
2442 		; !!End of Plane loop. If carry not set, then not done
2443 			jnc		@@PlanesW
2444 
2445 		; Done with this
2446 			jmp		@@DONE
2447 
2448 
2449 	@@Uploaded:
2450 	  ; - Font is uploaded
2451 		; Set SI to mask offset
2452 			mov		ax,	3			; Put mask size in ax
2453 			mov		cx,	[CHAR]         ; Put character place in CX
2454 			sub		cx,	[Char_Base4]	; Subtract base char
2455 			mul		cx				; Mul size by place
2456 			add		ax,	[Font_Mask_O4] ; Find masks offset in mask set
2457 			mov		si,	ax			; Save it
2458 
2459 		; Calc the source and put in BX
2460 			mov		bx,	[Font_SiteU4]	; Get base location
2461 			mov		ax,	6			; Put font size in ax
2462 			mov		cx,	[CHAR]         ; Put character place in BX
2463 			sub		cx,	[Char_Base4]	; Subtract base char
2464 			mul		cx				; Mul size by place
2465 			add		bx,	ax			; Put in SI
2466 
2467 		; Set BP to the scan line differential
2468 			mov		bp,	[WLine_Offset]
2469 
2470 		; Set DS to mask area
2471 			mov		ax,	[Font_Mask_S4]
2472 			mov 		ds,	ax
2473 
2474 		; Get the Screen Seg and put it in ES
2475 			mov		ax,  SCREEN_SEG
2476 			mov		es,	ax
2477 
2478 		; Set all data from latches
2479 			mov		dx,	GC_INDEX
2480 			mov		ax,	00000h + BIT_MASK  ; Set all latch writes
2481 			out		dx, 	ax
2482 
2483 		; Set up Map Mask
2484 			mov		al,  02h	; 02 is Map Mask
2485 			mov		dx,	SC_INDEX
2486 			out		dx,	al
2487 			inc		dx
2488 
2489 		; Set CL to shift spaces
2490 			mov		cl,	4
2491 
2492 	 ; This section is for WRITES ------------------------------
2493 
2494 	 ; -- Completely unrolled
2495 
2496 	  ; Scan Line #1
2497 		; This section prep the Map Mask
2498 			lodsb				; Get mask byte
2499 
2500 		; Set mask for first write
2501 			out		dx,	al		; Set map mask
2502 
2503 		; Write the byte
2504 			mov		ah,		[es:bx]
2505 			mov		[es:di],	ah
2506 
2507 	  ; Scan Line #2
2508 		; Set mask for next write
2509 			shr		al,       cl		; Move upper nibble down
2510 			out		dx,		al        ; Set map mask
2511 
2512 		; Adjust for next scan line
2513 			add		di,	bp	; Point DI to start of next line
2514 			inc		bx
2515 
2516 		; Write the second byte
2517 			mov		al,		[es:bx]
2518 			mov		[es:di],	al
2519 
2520 		; Adjust for next scan line
2521 			add		di,	bp	; Point DI to start of next line
2522 			inc		bx
2523 
2524 	  ; Scan Line #3
2525 		; This section prep the Map Mask
2526 			lodsb				; Get mask byte
2527 
2528 		; Set mask for first write
2529 			out		dx,	al		; Set map mask
2530 
2531 		; Write the byte
2532 			mov		ah,		[es:bx]
2533 			mov		[es:di],	ah
2534 
2535 	  ; Scan Line #4
2536 		; Set mask for next write
2537 			shr		al,       cl		; Move upper nibble down
2538 			out		dx,		al        ; Set map mask
2539 
2540 		; Adjust for next scan line
2541 			add		di,	bp	; Point DI to start of next line
2542 			inc		bx
2543 
2544 		; Write the second byte
2545 			mov		al,		[es:bx]
2546 			mov		[es:di],	al
2547 
2548 		; Adjust for next scan line
2549 			add		di,	bp	; Point DI to start of next line
2550 			inc		bx
2551 
2552 	  ; Scan Line #5
2553 		; This section prep the Map Mask
2554 			lodsb				; Get mask byte
2555 
2556 		; Set mask for first write
2557 			out		dx,	al		; Set map mask
2558 
2559 		; Write the byte
2560 			mov		ah,		[es:bx]
2561 			mov		[es:di],	ah
2562 
2563 	  ; Scan Line #6
2564 		; Set mask for next write
2565 			shr		al,       cl		; Move upper nibble down
2566 			out		dx,		al        ; Set map mask
2567 
2568 		; Adjust for next scan line
2569 			add		di,	bp	; Point DI to start of next line
2570 			inc		bx
2571 
2572 		; Write the second byte
2573 			mov		al,		[es:bx]
2574 			mov		[es:di],	al
2575 
2576 
2577 		; !!DONE!!
2578 	@@DONE:
2579 			pop		si di ds             ; Return state
2580 			pop		bp
2581 			ret
2582 
2583 ENDP			_XChar4_M;
2584 
2585 
2586 ;----------------------------- _XString4 ----------------------------------
2587 ; - This function will place a char from the current font to current screen
2588 ; - It will use the masked font on mask flag set to not 0.
2589 public		_XString4
2590 
2591 PROC			_XString4   FAR
2592 
2593 	ARG	X_S:WORD,	Y_S:WORD, MASKIT:WORD, STR_OFF:DWORD
2594 
2595 			push		bp
2596 			mov		bp,	sp		; Save Stack frame
2597 			push		ds di si
2598 
2599 		; Load DS.
2600 			ASSUME	ds:  @fardata
2601 			mov		ax,  @fardata
2602 			mov		ds,  ax			; Set DS to segment w/ Table
2603 
2604 		; Move flag into CX
2605 			mov		cx,  [MASKIT]
2606 
2607 		; Load DS:SI
2608 			lds		si,  [STR_OFF]
2609 
2610 		; !!! This is the master string loop
2611 	@@STRING:
2612 			xor       ax,	ax
2613 			mov	  	al,	[ds:si]		; Get the char
2614 			cmp		al,	0			; Is it the EOS
2615 			je		@@DONE			; If so jump
2616 
2617 		 ; Save cx
2618 			push 	cx
2619 
2620 		 ; Build stack frame
2621 			push		ax				; Push the char
2622 			push		[Y_S]			; Push the Y coor
2623 			push		[X_S]			; Push the X coor
2624 		 ; To mask or not to mask
2625 			jcxz		@@DontMask		; If Flag = 0, dont mask
2626 			call		_XChar4_M			; Put the char
2627 			jmp		@@Continue
2628 
2629 	@@DontMask:
2630 			call      _XChar4			; Do a mask instead
2631 
2632 	@@Continue:
2633 			add		sp,	6			; Adjust the stack
2634 
2635 			pop		cx				; Restore cx
2636 
2637 			add		[X_S],	4		; Move the cursor
2638 			inc		si				; Point to next char
2639 			jmp		@@STRING            ; Continue
2640 
2641 		; !!DONE!!
2642 	@@DONE:
2643 			pop		si di ds             ; Return state
2644 			pop		bp
2645 			ret
2646 
2647 ENDP			_XString4
2648 
2649 
2650 ; --------------------------- _XPaste_Tile_M -------------------------------
2651 ; - This function will place a tile from the display memory to current screen
2652 ; - It will use the mask passed to it to leave background transparent
2653 ; - Max Y size is 255
2654 
2655 public		_XPaste_Tile_M
2656 
2657 PROC			_XPaste_Tile_M   FAR
2658 
2659  ARG	X_S:WORD,	Y_S:WORD, X_D:WORD,	Y_D:WORD,	TILE:WORD, MASK_O:DWORD
2660 
2661 			push		bp
2662 			mov		bp,	sp			; Save Stack frame
2663 			push		ds di si
2664 
2665                cld
2666  
2667 		; Load DS.
2668 			ASSUME	ds:  @fardata
2669 			mov		ax,  @fardata
2670 			mov		ds,  ax			; Set DS to fardata segment
2671 
2672 		; Set DI to start of rectangle on screen
2673 			mov 		ax,  [WLine_Offset]
2674 			mul		[Y_S]		   ; Find Y offset value. Place in AX
2675 
2676 			mov		di,  [X_S]        ; Find X offset value. Place in DI
2677 			shr		di,  1
2678 			shr		di,  1		   ; Adjust to number of XBlocks
2679 
2680 			add		di,  ax		   ; Add X and Y offsets
2681 			add		di,  [Write_Page] ; Add in page offset
2682 
2683 		; Put in source in BX
2684 			mov		bx,	[TILE]
2685 
2686 		; Get the Screen Seg and put it in ES
2687 			mov		ax,  SCREEN_SEG
2688 			mov		es,	ax
2689 
2690 		; Set all data from latches
2691 			mov		dx,	GC_INDEX
2692 			mov		ax,	00000h + BIT_MASK  ; Set all latch writes
2693 			out		dx, 	ax
2694 
2695 		; Set CX to the number of XBlocks per line
2696 			mov		cx,	[X_D]
2697 			shr		cx,	1
2698 			shr		cx,	1
2699 
2700 		; Get distance from end of one line to start of other and save
2701 			mov		ax,		[WLine_Offset]	; Get screen width
2702 			sub		ax,		cx			; Del number of XBlocks
2703 			mov		dx,       ax			; Save in DX
2704 
2705 		; Save cl in ch.
2706 			mov		ch,  cl	; Save in CH
2707 
2708 
2709 		; Set DS:SI to mask area
2710 			lds		si,	[MASK_O]
2711 
2712 		; Set AH to the rows to do
2713 			mov		ax,	[Y_D]	; Puts number in AX
2714 			mov		ah,	al		; Puts number in ah
2715 
2716 		; Move scan line differential from dx to bp
2717 			mov		bp,  dx
2718 
2719 		; Set up Map Mask
2720 			mov		al,  02h	; 02 is Map Mask
2721 			mov		dx,	SC_INDEX
2722 			out		dx,	al
2723 			inc		dx
2724 
2725 		; This section is for WRITES ------------------------------
2726 	@@Rowloop:
2727 
2728 	@@ScanLine:
2729 		; This section prep the Map Mask
2730 			lodsb				; Get mask byte
2731 
2732 		; Set mask for write
2733 			out		dx,	al		; Set map mask
2734 
2735 		; Write the XBlock
2736 			mov		al,		[es:bx]
2737 			mov		[es:di],	al
2738 
2739 		; Adjust bx and si
2740 			inc		bx
2741 			inc		di
2742 
2743 		; End of ScanLine
2744 			dec		cl
2745 			jnz		@@ScanLine
2746 
2747 		; Adjust for next iteration
2748 			add		di,	bp	; Point DI to start of next line
2749 
2750 		; Restore cl
2751 			mov		cl,  ch
2752 
2753 		; End of Rowloop.
2754 			dec		ah
2755 			jnz		@@Rowloop
2756 
2757 		; !!DONE!!
2758 	@@DONE:
2759 			pop		si di ds             ; Return state
2760 			pop		bp
2761 			ret
2762 
2763 ENDP			_XPaste_Tile_M;
2764 
2765 
2766 ; --------------------------- _XPaste_Sprite_M ----------------------------
2767 ; - This function will place a sprite from the display memory to current screen
2768 ; - It will use the mask passed to it to leave background transparent
2769 ; - Max Y size is 255
2770 public		_XPaste_Sprite_M
2771 
2772 PROC			_XPaste_Sprite_M   FAR
2773 
2774  ARG	X_S:WORD,	Y_S:WORD, X_D:WORD,	Y_D:WORD,	TILE:WORD, MASK_O:DWORD
2775 
2776 			push		bp
2777 			mov		bp,	sp			; Save Stack frame
2778 			push		ds di si
2779 
2780                cld
2781  
2782 		; Load DS.
2783 			ASSUME	ds:  @fardata
2784 			mov		ax,  @fardata
2785 			mov		ds,  ax			; Set DS to fardata segment
2786 
2787 		; Set all data from latches
2788 			mov		dx,	GC_INDEX
2789 			mov		ax,	00000h + BIT_MASK  ; Set all latch writes
2790 			out		dx, 	ax
2791 
2792 		; Set DI to start of rectangle on screen
2793 			mov 		ax,  [WLine_Offset] ; Scan line size
2794 			mul		[Y_S]		   ; Find Y offset value. Place in AX
2795 
2796 			mov		di,  [X_S]        ; Find X offset value. Place in DI
2797 			shr		di,  1
2798 			shr		di,  1		   ; Adjust to number of XBlocks
2799 
2800 			add		di,  ax		   ; Add X and Y offsets
2801 			add		di,  [Write_Page] ; Add in page offset
2802 
2803 		; Put source in BX
2804 			mov		bx,	[TILE]
2805 
2806 		; Find adjustment to source for alignment
2807 			mov		ax,	[X_D]
2808 			mov		cx,	[X_S]
2809 
2810 			shr		ax,	1	   ; Number of XBlocks a line
2811 			shr		ax,	1
2812 			mul		[Y_D]        ; Find size of each sprite alignment
2813 
2814 			and		cx,	3	   ; Mask all but 2 LSBs
2815 
2816 			mul		cx		   ; Find new offset
2817 
2818 			add		bx,	ax	   ; Adjust BX
2819 
2820 		; Save adjustment for mask for alignment in DX
2821 			mov		dx,	ax	   ; AX as calculated above
2822 
2823 		; Set CX to the number of XBlocks
2824 			mov		cx,	[X_D]
2825 			shr		cx,	1
2826 			shr		cx,	1
2827 
2828 		; Get distance from end of one line to start of other and save
2829 			mov		ax,	[WLine_Offset]	; Get screen width
2830 			sub		ax,	cx			; Del number of XBlocks
2831 
2832 		; Set DS:SI to mask area
2833 			lds		si,	[MASK_O]
2834 
2835 		; Add alignment adjust to si
2836 			add		si,  dx
2837 
2838 		; Set AH to the rows to do
2839 			mov		dx,	[Y_D]	; Puts number in AX
2840 			mov		bp,	ax		; Move diff into BP
2841 			mov		ah,	dl		; Puts number in ah
2842 
2843 		; Get the Screen Seg and put it in ES
2844 			mov		dx,  SCREEN_SEG
2845 			mov		es,	dx
2846 
2847 		; Set up Map Mask
2848 			mov		al,  02h	; 02 is Map Mask
2849 			mov		dx,	SC_INDEX
2850 			out		dx,	al
2851 			inc		dx
2852 
2853 		; Save scan length (CL) in CH
2854 			mov		ch,	cl
2855 
2856 		; This section is for WRITES ------------------------------
2857 	@@Rowloop:
2858 
2859 	@@ScanLine:
2860 		; This section prep the Map Mask
2861 			lodsb				; Get mask byte
2862 
2863 		; Set mask for write
2864 			out		dx,	al		; Set map mask
2865 
2866 		; Write the XBlock
2867 			mov		al,		[es:bx]
2868 			mov		[es:di],	al
2869 
2870 		; Adjust bx and si
2871 			inc		bx
2872 			inc		di
2873 
2874 		; End of ScanLine
2875 			dec		cl
2876 			jnz		@@ScanLine
2877 
2878 
2879 		; Adjust for next iteration
2880 			add		di,	bp	; Point DI to start of next line
2881 
2882 		; Restore scan length
2883 			mov		cl,  ch
2884 
2885 		; End of Rowloop.
2886 			dec		ah
2887 			jnz		@@Rowloop
2888 
2889 		; !!DONE!!
2890 	@@DONE:
2891 			pop		si di ds             ; Return state
2892 			pop		bp
2893 			ret
2894 
2895 ENDP			_XPaste_Sprite_M;
2896 
2897 
2898 ; ------------------------ _XSet_Pal_Color ---------------------------
2899 ; - This function uses the bios to set a single color in the palette
2900 ; -
2901 public		_XSet_Pal_Color
2902 
2903 PROC			_XSet_Pal_Color
2904 
2905 	ARG	COLOR:WORD, RED:WORD, GREEN:WORD, BLUE:WORD
2906 
2907 			push		bp
2908 			mov		bp,	sp		; Save Stack frame
2909 
2910 			mov		bx,	[COLOR]	; Load color number
2911 
2912 			mov		ax,	[RED]
2913 			mov		dh,	al		; Load Red value
2914 
2915 			mov		ax,	[GREEN]
2916 			mov		ch,	al		; Load Green value
2917 
2918 			mov		ax,	[BLUE]
2919 			mov		cl,	al		; Load Blue value
2920 
2921 			mov		ax,	01010h	; Load ax with BIOS routine id
2922 			int		010h			; Call BIOS
2923 
2924 			pop		bp			; Return state
2925                ret
2926 
2927 ENDP			_XSet_Pal_Color
2928 
2929 ; ------------------------ _XSet_Pal_Block ---------------------------
2930 ; - This function uses the bios to set a block of colors in the palette
2931 ; -
2932 public		_XSet_Pal_Block
2933 
2934 PROC			_XSet_Pal_Block
2935 
2936 	ARG	START:WORD, NUMBER:WORD, PAL_O:DWORD
2937 
2938 			push		bp
2939 			mov		bp,	sp		; Save Stack frame
2940 
2941 			mov		bx,	[START]	; Load start color number
2942 
2943 			mov		cx,	[NUMBER]  ; Load number of colors
2944 
2945 			les		dx,	[PAL_O]   ; Load pointer data
2946 
2947 			mov		ax,	01012h	; Load ax with BIOS routine id
2948 			int		010h			; Call BIOS
2949 
2950 			pop		bp			; Return state
2951                ret
2952 
2953 ENDP			_XSet_Pal_Block
2954 
2955 
2956 ; ------------------------ _XPut_Pixel ------------------------------------
2957 ; - Put a pixel to the screen.
2958 ; -
2959 public		_XPut_Pixel
2960 
2961 PROC			_XPut_Pixel
2962 
2963 	ARG	X_LOC:WORD, Y_LOC:WORD, COLOR:WORD
2964 
2965 			push		bp
2966 			mov		bp,	sp		; Save Stack frame
2967 
2968 			push		ds di 
2969 
2970 
2971 		; Load DS.
2972 			ASSUME	ds:  @fardata
2973 			mov		ax,  @fardata
2974 			mov		ds,  ax			; Set DS to fardata segment
2975 
2976 		; Set DI to the XBlock
2977 			mov 		ax,  [WLine_Offset]  ; Scan line size
2978 			mul		[Y_LOC]		   ; Find Y offset value. Place in AX
2979 
2980 			mov		di,  [X_LOC]      ; Find X offset value. Place in DI
2981 			mov       cx,	di		   ; For later to determine the mask
2982 			shr		di,  1
2983 			shr		di,  1		   ; Adjust to number of XBlocks
2984 
2985 			add		di,  ax		   ; Add X and Y offsets
2986 			add		di,  [Write_Page] ; Add in page offset
2987 
2988 
2989 		; Set ah to the mask
2990 			and		cx,	03h		; Get the lower 2 bits
2991 			mov		ax,	0102h     ; MAP MASK
2992 			shl		ah,	cl		; Shift to app. plane
2993 
2994 		; Set up Map Mask
2995 			mov		dx,	SC_INDEX
2996 			out		dx,	ax
2997 
2998 		; Set all data from CPU and non from latches
2999 			mov		dx,	GC_INDEX
3000 			mov		ax,	0FF00h + BIT_MASK  ; Set all CPU writes
3001 			out		dx, 	ax
3002 
3003 		; Get the Screen Seg and put it in DS
3004 			mov		ax,  SCREEN_SEG
3005 			mov		ds,	ax
3006 
3007 		; Get the color
3008 			mov		ax,	[COLOR]	
3009 
3010 		; Put the Pixel
3011 			mov		[di],	al
3012 
3013 		; !!DONE!!
3014 			pop		di ds             ; Return state
3015 			pop		bp
3016 			ret
3017 
3018 ENDP  		_XPut_Pixel
3019 
3020 
3021 ; ------------------------ _MEvent_Handler ---------------------------
3022 ; - Xtile's mouse event handler
3023 ; -
3024 PROC			_MEvent_Handler
3025 
3026 		; Save thier DS
3027 			push ds di si
3028 
3029 	; This function is not callable from 'c' so we won't build a
3030 	; stack frame
3031 
3032 		; Save the event masks
3033 			push 	ax
3034 
3035 		; Correct X pos
3036 			shr	cx,	1
3037 
3038 		; Save dx in SI
3039 			mov		si,	dx
3040 
3041 		; Load DS.
3042 			ASSUME	ds:  @fardata
3043 			mov		ax,  @fardata
3044 			mov		ds,  ax			; Set DS to fardata segment
3045 
3046 		; Check for Lock
3047 			cmp		[LockHandler],	NOTLOCKM	; Is it locked
3048 			jz		@@NotLocked
3049 
3050 		; !!!Locked!!!  Jump out
3051 			pop		ax					; Pull flags off stack
3052 			jmp 		@@Done
3053 
3054 	@@NotLocked:
3055 		; Lock the handler
3056 			mov		ax,	LOCKM
3057 			mov		[LockHandler], ax
3058 
3059 	; Get and save the status of bit mask and map mask
3060 		; Get status of bit mask
3061 			mov		dx,	GC_INDEX
3062 			mov		ax,	0808h     ; 08 is bit mask
3063 			out		dx, 	al
3064 			inc		dx
3065 			in		al,	dx		; Get the bit mask
3066 			xchg		al,	ah
3067 			push		ax
3068 
3069 		; Get Map Mask
3070 			mov		ax,  0202h		; 02 is Map Mask
3071 			mov		dx,	SC_INDEX
3072 			out		dx,	al
3073 			inc		dx
3074 			in		al,	dx
3075                xchg		al,  ah
3076 			push  	ax
3077 
3078 	; -- Restore the the current background location ---
3079 	; This is a Save Site restore
3080 			cld
3081 
3082 		; Set DI to start of rectangle on screen
3083 			mov 		ax,  [DLine_Offset] ; Get line size
3084 			mov		bx,  [MLastY]       ; Get Y into view
3085 			push      bx				; Save on stack
3086 			add	     bx,  [ViewYLoc]     ; Add start of view
3087 			mul		bx			   ; Find Y offset value. Place in AX
3088 
3089 			mov		di,  [MLastX]     ; Find X offset value. Place in DI
3090 			mov		bp,  di		   ; Save X in BP
3091 			add		di,  [ViewXLoc]   ; Get start of view and add it
3092 			shr		di,  1
3093 			shr		di,  1
3094 
3095 			add		di,  ax		     ; Add X and Y offsets
3096 			add		di,  [Display_Page] ; Add in page offset
3097 
3098 		; Get DX back
3099 			mov		dx,	si
3100 
3101 		; Save the new location as the last known
3102 			mov		[MLastY],	dx
3103 			mov		[MLastX],	cx
3104 
3105 		; See if we need to clip Second XBlock
3106 			mov		cx,		2			; Assume 2 XBlocks to write
3107 			mov		dx,       [ScreenSizeX]	; Get screen size
3108 			sub		dx,		4			; Get 2nd to last XBlock
3109 			cmp		dx,		bp
3110 			jae       @@Continue			; Both blocks on reload
3111 			dec		cx					; Only one block on reload
3112 
3113 	@@Continue:
3114 		; Set all data from latches
3115 			mov		dx,	GC_INDEX
3116 			mov		ax,	00000h + BIT_MASK  ; Set all latch writes
3117 			out		dx, 	ax
3118 
3119 		; Insure Map Mask is set to all planes
3120 			mov		ax,  0F02h	; 0F sets all planes. 02 is Map Mask
3121 			mov		dx,	SC_INDEX
3122 			out		dx,	ax
3123 
3124 		; Set DX to number of lines to display
3125 			mov		dx,	8		; Assume 8 scan lines
3126 			pop		bx			; Get Y last and put in BX
3127 			mov		ax,	[ScreenSizeY] ; Get Screen size Y and put in ax
3128 			sub		ax,	8		; Subtract to make mimimum clip
3129 
3130 			cmp		ax,	bx		; Does it need clipping?
3131 			ja		@@ContinueC	; No, then go!
3132 
3133 			sub		bx,  ax		; Needs clipping!  Find new DX
3134 			sub		dx,	bx
3135 
3136 	@@ContinueC:
3137 		; Set BP to the distance from one scan line to next
3138 			mov		bp,	[DLine_Offset]
3139 			sub		bp,  cx    		; # XBlocks per scan line
3140 
3141 		; Get the Screen Seg and put it in DS and ES
3142 			mov		ax,  SCREEN_SEG
3143 			mov		ds,  ax
3144 			mov		es,	ax
3145 
3146 		; Set SI to source
3147 			mov		si,		MSAVEOFFSET
3148 
3149 		; Save number to move (CX) in BX
3150 			mov		bx,	cx
3151 
3152 	   ; This section is for WRITES ------------------------------
3153 	   ; The Reload will be clipped if appropriate
3154 
3155 	 @@RowLoop:
3156 		 ; Put 1 or 2 XBlocks
3157 			rep movsb
3158 
3159 		 ; Ready next iteration
3160 			add		di,	bp	; Point DI to start of next line
3161 
3162 		 ; Reload CX
3163 			mov		cx,	bx
3164 
3165 		 ; Are we done?
3166 			dec		dx
3167 			jnz		@@RowLoop	; No, then go and do another line
3168 
3169 
3170 	; ------ Now save the new area --------
3171 	; -- Do the reload
3172 
3173 		; Load DS.
3174 			ASSUME	ds:  @fardata
3175 			mov		ax,  @fardata
3176 			mov		ds,  ax			; Set DS to fardata segment
3177 
3178 		; Set SI to start of rectangle on screen
3179 			mov 		ax,  [DLine_Offset] ; Get line size
3180 			mov		bx,  [MLastY]       ; Get Y into view
3181 			mov		di,	bx			; Save in DI
3182 			add	     bx,  [ViewYLoc]     ; Add start of view
3183 			mul		bx			   ; Find Y offset value. Place in AX
3184 
3185 			mov		si,  [MLastX]     ; Find X offset value. Place in DI
3186 			mov		bp,  si		   ; Save in BP for later
3187 			add		si,  [ViewXLoc]   ; Get start of view and add it
3188 			shr		si,  1
3189 			shr		si,  1
3190 
3191 			add		si,  ax		     ; Add X and Y offsets
3192 			add		si,  [Display_Page] ; Add in page offset
3193 
3194 			push		si				; Save what will later be DI
3195 
3196 		; See if we need to clip Second XBlock
3197 			mov		cx,		2			; Assume 2 XBlocks to write
3198 			mov		dx,       [ScreenSizeX]	; Get screen size
3199 			sub		dx,		4			; Get 2nd to last XBlock
3200 			cmp		dx,		bp             ; BP from above.
3201 			jae        @@Continue3			; Both blocks on reload
3202 			dec		cx					; Only one block on reload
3203 
3204 	@@Continue3:
3205 		; Set DX to number of lines to reload
3206 			mov		dx,	8		; Assume 8 scan lines
3207 			mov		bx, 	di		; Get Y last and put in BX (from SI)
3208 			mov		ax,	[ScreenSizeY] ; Get Screen size Y and put in ax
3209 			sub		ax,	8		; Subtract to make mimimum clip
3210 
3211 			cmp		ax,	bx		; Does it need clipping?
3212 			ja		@@Continue4	; No, then go!
3213 
3214 			sub		bx,  ax		; Needs clipping!  Find new DX
3215 			sub		dx,	bx
3216 
3217 	@@Continue4:
3218 		; Save DX ( as number of lines to do ) for later
3219 			push		dx
3220 
3221 		; Set BP to scan line dif.
3222 			mov		bp,	[DLine_Offset]
3223 			sub		bp,  cx
3224 
3225 		; Get the Screen Seg and put it in DS
3226 			mov		ax,  SCREEN_SEG
3227 			mov		ds,	ax
3228 
3229 		; Set destination
3230 			mov		di,	MSAVEOFFSET
3231 
3232 		; Save SI so we dont have to calc later
3233 			mov		ax,	si
3234 
3235 		; Save CX in BX
3236 			mov		bx,	cx
3237 
3238 	   ; This section is for the MOVE ------------------------------
3239 
3240 	@@RowLoop2:
3241 		; Do line
3242 			rep		movsb	; One or two XBlocks
3243 
3244 		; Prep for next line
3245 			add		si,	bp	; Point SI to start of next line
3246 			mov		cx,	bx	; Restore CX
3247 
3248 		; Are we done?
3249 			dec		dx
3250 			jnz		@@RowLoop2	; No, then go and do another
3251 
3252 
3253 	; -------- Put the pointer in the new position ---------
3254 
3255 		; Load DS.
3256 			ASSUME	ds:  @fardata
3257 			mov		ax,  @fardata
3258 			mov		ds,  ax			; Set DS to fardata segment
3259 
3260 
3261 		; Find adjustment to source for alignment
3262 			mov		bx,	[MLastX]	 ; Put X loc into cx
3263 			add		bx,  [ViewXLoc] ; Add view start
3264 			mov		ax,	16		; Alignment size ( 2XBlocks*8Scan )
3265 
3266 			and		bx,	3	   ; Mask all but 2 LSBs
3267 			mul		bx		   ; Find offset into alignments (Put in AX)
3268 
3269 		; Put source into BX and add the alignment adj
3270 			mov		bx,	MOUSEOFFSET
3271 			add		bx,	ax	   ; Adjust BX
3272 
3273 
3274 		; Set DS:SI to mask area
3275 			lds		si,	[MPointerMask]
3276 
3277 		; Add adjustment for mask for alignment
3278 			add		si,	ax	   ; AX as calculated above
3279 
3280 		; Set ah to rows to do
3281 			pop		ax		   ; Was DX in the reload
3282 			mov		ah,  al	   ;	Move to upper nibble
3283 
3284 		; Increment BP to account for no last inc
3285 			inc		bp
3286 
3287 		; Pop the destination, prev si, from the stack
3288 			pop		di
3289 
3290 		; Set up Map Mask
3291 			mov		al,  02h	; 02 is Map Mask
3292 			mov		dx,	SC_INDEX
3293 			out		dx,	al
3294 			inc		dx
3295 
3296 		; Shift CX down to see if we need to write 2nd XBlock
3297 			shr		cx,	1
3298 
3299 		; This section is for WRITES ------------------------------
3300 	@@Rowloop3:
3301 
3302 
3303 		; Set mask for first XBlock write
3304 			lodsb				; Get mask byte
3305 			out		dx,	al		; Set map mask
3306 
3307 		; Write the 1st XBlock
3308 			mov		al,		[es:bx]
3309 			mov		[es:di],	al
3310 
3311 		; Load the next mask
3312 			lodsb
3313 
3314 		; Increment source pointers
3315 			inc	bx
3316 
3317 		; If CX is zero, pointer is clipped.  Don't put next XBlock
3318 			jcxz		@@Clipped
3319 
3320 	   ; - Do another write
3321 		; Set the mask
3322 			out		dx,	al		; Set map mask
3323 
3324 		; Increment destination pointers
3325 			inc	di
3326 
3327 		; Write the 2nd XBlock
3328 			mov		al,		[es:bx]
3329 			mov		[es:di],	al
3330 
3331 	 @@Clipped:
3332 		; Adjust for next iteration
3333 			add		di,	 bp  ; Point to next scan line
3334 			inc		bx
3335 
3336 		; End of Rowloop.
3337 			dec		ah
3338 			jnz		@@Rowloop3
3339 
3340 	  ; -- Done with screen
3341 
3342 	  ; Restore the state of the bit mask and map mask
3343 		; Get Map Mask
3344 			mov		dx,	SC_INDEX
3345 			pop		ax
3346 			out		dx,	ax
3347 
3348 		; Do the BIT MASK
3349 			mov		dx,	GC_INDEX
3350 			pop		ax
3351 			out		dx, 	ax
3352 
3353 	  ; -- See if we have to call the user's handler
3354 
3355 		; Make ES the local data
3356 			ASSUME	es:  @fardata
3357 			mov		ax,  @fardata
3358 			mov		es,  ax			; Set ES to fardata segment
3359 
3360 		; Restore event masks
3361 			pop		ax
3362 
3363 		; AND the mask with users mask
3364 			and		ax,	[es:MUEventMask]
3365 
3366 		; If zero then don't call user's
3367 			je		@@Done
3368 
3369 		; Load users DGROUP
3370 			mov	ax,  @data
3371 			mov  ds,  ax
3372 
3373 		; Otherwise set up stack and call users routine
3374 			push		ax		; Push the event mask
3375 
3376 			push		[es:MLastY]  ; Push Y location
3377 
3378 			push		[es:MLastX]  ; Push X location
3379 
3380 			call   	[es:Mouse_Hndlr_O]	; User pointer to call user handler
3381 
3382 					; Clean stack after call
3383 			add		sp,	6
3384 
3385 
3386 	  ; -- DONE!!
3387 
3388 	@@Done:
3389 		; Make DS the local data
3390 			ASSUME	ds:  @fardata
3391 			mov		ax,  @fardata
3392 			mov		ds,  ax			; Set DS to fardata segment
3393 
3394 		; Unlock the handler
3395 			mov		ax,	NOTLOCKM
3396 			mov		[LockHandler], ax
3397 
3398 			pop   si di ds     ; Pop mouses DS
3399 			ret
3400 
3401 ENDP			_MEvent_Handler
3402 
3403 
3404 ; ------------------------ _XRegister_Mouse ---------------------------
3405 ; - This function sets up the use of the mouse
3406 ; - It returns FALSE (0) if it cannot
3407 ; -
3408 public		_XRegister_Mouse
3409 
3410 PROC			_XRegister_Mouse
3411 
3412 	ARG	MPOINT:DWORD, MMASK:DWORD, HANDLER:DWORD
3413 
3414 			push		bp
3415 			mov		bp,	sp		; Save Stack frame
3416 
3417 		; Save registers
3418 			push		ds si di
3419 
3420 		; First see if mouse is available
3421 			mov       ax,	0
3422 			int		33h
3423 
3424 			cmp		ax,	0FFFFh	; If ax is FFFFh then mouse is present
3425 			je 		@@Cont
3426 
3427 			mov		ax,	MOUSE_NOTPRES
3428 			jmp		@@Done		; Otherwise, done
3429 
3430 		; Mouse is present so continue
3431 	@@Cont:
3432 
3433 	; ----------- Upload mouse pointer ------------
3434 
3435 		; Prep the stack for call to upload sprite
3436 			les		si,	[MPOINT]	; Get the image offset
3437 			push		es
3438 			push		si
3439 
3440 			mov		si,	(64*4)		; Mouse sprite size
3441 			push		si
3442 
3443 			mov		si,	MOUSEOFFSET    ; Mouse pointer site
3444 			push		si
3445 
3446 		; Call upload sprite
3447 			call 	_XUpload_Sprite
3448 
3449 		; Fix the stack after call
3450 			add		sp,	8
3451 
3452 	; ---- Done uploading mouse pointer
3453 
3454 
3455 		; Load DS.
3456 			ASSUME	ds:  @fardata
3457 			mov		ax,  @fardata
3458 			mov		ds,  ax			; Set DS to fardata segment
3459 
3460 		; Get the pointer mask address
3461 			les		si,  [MMASK]
3462 			mov		[MPointerMask_O], si
3463 			mov		ax,  es
3464 			mov		[MPointerMask_S], ax
3465 
3466 		; Set up user handler
3467 			les		si,  [HANDLER]
3468 			mov		[OFFSET Mouse_Hndlr_O], si
3469 			mov		ax,  es
3470 			mov		[OFFSET Mouse_Hndlr_O+2], ax
3471 
3472 		; !!DONE!!
3473 			mov		ax,	MOUSE_PRESENT   ; Return the mouse is present
3474 
3475 
3476 		; Set the new mickey counts
3477 		 	mov		ax,	000Fh		 ; Mouse driver routine
3478 			mov		cx,  8			 ; Double horizontal
3479 			mov		dx,  8			 ; Default vertical
3480 			int		033h				 ; Call routine	
3481 
3482 	@@Done:
3483 			pop		di si ds
3484 
3485 			pop		bp			; Return state
3486                ret
3487 
3488 ENDP			_XRegister_Mouse
3489 
3490 
3491 ; ------------------------ _Mouse_Active ---------------------------
3492 ; - Makes the mouse active and starts display of the pointer
3493 ; -
3494 public		_XMouse_Active
3495 
3496 PROC			_XMouse_Active
3497 
3498 	ARG	EMASK:WORD, STARTX:WORD, STARTY:WORD
3499 
3500 			push		bp
3501 			mov		bp,	sp		; Save Stack frame
3502 
3503 		; Save regs
3504 			push		ds si di
3505 
3506 		; Load DS.
3507 			ASSUME	ds:  @fardata
3508 			mov		ax,  @fardata
3509 			mov		ds,  ax			; Set DS to fardata segment
3510 
3511 			cld
3512 
3513 		; Save the users mask
3514 			mov		cx,	[EMASK]   	; Get user's mask
3515 			push		cx
3516 
3517 		; Set mouse reporting limits
3518 			mov		ax,  0007h	; Set X limits function
3519 			mov		cx,	0000h	; X minimum
3520 			mov       dx,  [ScreenSizeX]       ; X maximum
3521 			dec		dx
3522 			shl		dx,	1	; Comp for oddity
3523 			int		033h
3524 
3525 			mov		ax,	0008h	; Set Y limits function
3526 			mov		cx,	0000h     ; Y minimum
3527 			mov		dx,	[ScreenSizeY]		; Y maximum
3528 			dec		dx  			; Adjust for pointer size
3529 			int       033h
3530 
3531 	; -- Set up VGA Registers
3532 		; Set all data from latches
3533 			mov		dx,	GC_INDEX
3534 			mov		ax,	00000h + BIT_MASK  ; Set all latch writes
3535 			out		dx, 	ax
3536 
3537 		; Insure Map Mask is set to all planes
3538 			mov		ax,  0F02h	; 0F sets all planes. 02 is Map Mask
3539 			mov		dx,	SC_INDEX
3540 			out		dx,	ax
3541 
3542 	; -- Set the mouse's position and display the pointer
3543 
3544 		; Let the driver know where the mouse pointer is
3545 			mov		ax,	0004h	; Set mouse pointer position func
3546 
3547 			mov		cx,	[STARTX]	; Set X coord
3548 			mov		dx,	[STARTY]	; Set Y coord
3549 
3550 			mov       [MLastX], cx   ; Save as last location
3551 			mov		[MLastY], dx
3552 
3553 			shl		cx,	1		; Comp
3554 
3555 			int		033h			; Call function
3556 
3557 		; Reload background & fake a mouse event to put the pointer
3558 		; on the screen the first time
3559 
3560 	; -- Do the reload
3561 
3562 		; Return CX to actual coord
3563 			shr		cx,	1
3564 
3565 		; Set SI to start of rectangle on screen
3566 			mov 		ax,  [DLine_Offset] ; Get line size
3567 			mov		bx,  [MLastY]       ; Get Y into view
3568 			mov		di,	bx			; Save in DI
3569 			add	     bx,  [ViewYLoc]     ; Add start of view
3570 			mul		bx			   ; Find Y offset value. Place in AX
3571 
3572 			mov		si,  [MLastX]     ; Find X offset value. Place in DI
3573 			mov		bp,  si		   ; Save in BP for later
3574 			add		si,  [ViewXLoc]   ; Get start of view and add it
3575 			shr		si,  1
3576 			shr		si,  1
3577 
3578 			add		si,  ax		     ; Add X and Y offsets
3579 			add		si,  [Display_Page] ; Add in page offset
3580 
3581 		; See if we need to clip Second XBlock
3582 			mov		cx,		2			; Assume 2 XBlocks to write
3583 			mov		dx,       [ScreenSizeX]	; Get screen size
3584 			sub		dx,		4			; Get 2nd to last XBlock
3585 			cmp		dx,		bp             ; BP from above.
3586 			jge       @@Continue3			; Both blocks on reload
3587 			dec		cx					; Only one block on reload
3588 
3589 	@@Continue3:
3590 		; Set DX to number of lines to reload
3591 			mov		dx,	8		; Assume 8 scan lines
3592 			mov		bx, 	di		; Get Y last and put in BX (from SI)
3593 			mov		ax,	[ScreenSizeY] ; Get Screen size Y and put in ax
3594 			sub		ax,	8		; Subtract to make mimimum clip
3595 
3596 			cmp		ax,	bx		; Does it need clipping?
3597 			jg		@@Continue4	; No, then go!
3598 
3599 			sub		bx,  ax		; Needs clipping!  Find new DX
3600 			sub		dx,	bx
3601 
3602 	@@Continue4:
3603 
3604 		; Set BP to scan line dif.
3605 			mov		bp,	[DLine_Offset]
3606 			sub		bp,  cx
3607 
3608 		; Get the Screen Seg and put it in DS and ES
3609 			mov		ax,  SCREEN_SEG
3610 			mov		ds,	ax
3611 			mov		es,  ax
3612 
3613 		; Set destination
3614 			mov		di,	MSAVEOFFSET
3615 
3616 		; Save CX in BX
3617 			mov		bx,	cx
3618 
3619 	   ; This section is for the MOVE ------------------------------
3620 	   ; Completely unrolled
3621 
3622 	@@RowLoop2:
3623 		; Do line
3624 			rep		movsb	; One or two XBlocks
3625 
3626 		; Prep for next line
3627 			add		si,	bp	; Point SI to start of next line
3628 			mov		cx,	bx	; Restore CX
3629 
3630 		; Are we done?
3631 			dec		dx
3632 			jnz		@@RowLoop2	; No, then go and do another
3633 
3634 	  ; - Done with Reload
3635 
3636 		; Load DS.
3637 			ASSUME	ds:  @fardata
3638 			mov		ax,  @fardata
3639 			mov		ds,  ax			; Set DS to fardata segment
3640 
3641 		; Ensure the mouse is not locked
3642 			mov		ax,			NOTLOCKM
3643 			mov		[LockHandler], ax
3644 
3645 		; Fake a mouse event and call handler
3646 			mov		ax,	0001h	; Indicate a move
3647 			mov		bx,	0000h	; No info
3648 			mov		cx,  [MLastX]  ; X coord
3649 			shl		cx, 	1		; Double, that's how it is expected
3650 			mov		dx,	[MLastY]  ; Y coord
3651 
3652 			call		_MEvent_Handler
3653 
3654 		; Get the users event mask, save, and build our mask in cx
3655 			pop		cx				; Get the Mask back
3656 			mov		[MUEventMask], cx   ; Save it
3657 			or		cx,  0001h          ; Build ours
3658 						; We must make sure all moves are reported
3659 
3660 		; Define XTile's handler and register it with the mouse driver
3661 			mov		ax,	0000Ch	; Function number
3662 
3663 			mov		dx,	cs		; Get XTile's handler address
3664 			mov		es,	dx
3665 			mov		dx,  OFFSET _MEvent_Handler
3666 
3667 			int		033h			; Call the mouse driver
3668 		; !!DONE!!
3669 
3670 			pop		di si ds		; Restore regs
3671 
3672 			pop		bp			; Return state
3673 			ret
3674 
3675 ENDP			_XMouse_Active
3676 
3677 
3678 ; ------------------------ _XMouse_InActive ---------------------------
3679 ; - Turns off the mouse.  Restores background to last known mouse position.
3680 ; -
3681 public		_XMouse_InActive
3682 
3683 PROC			_XMouse_InActive
3684 
3685 			push		bp
3686 			mov		bp,	sp		; Save Stack frame
3687 
3688 		; Save regs
3689 			push		ds si di
3690 
3691 		; Register with mouse driver that we don't want any more reports
3692 			mov		ax,	0000Ch	; Function number
3693 			mov		cx,	00000h	; Clear flag
3694 			mov		dx,	00000h	; Get XTile's handler address
3695 			mov		es,	dx
3696 			mov		dx,  00000h
3697 
3698 			int		033h			; Call the mouse driver
3699 
3700 		; Load DS with local segment
3701 			ASSUME	ds:  @fardata
3702 			mov		ax,  @fardata
3703 			mov		ds,  ax		; Set DS to fardata segment
3704 
3705 		; Ensure the mouse is locked
3706 			mov		ax,			LOCKM
3707 			mov		[LockHandler], ax
3708 
3709 		; Clear the users mask
3710 			mov		cx,	0000h   		; Set to no events
3711 			mov		[MUEventMask], cx   ; Save it
3712 
3713 	; ---- This is the restore
3714 			cld
3715 
3716 		; Set DI to start of rectangle on screen
3717 			mov 		ax,  [DLine_Offset] ; Get line size
3718 			mov		bx,  [MLastY]       ; Get Y into view
3719 			mov		si,  bx 			; Save in SI
3720 			add	     bx,  [ViewYLoc]     ; Add start of view
3721 			mul		bx			   ; Find Y offset value. Place in AX
3722 
3723 			mov		di,  [MLastX]     ; Find X offset value. Place in DI
3724 			mov		bp,  di		   ; Save X in BP
3725 			add		di,  [ViewXLoc]   ; Get start of view and add it
3726 			shr		di,  1
3727 			shr		di,  1
3728 
3729 			add		di,  ax		     ; Add X and Y offsets
3730 			add		di,  [Display_Page] ; Add in page offset
3731 
3732 
3733 		; See if we need to clip Second XBlock
3734 			mov		cx,		2			; Assume 2 XBlocks to write
3735 			mov		dx,       [ScreenSizeX]	; Get screen size
3736 			sub		dx,		4			; Get 2nd to last XBlock
3737 			cmp		dx,		bp
3738 			ja        @@Continue			; Both blocks on reload
3739 			dec		cx					; Only one block on reload
3740 
3741 	@@Continue:
3742 		; Set all data from latches
3743 			mov		ax,	GC_INDEX
3744 			mov		ax,	00000h + BIT_MASK  ; Set all latch writes
3745 			out		dx, 	ax
3746 
3747 		; Insure Map Mask is set to all planes
3748 			mov		ax,  0F02h	; 0F sets all planes. 02 is Map Mask
3749 			mov		dx,	SC_INDEX
3750 			out		dx,	ax
3751 
3752 		; Set DX to number of lines to display
3753 			mov		dx,	8		; Assume 8 scan lines
3754 			mov		ax,	[ScreenSizeY] ; Get Screen size Y and put in ax
3755 			sub		ax,	8		; Subtract to make mimimum clip
3756 
3757 			cmp		ax,	si		; Does it need clipping? (SI = last Y)
3758 			ja		@@ContinueC	; No, then go!
3759 
3760 			sub		si,  ax		; Needs clipping!  Find new DX
3761 			sub		dx,	si
3762 
3763 	@@ContinueC:
3764 		; Set BP to the distance from one scan line to next
3765 			mov		bp,	[DLine_Offset]
3766 			sub		bp,  cx    		; # XBlocks per scan line
3767 
3768 		; Get the Screen Seg and put it in DS and ES
3769 			mov		ax,  SCREEN_SEG
3770 			mov		ds,  ax
3771 			mov		es,	ax
3772 
3773 		; Set SI to source
3774 			mov		si,		MSAVEOFFSET
3775 
3776 		; Save number to move (CX) in BX
3777 			mov		bx,	cx
3778 
3779 	   ; This section is for WRITES ------------------------------
3780 	   ; The Reload will be clipped if appropriate
3781 
3782 	 @@RowLoop:
3783 		 ; Put 1 or 2 XBlocks
3784 			rep movsb
3785 
3786 		 ; Ready next iteration
3787 			add		di,	bp	; Point DI to start of next line
3788 
3789 		 ; Reload CX
3790 			mov		cx,	bx
3791 
3792 		 ; Are we done?
3793 			dec		dx
3794 			jnz		@@RowLoop	; No, then go and do another line
3795 
3796 
3797 	   ; -- DONE!!
3798 
3799 			pop		di si ds		; Restore regs
3800 			pop		bp			; Return state
3801                ret
3802 
3803 ENDP			_XMouse_InActive
3804 
3805 
3806 ; ------------------------ _XReload_TileW ---------------------------
3807 ; - This will "reload" a tile from the write page to display memory
3808 ; - storeage
3809 ; -
3810 public		_XReload_TileW
3811 
3812 PROC			_XReload_TileW
3813 
3814 	ARG	STARTX:WORD, STARTY:WORD, XDELTA:WORD, YDELTA:WORD, OFFST:WORD
3815 
3816 			push		bp
3817 			mov		bp,	sp		; Save Stack frame
3818 
3819 		; Save regs
3820 			push		ds si di
3821 
3822 		; Load DS.
3823 			ASSUME	ds:  @fardata
3824 			mov		ax,  @fardata
3825 			mov		ds,  ax			; Set DS to fardata segment
3826 
3827 	; -- Do the reload
3828 
3829 		; Set SI to start of rectangle on screen
3830 			mov 		ax,  [WLine_Offset] ; Get line size
3831 			mul		[STARTY]			; Find Y offset
3832 
3833 			mov		si,  [STARTX]     ; Find X offset value. Place in DI
3834 			shr		si,  1
3835 			shr		si,  1
3836 
3837 			add		si,  ax		     ; Add X and Y offsets
3838 			add		si,  [Write_Page]   ; Add in page offset
3839 
3840 		; Set destination
3841 			mov		di,	[OFFST]
3842 
3843 		; Set all data from latches
3844 			mov		dx,	GC_INDEX
3845 			mov		ax,	00000h + BIT_MASK  ; Set all latch writes
3846 			out		dx, 	ax
3847 
3848 		; Insure Map Mask is set to all planes
3849 			mov		ax,  0F02h	; 0F sets all planes. 02 is Map Mask
3850 			mov		dx,	SC_INDEX
3851 			out		dx,	ax
3852 
3853 		; Set CX to the number of XBlocks to move per scan line
3854 			mov       cx,  [XDELTA]
3855 			shr		cx,  1
3856 			shr		cx,  1
3857 
3858 		; Set BX to the number of scan lines to do
3859 			mov		bx,  [YDELTA]
3860 
3861 		; Set AX to scan line dif.
3862 			mov		ax,	[WLine_Offset]
3863 			sub		ax,  cx			; Scan size minus tile size
3864 
3865 		; Get the Screen Seg and put it in ES
3866 			mov		dx,  SCREEN_SEG
3867 			mov		es,	dx
3868 			mov		ds,	dx
3869 
3870 		; Save number of XBlocks (CX) in DX
3871 			mov		dx,  cx
3872 
3873 		; This section is for the MOVE ------------------------------
3874 		@@Rowloop:
3875 
3876 			rep  movsb
3877 
3878 		; Adjust for next iteration
3879 			add	si,	ax	; Point DI to start of next line
3880 
3881 		; Re-load CX
3882 			mov  cx,  dx
3883 
3884 		; End of Rowloop.
3885 			dec	  bx
3886 			jnz    @@Rowloop
3887 
3888 
3889 		; DONE!!!
3890 			pop    di si ds
3891 
3892 			pop	  bp			; Return state
3893 			ret
3894 
3895 ENDP	   _XReload_TileW
3896 
3897 
3898 ; ------------------------ _XSet_Clip ---------------------------
3899 ; - This will set the clip boundries
3900 ; -
3901 public		_XSet_Clip
3902 
3903 PROC			_XSet_Clip
3904 
3905 	ARG	STARTX:WORD, STARTY:WORD, ENDX:WORD, ENDY:WORD
3906 
3907 			push		bp
3908 			mov		bp,	sp		; Save Stack frame
3909 
3910 		; Save regs
3911 			push		ds
3912 
3913 		; Load DS.
3914 			ASSUME	ds:  @fardata
3915 			mov		ax,  @fardata
3916 			mov		ds,  ax			; Set DS to fardata segment
3917 
3918 	; -- Load the values
3919 			mov		ax,		[STARTX]
3920 			mov		[ClipSX],	ax
3921 			mov		ax,		[STARTY]
3922 			mov		[ClipSY],	ax
3923 			mov		ax,		[ENDX]
3924 			mov		[ClipEX],	ax
3925 			mov		ax,		[ENDY]
3926 			mov		[ClipEY],	ax
3927 
3928 		; DONE!!!
3929 			pop    ds
3930 
3931 			pop	  bp			; Return state
3932 			ret
3933 
3934 ENDP	   _XSet_Clip
3935 
3936 
3937 ENDS
3938 
3939 END