ID_VL_A.ASM (13243B)
1 ; ID_VL.ASM 2 3 IDEAL 4 MODEL MEDIUM,C 5 6 INCLUDE 'ID_VL.EQU' 7 8 SCREENSEG = 0a000h 9 10 DATASEG 11 12 EXTRN TimeCount:WORD ; incremented every 70th of a second 13 EXTRN linewidth:WORD 14 15 starttime dw ? 16 17 CODESEG 18 19 ;=========================================================================== 20 21 22 ;============== 23 ; 24 ; VL_WaitVBL ******** NEW ********* 25 ; 26 ; Wait for the vertical retrace (returns before the actual vertical sync) 27 ; 28 ;============== 29 30 PROC VL_WaitVBL num:WORD 31 PUBLIC VL_WaitVBL 32 @@wait: 33 34 mov dx,STATUS_REGISTER_1 35 36 mov cx,[num] 37 ; 38 ; wait for a display signal to make sure the raster isn't in the middle 39 ; of a sync 40 ; 41 @@waitnosync: 42 in al,dx 43 test al,8 44 jnz @@waitnosync 45 46 47 @@waitsync: 48 in al,dx 49 test al,8 50 jz @@waitsync 51 52 loop @@waitnosync 53 54 ret 55 56 ENDP 57 58 59 ;=========================================================================== 60 61 ;============== 62 ; 63 ; VL_SetCRTC 64 ; 65 ;============== 66 67 PROC VL_SetCRTC crtc:WORD 68 PUBLIC VL_SetCRTC 69 70 ; 71 ; wait for a display signal to make sure the raster isn't in the middle 72 ; of a sync 73 ; 74 cli 75 76 mov dx,STATUS_REGISTER_1 77 78 @@waitdisplay: 79 in al,dx 80 test al,1 ;1 = display is disabled (HBL / VBL) 81 jnz @@waitdisplay 82 83 84 ; 85 ; set CRTC start 86 ; 87 ; for some reason, my XT's EGA card doesn't like word outs to the CRTC 88 ; index... 89 ; 90 mov cx,[crtc] 91 mov dx,CRTC_INDEX 92 mov al,0ch ;start address high register 93 out dx,al 94 inc dx 95 mov al,ch 96 out dx,al 97 dec dx 98 mov al,0dh ;start address low register 99 out dx,al 100 mov al,cl 101 inc dx 102 out dx,al 103 104 105 sti 106 107 ret 108 109 ENDP 110 111 112 113 ;=========================================================================== 114 115 ;============== 116 ; 117 ; VL_SetScreen 118 ; 119 ;============== 120 121 PROC VL_SetScreen crtc:WORD, pel:WORD 122 PUBLIC VL_SetScreen 123 124 125 mov cx,[timecount] ; if timecount goes up by two, the retrace 126 add cx,2 ; period was missed (an interrupt covered it) 127 128 mov dx,STATUS_REGISTER_1 129 130 ; 131 ; wait for a display signal to make sure the raster isn't in the middle 132 ; of a sync 133 ; 134 @@waitdisplay: 135 in al,dx 136 test al,1 ;1 = display is disabled (HBL / VBL) 137 jnz @@waitdisplay 138 139 140 @@loop: 141 sti 142 jmp $+2 143 cli 144 145 cmp [timecount],cx ; will only happen if an interrupt is 146 jae @@setcrtc ; straddling the entire retrace period 147 148 ; 149 ; when several succesive display not enableds occur, 150 ; the bottom of the screen has been hit 151 ; 152 153 in al,dx 154 test al,8 155 jnz @@waitdisplay 156 test al,1 157 jz @@loop 158 159 in al,dx 160 test al,8 161 jnz @@waitdisplay 162 test al,1 163 jz @@loop 164 165 in al,dx 166 test al,8 167 jnz @@waitdisplay 168 test al,1 169 jz @@loop 170 171 in al,dx 172 test al,8 173 jnz @@waitdisplay 174 test al,1 175 jz @@loop 176 177 in al,dx 178 test al,8 179 jnz @@waitdisplay 180 test al,1 181 jz @@loop 182 183 184 @@setcrtc: 185 186 187 ; 188 ; set CRTC start 189 ; 190 ; for some reason, my XT's EGA card doesn't like word outs to the CRTC 191 ; index... 192 ; 193 mov cx,[crtc] 194 mov dx,CRTC_INDEX 195 mov al,0ch ;start address high register 196 out dx,al 197 inc dx 198 mov al,ch 199 out dx,al 200 dec dx 201 mov al,0dh ;start address low register 202 out dx,al 203 mov al,cl 204 inc dx 205 out dx,al 206 207 ; 208 ; set horizontal panning 209 ; 210 mov dx,ATR_INDEX 211 mov al,ATR_PELPAN or 20h 212 out dx,al 213 jmp $+2 214 mov al,[BYTE pel] ;pel pan value 215 out dx,al 216 217 sti 218 219 ret 220 221 ENDP 222 223 224 ;=========================================================================== 225 226 227 ;============================================================================ 228 ; 229 ; VL_ScreenToScreen 230 ; 231 ; Basic block copy routine. Copies one block of screen memory to another, 232 ; using write mode 1 (sets it and returns with write mode 0). bufferofs is 233 ; NOT accounted for. 234 ; 235 ;============================================================================ 236 237 PROC VL_ScreenToScreen source:WORD, dest:WORD, wide:WORD, height:WORD 238 PUBLIC VL_ScreenToScreen 239 USES SI,DI 240 241 pushf 242 cli 243 244 mov dx,SC_INDEX 245 mov ax,SC_MAPMASK+15*256 246 out dx,ax 247 mov dx,GC_INDEX 248 mov al,GC_MODE 249 out dx,al 250 inc dx 251 in al,dx 252 and al,NOT 3 253 or al,1 254 out dx,al 255 256 popf 257 258 mov bx,[linewidth] 259 sub bx,[wide] 260 261 mov ax,SCREENSEG 262 mov es,ax 263 mov ds,ax 264 265 mov si,[source] 266 mov di,[dest] ;start at same place in all planes 267 mov dx,[height] ;scan lines to draw 268 mov ax,[wide] 269 270 @@lineloop: 271 mov cx,ax 272 rep movsb 273 add si,bx 274 add di,bx 275 276 dec dx 277 jnz @@lineloop 278 279 mov dx,GC_INDEX+1 280 in al,dx 281 and al,NOT 3 282 out dx,al 283 284 mov ax,ss 285 mov ds,ax ;restore turbo's data segment 286 287 ret 288 289 ENDP 290 291 292 ;=========================================================================== 293 294 295 MASM 296 ;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ 297 ; 298 ; Name: VL_VideoID 299 ; 300 ; Function: Detects the presence of various video subsystems 301 ; 302 ; int VideoID; 303 ; 304 ; Subsystem ID values: 305 ; 0 = (none) 306 ; 1 = MDA 307 ; 2 = CGA 308 ; 3 = EGA 309 ; 4 = MCGA 310 ; 5 = VGA 311 ; 80h = HGC 312 ; 81h = HGC+ 313 ; 82h = Hercules InColor 314 ; 315 ;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ 316 317 ;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ 318 ; 319 ; Equates 320 ; 321 ;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ 322 VIDstruct STRUC ; corresponds to C data structure 323 324 Video0Type DB ? ; first subsystem type 325 Display0Type DB ? ; display attached to first subsystem 326 327 Video1Type DB ? ; second subsystem type 328 Display1Type DB ? ; display attached to second subsystem 329 330 VIDstruct ENDS 331 332 333 Device0 EQU word ptr Video0Type[di] 334 Device1 EQU word ptr Video1Type[di] 335 336 337 MDA EQU 1 ; subsystem types 338 CGA EQU 2 339 EGA EQU 3 340 MCGA EQU 4 341 VGA EQU 5 342 HGC EQU 80h 343 HGCPlus EQU 81h 344 InColor EQU 82h 345 346 MDADisplay EQU 1 ; display types 347 CGADisplay EQU 2 348 EGAColorDisplay EQU 3 349 PS2MonoDisplay EQU 4 350 PS2ColorDisplay EQU 5 351 352 TRUE EQU 1 353 FALSE EQU 0 354 355 ;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ 356 ; 357 ; Program 358 ; 359 ;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ 360 361 Results VIDstruct <> ;results go here! 362 363 EGADisplays DB CGADisplay ; 0000b, 0001b (EGA switch values) 364 DB EGAColorDisplay ; 0010b, 0011b 365 DB MDADisplay ; 0100b, 0101b 366 DB CGADisplay ; 0110b, 0111b 367 DB EGAColorDisplay ; 1000b, 1001b 368 DB MDADisplay ; 1010b, 1011b 369 370 DCCtable DB 0,0 ; translate table for INT 10h func 1Ah 371 DB MDA,MDADisplay 372 DB CGA,CGADisplay 373 DB 0,0 374 DB EGA,EGAColorDisplay 375 DB EGA,MDADisplay 376 DB 0,0 377 DB VGA,PS2MonoDisplay 378 DB VGA,PS2ColorDisplay 379 DB 0,0 380 DB MCGA,EGAColorDisplay 381 DB MCGA,PS2MonoDisplay 382 DB MCGA,PS2ColorDisplay 383 384 TestSequence DB TRUE ; this list of flags and addresses 385 DW FindPS2 ; determines the order in which this 386 ; program looks for the various 387 EGAflag DB ? ; subsystems 388 DW FindEGA 389 390 CGAflag DB ? 391 DW FindCGA 392 393 Monoflag DB ? 394 DW FindMono 395 396 NumberOfTests EQU ($-TestSequence)/3 397 398 399 PUBLIC VL_VideoID 400 VL_VideoID PROC 401 402 push bp ; preserve caller registers 403 mov bp,sp 404 push ds 405 push si 406 push di 407 408 push cs 409 pop ds 410 ASSUME DS:@Code 411 412 ; initialize the data structure that will contain the results 413 414 lea di,Results ; DS:DI -> start of data structure 415 416 mov Device0,0 ; zero these variables 417 mov Device1,0 418 419 ; look for the various subsystems using the subroutines whose addresses are 420 ; tabulated in TestSequence; each subroutine sets flags in TestSequence 421 ; to indicate whether subsequent subroutines need to be called 422 423 mov byte ptr CGAflag,TRUE 424 mov byte ptr EGAflag,TRUE 425 mov byte ptr Monoflag,TRUE 426 427 mov cx,NumberOfTests 428 mov si,offset TestSequence 429 430 @@L01: lodsb ; AL := flag 431 test al,al 432 lodsw ; AX := subroutine address 433 jz @@L02 ; skip subroutine if flag is false 434 435 push si 436 push cx 437 call ax ; call subroutine to detect subsystem 438 pop cx 439 pop si 440 441 @@L02: loop @@L01 442 443 ; determine which subsystem is active 444 445 call FindActive 446 447 mov al,Results.Video0Type 448 mov ah,0 ; was: Results.Display0Type 449 450 pop di ; restore caller registers and return 451 pop si 452 pop ds 453 mov sp,bp 454 pop bp 455 ret 456 457 VL_VideoID ENDP 458 459 460 ; 461 ; FindPS2 462 ; 463 ; This subroutine uses INT 10H function 1Ah to determine the video BIOS 464 ; Display Combination Code (DCC) for each video subsystem present. 465 ; 466 467 FindPS2 PROC near 468 469 mov ax,1A00h 470 int 10h ; call video BIOS for info 471 472 cmp al,1Ah 473 jne @@L13 ; exit if function not supported (i.e., 474 ; no MCGA or VGA in system) 475 476 ; convert BIOS DCCs into specific subsystems & displays 477 478 mov cx,bx 479 xor bh,bh ; BX := DCC for active subsystem 480 481 or ch,ch 482 jz @@L11 ; jump if only one subsystem present 483 484 mov bl,ch ; BX := inactive DCC 485 add bx,bx 486 mov ax,[bx+offset DCCtable] 487 488 mov Device1,ax 489 490 mov bl,cl 491 xor bh,bh ; BX := active DCC 492 493 @@L11: add bx,bx 494 mov ax,[bx+offset DCCtable] 495 496 mov Device0,ax 497 498 ; reset flags for subsystems that have been ruled out 499 500 mov byte ptr CGAflag,FALSE 501 mov byte ptr EGAflag,FALSE 502 mov byte ptr Monoflag,FALSE 503 504 lea bx,Video0Type[di] ; if the BIOS reported an MDA ... 505 cmp byte ptr [bx],MDA 506 je @@L12 507 508 lea bx,Video1Type[di] 509 cmp byte ptr [bx],MDA 510 jne @@L13 511 512 @@L12: mov word ptr [bx],0 ; ... Hercules can't be ruled out 513 mov byte ptr Monoflag,TRUE 514 515 @@L13: ret 516 517 FindPS2 ENDP 518 519 520 ; 521 ; FindEGA 522 ; 523 ; Look for an EGA. This is done by making a call to an EGA BIOS function 524 ; which doesn't exist in the default (MDA, CGA) BIOS. 525 526 FindEGA PROC near ; Caller: AH = flags 527 ; Returns: AH = flags 528 ; Video0Type and 529 ; Display0Type updated 530 531 mov bl,10h ; BL := 10h (return EGA info) 532 mov ah,12h ; AH := INT 10H function number 533 int 10h ; call EGA BIOS for info 534 ; if EGA BIOS is present, 535 ; BL <> 10H 536 ; CL = switch setting 537 cmp bl,10h 538 je @@L22 ; jump if EGA BIOS not present 539 540 mov al,cl 541 shr al,1 ; AL := switches/2 542 mov bx,offset EGADisplays 543 xlat ; determine display type from switches 544 mov ah,al ; AH := display type 545 mov al,EGA ; AL := subystem type 546 call FoundDevice 547 548 cmp ah,MDADisplay 549 je @@L21 ; jump if EGA has a monochrome display 550 551 mov CGAflag,FALSE ; no CGA if EGA has color display 552 jmp short @@L22 553 554 @@L21: mov Monoflag,FALSE ; EGA has a mono display, so MDA and 555 ; Hercules are ruled out 556 @@L22: ret 557 558 FindEGA ENDP 559 560 ; 561 ; FindCGA 562 ; 563 ; This is done by looking for the CGA's 6845 CRTC at I/O port 3D4H. 564 ; 565 FindCGA PROC near ; Returns: VIDstruct updated 566 567 mov dx,3D4h ; DX := CRTC address port 568 call Find6845 569 jc @@L31 ; jump if not present 570 571 mov al,CGA 572 mov ah,CGADisplay 573 call FoundDevice 574 575 @@L31: ret 576 577 FindCGA ENDP 578 579 ; 580 ; FindMono 581 ; 582 ; This is done by looking for the MDA's 6845 CRTC at I/O port 3B4H. If 583 ; a 6845 is found, the subroutine distinguishes between an MDA 584 ; and a Hercules adapter by monitoring bit 7 of the CRT Status byte. 585 ; This bit changes on Hercules adapters but does not change on an MDA. 586 ; 587 ; The various Hercules adapters are identified by bits 4 through 6 of 588 ; the CRT Status value: 589 ; 590 ; 000b = HGC 591 ; 001b = HGC+ 592 ; 101b = InColor card 593 ; 594 595 FindMono PROC near ; Returns: VIDstruct updated 596 597 mov dx,3B4h ; DX := CRTC address port 598 call Find6845 599 jc @@L44 ; jump if not present 600 601 mov dl,0BAh ; DX := 3BAh (status port) 602 in al,dx 603 and al,80h 604 mov ah,al ; AH := bit 7 (vertical sync on HGC) 605 606 mov cx,8000h ; do this 32768 times 607 @@L41: in al,dx 608 and al,80h ; isolate bit 7 609 cmp ah,al 610 loope @@L41 ; wait for bit 7 to change 611 jne @@L42 ; if bit 7 changed, it's a Hercules 612 613 mov al,MDA ; if bit 7 didn't change, it's an MDA 614 mov ah,MDADisplay 615 call FoundDevice 616 jmp short @@L44 617 618 @@L42: in al,dx 619 mov dl,al ; DL := value from status port 620 and dl,01110000b ; mask bits 4 thru 6 621 622 mov ah,MDADisplay ; assume it's a monochrome display 623 624 mov al,HGCPlus ; look for an HGC+ 625 cmp dl,00010000b 626 je @@L43 ; jump if it's an HGC+ 627 628 mov al,HGC ; look for an InColor card or HGC 629 cmp dl,01010000b 630 jne @@L43 ; jump if it's not an InColor card 631 632 mov al,InColor ; it's an InColor card 633 mov ah,EGAColorDisplay 634 635 @@L43: call FoundDevice 636 637 @@L44: ret 638 639 FindMono ENDP 640 641 ; 642 ; Find6845 643 ; 644 ; This routine detects the presence of the CRTC on a MDA, CGA or HGC. 645 ; The technique is to write and read register 0Fh of the chip (cursor 646 ; low). If the same value is read as written, assume the chip is 647 ; present at the specified port addr. 648 ; 649 650 Find6845 PROC near ; Caller: DX = port addr 651 ; Returns: cf set if not present 652 mov al,0Fh 653 out dx,al ; select 6845 reg 0Fh (Cursor Low) 654 inc dx 655 in al,dx ; AL := current Cursor Low value 656 mov ah,al ; preserve in AH 657 mov al,66h ; AL := arbitrary value 658 out dx,al ; try to write to 6845 659 660 mov cx,100h 661 @@L51: loop @@L51 ; wait for 6845 to respond 662 663 in al,dx 664 xchg ah,al ; AH := returned value 665 ; AL := original value 666 out dx,al ; restore original value 667 668 cmp ah,66h ; test whether 6845 responded 669 je @@L52 ; jump if it did (cf is reset) 670 671 stc ; set carry flag if no 6845 present 672 673 @@L52: ret 674 675 Find6845 ENDP 676 677 678 ; 679 ; FindActive 680 ; 681 ; This subroutine stores the currently active device as Device0. The 682 ; current video mode determines which subsystem is active. 683 ; 684 685 FindActive PROC near 686 687 cmp word ptr Device1,0 688 je @@L63 ; exit if only one subsystem 689 690 cmp Video0Type[di],4 ; exit if MCGA or VGA present 691 jge @@L63 ; (INT 10H function 1AH 692 cmp Video1Type[di],4 ; already did the work) 693 jge @@L63 694 695 mov ah,0Fh 696 int 10h ; AL := current BIOS video mode 697 698 and al,7 699 cmp al,7 ; jump if monochrome 700 je @@L61 ; (mode 7 or 0Fh) 701 702 cmp Display0Type[di],MDADisplay 703 jne @@L63 ; exit if Display0 is color 704 jmp short @@L62 705 706 @@L61: cmp Display0Type[di],MDADisplay 707 je @@L63 ; exit if Display0 is monochrome 708 709 @@L62: mov ax,Device0 ; make Device0 currently active 710 xchg ax,Device1 711 mov Device0,ax 712 713 @@L63: ret 714 715 FindActive ENDP 716 717 718 ; 719 ; FoundDevice 720 ; 721 ; This routine updates the list of subsystems. 722 ; 723 724 FoundDevice PROC near ; Caller: AH = display # 725 ; AL = subsystem # 726 ; Destroys: BX 727 lea bx,Video0Type[di] 728 cmp byte ptr [bx],0 729 je @@L71 ; jump if 1st subsystem 730 731 lea bx,Video1Type[di] ; must be 2nd subsystem 732 733 @@L71: mov [bx],ax ; update list entry 734 ret 735 736 FoundDevice ENDP 737 738 IDEAL 739 740 741 742 END