home *** CD-ROM | disk | FTP | other *** search
- page 60,132
- title Ega720 Hercules-compatible resident driver for EGA cards
-
- ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- ; This program demonstrates how to program an Enhanced Graphics Adapter driving
- ; a Monochrome display in a Hercules-compatible 720x348 mode. It will work
- ; with *any* EGA card with at least 128K memory. It does not require an
- ; EGA clones with built-in Hercules emulation. However, it will NOT work if
- ; you have a CGA installed in addition to the EGA.
- ;
- ; You can run this as a "stay resident" program, and patch existing Hercules-
- ; compatible programs to call it so they can run on an EGA in graphics mode.
- ; (Or similarly, patch a program that does know about the EGA to run in the
- ; higher 720x348 resolution instead of the normal 640x350 EGA resolution, by
- ; using its Hercules driver instead of its EGA driver.)
- ;
- ; Or, you can incorporate this code into your own program to provide a higher
- ; resolution mode on Monochrome EGA's. In this case, ignore all the details
- ; about how to patch existing programs and look at the "DoInt" subroutine and
- ; the "HOW IT WORKS" discussion.
- ;
- ; The program does not make the EGA register-compatible with the Hercules,
- ; however it does give the same memory map and 720 pixel wide display as the
- ; Hercules card. To make an existing Hercules program work with this program,
- ; you will have to patch that program so that its initialization code calls
- ; this routine instead of loading the Hercules registers. Once the card is
- ; initialized, the program can write to the display buffer just as if it were
- ; writing to a Hercules card.
- ;
- ; ***HOW TO INSTALL THIS PROGRAM***
- ;
- ; Assemble, link, and exe2bin this file. Then run it. It installs a routine
- ; under Interrupt 68h (normally unused). If INT 68h is in use for something
- ; else on your system, change the interrupt number below.
- ;
- ; ***HOW TO PATCH AN EXISTING PROGRAM***
- ;
- ; To patch an existing Hercules-compatible program, you will need to use
- ; DEBUG to: 1) find the Hercules initialization code, 2) determine whether it
- ; uses Hercules Page 0, Page 1, or both, and 3) patch in an appropriate INT 68h
- ; call.
- ;
- ; Hercules initialization code will consist of some OUT instructions to these
- ; registers: 3BFh, 3B8h, 3B4h, and 3B5h. The sequence will be something like:
- ;
- ; Output the value 1 or 3 to 3BFh (this may be omitted in older programs)
- ; Output any value with bit 3 off to 3B8h (turns video off)
- ; A loop writing various values to 3B4h and 3B5h (loads CRTC registers)
- ; Output a value with bit 3 on to 3B8h (turns video back on)
- ;
- ; * This last output gives you some critical information. Look at the values
- ; of bits 1 and 7 in particular:
- ; Bit 1 (mask 02h): 0 = text mode, 1 = graphics mode.
- ; Bit 7 (mask 80h): 0 = page 0, 1 = page 1.
- ;
- ; To find the code, you can use the Search command in DEBUG something like:
- ;
- ; -s 100 l xxxx bf 3
- ; or
- ; -s 100 l xxxx b8 3
- ;
- ; where xxxx is the value in register CX. If the program has a separate
- ; Hercules driver, that's the file you should be looking in. If not, try
- ; the program file itself (if a .EXE file do the usual trick of renaming it
- ; to a different extension, because you will need to write it back out.)
- ;
- ; If the initialization sequence is setting TEXT mode, replace it with a
- ; normal BIOS "set mode" call.
- ;
- ; mov ah,0 ; (You're in DEBUG, so hex is default)
- ; mov al,7 ; (Yes, this could just be a MOV AX)
- ; int 10
- ;
- ; You may find code that loads the Hercules registers and then also does a
- ; BIOS set mode call. In that case, just patch out the Hercules code and
- ; let the set mode do its thing. Or there may just be a BIOS call. Leave
- ; it alone.
- ;
- ; If the initialization sequence is setting GRAPHICS mode, replace it with
- ; a call to this resident routine:
- ;
- ; mov al,80 *or* 00 ; 80 for page 1, 00 for page 0
- ; int 68
- ;
- ; Use 80 or 00 depending on whether you found the initialization code to be
- ; using page 1 or page 0. For example, Microsoft Windows uses page 1, while
- ; Framework version 1 uses page 0.
- ;
- ; Naturally, when making these patches you should look at the surrounding code
- ; to duplicate any register saving, return values, NEAR or FAR return, etc.
- ; Note that the INT 10 and INT 68 calls preserve all registers except AX.
- ;
- ; These patches will be sufficient for many programs. If you have a program
- ; that uses both Hercules pages 0 and 1 and flips back and forth between them,
- ; you will need to do some additional work. The program will contain
- ; additional output instructions to port 3B8, with bit 7 (mask 80h) on or off.
- ; Replace these with:
- ;
- ; mov al,81 *or* 01 ; 81 for page 1, 01 for page 0
- ; int 68
- ;
- ; *Note* I haven't tested this option, sorry.
- ;
- ; ***A SAMPLE PATCH - MICROSOFT WINDOWS***
- ;
- ; To patch Microsoft Windows for this high resolution mode, do the following:
- ; (This is for Windows version 1.01, either the retail or Developer's version)
- ;
- ; 1. **Make COPIES of your SETUP and BUILD disks**
- ; **Use the COPIES. DO NOT MODIFY YOUR ORIGINALS!!**
- ;
- ; 2. On your SETUP disk, apply this patch:
- ;
- ; A>debug hercules.drv
- ; -a a97
- ; xxxx:0A97 mov al,80
- ; xxxx:0A99 int 68
- ; xxxx:0A9B mov al,1
- ; xxxx:0A9D ret
- ; xxxx:0A9E
- ; -a ab2
- ; xxxx:0AB2 mov ah,0
- ; xxxx:0AB4 int 10
- ; xxxx:0AB6 mov al,1
- ; xxxx:0AB8 ret
- ; xxxx:0AB9
- ; -w
- ; -q
- ;
- ; 3. On your BUILD disk, apply this patch:
- ;
- ; A>copy egamono.grb hercules.grb
- ;
- ; A>debug hercules.lgo
- ; -a 343
- ; xxxx:0343 mov al,80
- ; xxxx:0345 int 68
- ; xxxx:0347 ret
- ; xxxx:0348
- ; -w
- ; -q
- ;
- ; 4. Run SETUP to install Windows. When it asks for the display type,
- ; specify Hercules.
- ;
- ; You should be up and running in the higher resolution mode!
- ; The only problem I have found is that if you run an "old" application
- ; that takes over the screen it doesn't display the "press any key to
- ; return to Windows" message. This is done by HERCULES.GRB, which I didn't
- ; get patched, but instead took the shortcut of copying EGAMONO.GRB.
- ;
- ; NOTE: Microsoft has OK'd my uploading this patch (see BIX message
- ; microsoft/applications #192), but of course does not endorse or take
- ; any responsibility for it. Thank you Microsoft for a sensible attitude.
- ;
- ; I have also successfully patched Lotus 1-2-3 to run on the EGA in
- ; this mode, but will NOT make that patch available because Lotus is very
- ; unfriendly to people who patch their products. See BIX message
- ; spreadsheets/other #24. The words I have for Lotus are not printable.
- ;
- ; (I have also patched Framework version 1.1 but haven't yet checked with
- ; Ashton-Tate about uploading patches. Hint: It's HERCULES.DRV, and they
- ; use page 0, unlike Windows which uses page 1.)
- ;
- ; ***HOW IT WORKS***
- ;
- ; If you want to support the 720x348 mode in a program of your own, this is
- ; the section of interest to you. (Or you can ignore this and just use the
- ; code.)
- ;
- ; This program uses some EGA features which are not used in the standard modes.
- ; Page number references are from the August 2, 1984 EGA manual.
- ;
- ; The "Memory Map" bits in Graphics Controller register 6 ("Miscellaneous
- ; Register") are set to 00. This maps the EGA display memory into a full
- ; 128K bytes from A0000h to BFFFFh. This is why you can't have a CGA in
- ; the same machine. Theoretically, you could set these to 10 if you were
- ; using Hercules page 0 (B0000-B7FFF) and then you could co-exist with a CGA.
- ; I didn't get this to work, however. (p.53)
- ;
- ; In this 128K mode (only), bit 5 of the Miscellaneous Output Register selects
- ; which 64K block is displayed. This is described wrong in the manual. All
- ; standard modes set this to 1. We set it to 0, which selects the higher
- ; 64K block (B0000-BFFFF). 1 would give us A0000-AFFFF. (p.13)
- ;
- ; Like in the standard modes, we then use CRTC registers 0C/0D (Start Address)
- ; to select the display base address within that 64K block. This selects
- ; Hercules page 0 or 1. (p.34)
- ;
- ; The "native" EGA graphics modes use linear addressing, where each scan line
- ; begins in memory right after the previous one. The CGA has a strange
- ; interleaving, where alternate rows are offset by 2000h. The Hercules card
- ; is like the CGA except it uses groups of four rows instead of two. So your
- ; row addressing is like this:
- ; Row 0: 0000h
- ; Row 1: 2000h
- ; Row 2: 4000h
- ; Row 3: 6000h
- ; Row 4: 0000h + (size of one row = 90 bytes)
- ; Row 5: 2000h + 90
- ; etc.
- ;
- ; CRTC register 17h (Mode Control) contains two bits (bits 0 and 1) which
- ; control this addressing. In the EGA native modes, these bits are both 1,
- ; and addressing is linear. If bit 0 is 0, you get the CGA compatibility
- ; mode, with alternating lines offset by 2000h. If bits 0 and 1 are both 0,
- ; you get the Hercules addressing mode as shown above. Don't be misled by
- ; the funny name of bit 1 in the manual. It should have been called CMS 1
- ; because it is exactly like bit 0 (CMS 0). (p.41-42)
- ;
- ; If you are writing your own software to support the 720 mode, you may find
- ; it easier to use linear addressing instead of the funny Hercules/CGA style
- ; addressing. To do this, set both these bits to 1 instead of 0. Fiddle
- ; with the CRTC registers a little and you will then get a 720x350 mode.
- ; (Hercules is 348 because it had to be divisible by 4.) I haven't tested
- ; this, however.
- ;
- ; ***NO NONSENSE PUBLIC DOMAIN STATEMENT***
- ;
- ; This program and documentation are placed in the public domain. Period.
- ;
- ; June 22, 1986
- ;
- ; Michael Geary
- ; P.O. Box 1479
- ; Los Gatos, CA 95031
- ; BIX: geary
-
- HercInt equ 68h ; Interrupt to put EGA in Hercules mode
- ; Change this if INT 68h conflicts
- ; with something else
-
- Code SEGMENT
-
-
- Zseg SEGMENT at 0
-
- org HercInt*4 ; Our interrupt vector
- IntOff dw ?
- IntSeg dw ?
-
- org 4A8h ; EGA BIOS "Save Table" pointer
- SvXoff dw ?
- SvXseg dw ?
-
- Zseg ENDS
-
-
- Data SEGMENT byte
-
- ; This is a "Save Table" as used by the EGA BIOS. Since it is just used
- ; temporarily for our mode setting, we provide only the single parameter
- ; table instead of the full set.
-
- Table label dword
- dw offset Com:Params - (11h*40h)
- TblSeg dw ?
- dd 7 dup (?)
-
- Params label byte
-
- ; "Hercules" Mode F (large memory)
-
- ; cols, rows, lines
- db 05Ah, 018h, 00Eh
-
- ; page len
- dw 08000h
-
- ; sequencer
- db 001h, 001h, 000h, 006h
-
- ; miscoutreg
- db 086h
-
- ; crtc
- db 06Ch, 059h, 05Ch, 02Ch
- db 05Bh, 04Ch, 070h, 01Fh
- db 000h, 003h, 000h, 000h
- PageBit label byte
- db 000h, 000h, 000h, 000h
- db 05Dh, 02Dh, 05Bh, 02Dh
- db 00Dh, 05Ch, 06Ch, 0E0h, 0FFh
-
- ; attribute
- db 000h, 008h, 008h, 008h, 008h, 008h, 008h, 008h
- db 008h, 008h, 008h, 008h, 008h, 008h, 008h, 008h
- db 003h, 000h, 001h, 000h
-
- ; graphics
- db 000h, 000h, 000h, 000h, 000h, 000h, 001h, 00Fh, 0FFh
-
- Data ENDS
-
-
- Com GROUP Code, Data, Top
-
- ASSUME cs:Com, ds:Com, es:nothing, ss:nothing
-
- org 100h
-
- ; This is the code to install the resident driver. You won't need it if you
- ; are incorporating the 720 technique into your own program, of course.
-
- Start:
- xor ax, ax
- mov es, ax
- ASSUME es:Zseg
-
- CLI
-
- mov IntOff, offset Com:DoInt
- mov IntSeg, cs
-
- mov TblSeg, cs
-
- STI
-
- mov dx, offset Com:TopOff
- shr dx, 1
- shr dx, 1
- shr dx, 1
- shr dx, 1
-
- mov ax, 3100h
- int 21h ; Terminate and stay resident
-
- ASSUME ds:nothing
-
- ; This the code to set up the 720x348 mode. To make life easy, we
- ; temporarily set up a pointer to our register table and then let the BIOS
- ; do the work of loading all the registers.
-
- DoInt:
- push es
- push ax
-
- test al, 1 ; is it just a page flip?
- jnz Flip ; yes, just go do that
-
- ; Set up Hercules mode from scratch
- and al, 80h
- mov PageBit, al ; set page 0 or 1
-
- xor ax, ax
- mov es, ax
- ASSUME es:Zseg
-
- CLI
-
- push SvXoff ; save previous parameter table
- push SvXseg
-
- mov SvXoff, offset Com:Table ; temporarily set to our table
- mov SvXseg, cs
-
- STI
-
- mov ax, 000Fh ; call BIOS to do the mode setting
- int 10h ; using our parameters
-
- CLI
-
- pop SvXseg ; restore previous parameter table
- pop SvXoff
-
- STI
-
- return:
- pop ax
- pop es
-
- iret
-
- ; Do a simple page flip. *Note* I haven't tested this! -MG
- ; If you are using the 720 technique in your own program you probably won't
- ; want to use this code anyway.
- Flip:
- and al, 80h
- push dx
- mov dx, 3B4h
- mov ah, al
- mov al, 0Ch
- out dx, ax
- pop dx
- jmp short return
-
-
- Code ENDS
-
-
- Top SEGMENT para
- TopOff:
- Top ENDS
-
-
- END Start
-