home *** CD-ROM | disk | FTP | other *** search
- #!/bin/sh
- # shar: Shell Archiver
- # Run the following text with /bin/sh to create:
- # read.me
- # hercbios.doc
- # hercules.prg
- # gchar.asm
- # graph.asm
- # hcharset.asm
- # hercbios.asm
- # hercbios.aut
- # hercbios.h
- # hercdemo.asm
- # hercmake.att
- # hercmake.lcm
- # hercpixl.dc
- # hercpixl.lc
- # testpix.c
- echo x - extracting shar
- sed 's/^X//' << 'SHAR_EOF' > read.me
- X
- X H E R C U L E S
- X ---------------
- X
- XThis .ARC file contains two sets of information:
- X
- X
- X - HERCULES.PRG is a memo from Bob Morse and a note from me
- X explaining the programming parameters for the Hercules (and
- X clone) graphics board. His information is especially useful
- X because he lists the internal parameters which must be
- X programmed into the 6845 chip to get graphics mode to work
- X correctly. Please report any problems with this information to
- X me at DECWET::BROWN or Bob at LEWS2::MORSE.
- X
- X HERCDEMO.COM (source included as HERCDEMO.ASM) is a quick and
- X dirty demo program I wrote to help me understand the way the
- X HERCULES card works, and use graphics character generation.
- X
- X
- X - HERCBIOS.COM plus support sofware. HERCBIOS.COM is a terminate-
- X and-stay-resident program which takes over some functions from
- X ROM BIOS INT 10h, providing IBM-compatible graphics modes 6 (640
- X by 200) and 7 (monochrome text) and adding mode 8: Hercules
- X graphics (720 by 348). Other functions are just passed through
- X to the existing ROM BIOS.
- X
- X HERCBIOS was written by Dave Tutelman at AT&T in New Jersey, and
- X the software came to me via net.micro.pc, hot off the wire two
- X days ago. I've included his note and banner as HERCBIOS.AUT.
- X
- X HERCBIOS.DOC explains the operation of the program in detail.
- X
- X HCHARSET.ASM is a simple test program to demonstate IBM and
- X HERCULES modes.
- X
- X There is also a C program which gives a more extended demo of
- X the facility: TESTPIX.C. TESTPIX must be linked with another C
- X module, HERCPIXL, which provides the actual linkages to INT 10h.
- X Since system calls are implementation specific, there are two
- X versions of this module: HERCPIXL.DC and HERCPIXL.LC.
- X HERCPIXL.DC is DeSmet C compatible and HERCPIXL.LC is Lattice C
- X compatible. I've included TESTPIX.EXE (build with Lattice) so
- X you can test the software if you don't have C.
- X
- X Finally, there are two make files: HERCMAKE.ATT and
- X HERCMAKE.LCM. HERCMAKE.ATT is a make file for a make program
- X which looks UNIX compatible, so I called it ".ATT".
- X HERCMAKE.LCM is a make file for the Larry Campbell MAKE program
- X I use. In either case, you will have to use the -f switch
- X invocation of MAKE. E.g: MAKE -f HERCMAKE.LCM HERCBIOS.COM.
- X
- X HERCBIOS.COM seems to work quite nicely as advertised, but I
- X must warn you that there are some functions which are not yet
- X implemented -- scrolling in graphics mode, for one. I'm sure
- X Dave will continue to enhance it and hope to get future updates.
- X In the meantime, if anyone gets brave and tackles scrolling, put
- X the updates on PAR5!
- X
- X
- X-Reid Brown
- X 6-Sep-1986
- X DECWET::BROWN
- SHAR_EOF
- echo x - extracting shar
- sed 's/^X//' << 'SHAR_EOF' > hercbios.doc
- X
- X
- X ***** HERCBIOS *****
- X BIOS PATCH FOR THE HERCULES BOARD
- X
- X Dave Tutelman 1986
- X
- X
- X
- X The accompanying program is a front end to the INT 10 (VIDEO)
- X functions of the DOS BIOS, so that the important functions work
- X on a Hercules graphics board or its clones. (It was developed on
- X a SuperComputer clone of a Hercules) It is a
- X terminate-and-stay-resident program, that is installed by being
- X called; it is NOT a DOS driver. If you want it installed at boot,
- X include it in AUTOEXEC.BAT, not CONFIG.SYS.
- X
- X WHAT IT'S GOOD FOR
- X
- X The major strength of this program is that it will allow you to
- X write programs for the Hercules board that run in graphics mode,
- X and still write text easily on the graphics screen. With it, you
- X can program in those higher-level language processors that use
- X the DOS or BIOS calls for display, using their standard I/O calls
- X to write text to the graphics screen. (For a list of known
- X compatible and incompatible languages, see the section later in
- X this manual.)
- X
- X A second use of this program is to allow the running of existing
- X graphics programs that use the BIOS calls for ALL screen display.
- X It will NOT allow most commercial graphics programs written for
- X the the Color Graphics Adapter (CGA) to run on the Hercules
- X board. That is because most graphics programs write directly to
- X the video memory instead of using the BIOS calls. The only
- X existing graphics program that this has been tested against is
- X PC-LISP; that is the only graphics program I've encountered that
- X uses the BIOS exclusively.
- X
- X
- X HOW IT WORKS
- X
- X HERCBIOS is a terminate-and-stay-resident program that intercepts
- X all calls to Interrupt 10H, the BIOS video services. It will
- X either process the interrupt or pass the call on to the real
- X BIOS, depending on whether something specific to the Hercules
- X board needs to be done. Specifically, HERCBIOS handles the
- X interrupt itself if (1) the board is in graphics mode, or (2) the
- X BIOS call is a request to enter graphics mode.
- X
- X Two graphics modes are recognized and processed by HERCBIOS:
- X
- X Mode 6 - IBM Hi-res mode: This uses part of the 720x348
- X Hercules raster as a 640x200 IBM-compatible graphics screen.
- X It will work with programs for the IBM CGA and its clones,
- X provided they use the BIOS services for their graphics
- X display. (Note - such programs are rare.)
- X
- X Mode 8 - Hercules-specific mode: This uses the full
- X
- X - 1 -
- X
- X
- X Hercules raster.
- X
- X Actually, both modes are quite capable of putting a pixel
- X anywhere on the Hercules raster. The major difference is that
- X Mode 6 draws characters in an 8x8 pixel box (like the CGA), while
- X Mode 8 uses the finer resolution of the Hercules board to improve
- X legibility by using a 12x8 pixel box for characters. In either
- X mode, more characters than 25x80 will fit on the screen. Mode 6
- X supports 43x90 characters on the screen (but 25x80 inside the
- X 640x200-pixel sub-screen); Mode 8 supports 29x90 characters.
- X
- X The functions implemented by HERCBIOS are:
- X
- X Fn 0 - Set mode (6, 7, or 8)
- X Fn 2 - Set cursor position
- X Fn 3 - Read cursor position
- X Fn 5 - New display page
- X Fn 9 - Write character with attribute
- X Fn 10 - Write character
- X Fn 12 - Write pixel
- X Fn 13 - Read pixel
- X Fn 14 - Teletypewriter-style character write
- X Fn 15 - Get video status
- X
- X Check your System Programmers' Guide for the use of these BIOS
- X functions.
- X
- X A number of properties of the alphanumeric display are not
- X supported by the hardware when you enter graphics mode. For
- X instance, the cursor is not shown in graphics mode, nor are all
- X of the character attributes. HERCBIOS does its best to emulate
- X the alphanumeric mode, but it cannot implement a cursor or the
- X blinking or bold attributes. The table below shows the "best
- X shot" that HERCBIOS takes at character attributes:
- X
- X CODE USUALLY MEANS IBM MODE HERC MODE
- X 00 invisible invisible invisible
- X 01 underline [normal] underline
- X 07 normal normal normal
- X 0F hi-intens [rev video] [rev video]
- X 70 rev video rev video rev video
- X
- X
- X Anything else displays as normal
- X
- X The teletypewriter-style output protects the bottom line on the
- X screen as an unscrolled line, for status messages, function key
- X labels, etc. This is non-standard, but I like it. (And we do have
- X more rows than the CGA display. It's the 43rd line that isn't
- X scrolled.)
- X
- X
- X
- X
- X
- X
- X
- X - 2 -
- X
- X
- X MAKING AND INSTALLING THE PROGRAM
- X Making the .COM File from Assembler Source
- X
- X HERCBIOS was originally developed on ASM 1.0. The version
- X included with this uses MASM 4.0. I don't know for sure whether
- X it will assemble with other versions of assembler.
- X
- X The commands for making HERCBIOS.COM from the source are in the
- X MAKEFILE included with the distribution. I run it with NDMAKE, an
- X excellent MS-DOS shareware MAKE from Don Knellers, but it should
- X be easy to adapt to your own favorite MAKE. If you make it by
- X hand, the commands are:
- X
- X masm hercbios;
- X masm gchar;
- X masm graph;
- X link hercbios gchar graph, hercbios.exe;
- X exe2bin hercbios.exe hercbios.com
- X del hercbios.exe
- X
- X If you have a machine whose processor is an iAPX 286, 186, or
- X 188, you may be able to get some increased performance and a
- X smaller .COM file by editing one character in the header file
- X hercbios.h. Simply remove the ";" that comments out the
- X definition of iAPX286. That will allow some non-8088 instructions
- X to assemble, as well as changing some code that was optimized for
- X speed (at the expense of storage and beauty) on the 8088. (This
- X option is known to assemble and link, but has not been tested; I
- X have no access to a 286 machine with Hercules graphics.)
- X
- X
- X Installing HERCBIOS.COM
- X
- X Once you have HERCBIOS.COM, store it where your PATH will find it
- X and add the line
- X
- X HERCBIOS
- X
- X to your AUTOEXEC.BAT file somewhere after the PATH command. This
- X will cause it to be installed during boot, so it will be there
- X whenever you run your graphics programs. (Its presence won't
- X affect operation of your computer in alphanumeric mode, since it
- X passes on to the normal BIOS anything that's not in graphics
- X mode.)
- X
- X I am including a couple of demonstration/test programs in this
- X distribution, so that you can:
- X - See how to write programs for HERCBIOS.
- X - Test to assure that it runs with your computer and monitor.
- X The programs can be run in their executable form and their source
- X can be examined.
- X
- X
- X
- X
- X
- X
- X - 3 -
- X
- X
- X COMPATIBILITY AND INCOMPATIBILITY
- X
- X HERCBIOS has been tested on a Hercules board in an IBM PC-XT, a
- X Hercules-compatible board I built from a SuperComputer bare
- X board, and a Leading Edge XT clone. The current version works
- X with all of these, but I have a homebrew monitor that has trouble
- X syncing to the higher sweep rate of the monochrome display. If
- X you have trouble with the stability of your image, try fiddling
- X with the parameters for the 6845 display chip. They are in the
- X file HERCBIOS.ASM, in the "db" statement defining vid_parm_table
- X at the end of Function 0 (Set Video Mode). I have left in (but
- X commented out) the set of parameters that works on my homebrew
- X monitor.
- X
- X I have written programs using HERCBIOS in a number of languages.
- X Here are some of the caveats I'd like to pass on:
- X
- X - Things are fine using INT 10h calls in assembler. (No big
- X surprise.)
- X
- X - Turbo Pascal works with HERCBIOS, with one caveat (at least
- X for releases 1 and 2). The Pascal cursor function GoTOXY will
- X home the cursor if presented with x>80 or y>25. To make full
- X use of the 29x90 or 43x90 screen, you will have to write your
- X own version of GoTOXY, using Turbo's machine language escape
- X to issue the INT 10h.
- X
- X - I've written a little in Microsoft C 3.0. No problems so far.
- X
- X - The TESTPIX program was written in deSmet C 2.4. It worked
- X fine, with one caveat. The console I/O routine getchar()
- X seems to write to display memory (perhaps as part of keyboard
- X echo). This can interfere with what is displayed on the
- X Hercules board display page 1. (I had no problems on page
- X 0.)
- X
- X - Forget about using it with BASICA or GWBASIC. Microsoft BASIC
- X graphics routines write directly to display memory,
- X completely bypassing the BIOS.
- X
- X
- X USE AND ENJOY!
- X
- X Bug reports to:
- X Dave Tutelman
- X 16 Tilton Drive
- X Wayside, NJ 07712
- X
- X
- X Currently receive EMail at ...!mtuxo!mtuxt!dmt
- X
- X
- X Flames to:
- X /dev/null
- X
- X
- X
- X - 4 -SHAR_EOF
- echo x - extracting shar
- sed 's/^X//' << 'SHAR_EOF' > hercules.prg
- X Hercules Monochrome Graphics Card Programming
- X ---------------------------------------------
- X
- X provided by
- X
- X Robert Morse MLO5-2/B6 LEWS2::MORSE
- X
- XThe board configuration is controlled by the write-only control register
- Xat port 03BF. All bits are set to zero upon power-up, which limits
- Xthe board to text mode (it will pass IBM monochrome display adapter
- Xdiagnostics only while all bits are zero).
- X
- XBit Description
- X--- -----------
- X 0 0=disable setting of graphics mode; 1=allow graphics mode.
- X 1 0=disable page one (allows coexistence with a color graphics
- X board); 1=enable page one (required to run Lotus 1-2-3).
- X 2..7 (not used)
- X
- X
- X
- XModes are controlled by the write-only control register at port 03B8. All
- Xbits are set to zero upon power-up.
- X
- XBit Description
- X--- -----------
- X 0 (not used)
- X 1 0=text; 1=graphics.
- X 2 (not used)
- X 3 0=blank screen; 1=activate screen.
- X 4 (not used)
- X 5 0=disable text blink; 1=enable text blink.
- X 6 (not used)
- X 7 0=page zero at B0000h; 1=page one at B8000h.
- X
- X
- X
- XTable of 6845 values (all values in hexadecimal):
- X
- XRegister Text Graphics
- X------------------------- ---- --------
- X 0 Total chars/row -1 61 35
- X 1 Visible chars/row 50 2D
- X 2 Hsync position 52 2E
- X 3 Hsync width 0F 07
- X 4 Total rows -1 19 5B
- X 5 Additional scan lines 06 02
- X 6 Visible rows 19 57
- X 7 Vsync position 19 57
- X 8 Interlace control 02 02
- X 9 Lines/row -1 0D 03
- X A Top cursor scan 0B 00
- X B Bottom cursor scan 0C 00
- X C Display origin 00 00
- X D Display origin 00 00
- X
- XIn text mode, each character time is 0.5625 microseconds and a character is
- X9 dots wide and 14 dots high. The controller is programmed for 25
- Xdisplayed rows of 14 scan lines each. There are 350 visible scan lines and
- X370 total scan lines.
- X
- X
- XIn graphics mode, each character time is 1.000 microseconds and a character
- Xis 16 dots wide and 4 dots high. The controller is programmed for 87
- Xdisplayed rows of 4 scan lines each. There are 348 visible scan lines and
- X370 total scan lines. Each row has 45 displayed characters of 16 bits,
- Xgiving 720 dots/row.
- X
- X
- X<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>
- X Note on Addressing the Screen
- X -----------------------------
- X
- XThe preceding paragraph gives a hint about pixel addresses in graphics
- Xmode. I looked through the HERCBIOS sources and then wrote a program
- X(HERCDEMO.ASM) to help me understand this. Here's how screen addressing
- Xworks:
- X
- X o Although you might think of graphics mode as pure bits, the 6845
- X chip always thinks in term of characters. When you switch to
- X graphics mode, the characters are 16 bits wide by 4 bits high.
- X Thus, in graphics mode the screen has 87 rows of "characters"
- X and each row is 45 characters wide, for 720x348 pixels.
- X
- X o For a reason unknown to me (probably speed of memory access),
- X each of the four scan lines in a graphics character is stored in
- X a different "bank" or 2000h section of the screen buffer. All
- X 87 scan line 0s are stored from 0-2000h, all scan line 1s from
- X 2000h-4000h, all scan line 2s from 4000h-6000h, and all scan
- X line 3s from 6000h-8000h.
- X
- X o Within a bank of memory (representing one set of scan lines),
- X each row is 45 words or 90 bytes wide. Rows follow each other
- X with no intervening space. So, assuming row numbers from 0 to
- X 86, the 5th graphics character in row 40 is composed of four
- X scan lines, each 16 bits wide, located at the following memory
- X addresses (offsets from the beginning of the screen buffer):
- X 40*90 = 3600 (offset in any bank to row 40)
- X 4*2=8 (5th graphics char = (n-1)*2 bytes/char)
- X Scan line 0: locations 3608,3609
- X Scan line 1: 2000h (8192) + 3608,9 = 11800,11801
- X Scan line 3: 4000h (16384) + 3608,9 = 19992,19993
- X Scan line 4: 6000h (24576) + 3608,9 = 28184,28185
- X
- X o Computing a pixel location is a little harder, but still fairly
- X straightforward. Say you want to address the bit at 300,300
- X with a point of origin at the upper left. 300 scan lines down
- X from the top is 300/4 = 75 (no remainder), which is scan line 0
- X of row 75. 300 bits into the line is 300/8 = 37 remainder 4.
- X The bit you want is in bank 0 (0-2000h) since it is scan line 0,
- X offset by 75*90 =6750 for the row, plus 37 for the byte within
- X the row, or byte offset 6787 from the beginning of that page in
- X screen memory. Within that byte, you want to set/reset bit 4.
- X
- X
- XWell, that should cover it. If you should discover that I got any of
- Xthis wrong, send me mail.
- X
- X-Reid Brown
- XDECWET::BROWN
- SHAR_EOF
- echo x - extracting shar
- sed 's/^X//' << 'SHAR_EOF' > gchar.asm
- X;********************************************************************
- X;*
- X;* GRAPHIC CHARACTER HANDLING
- X;*
- X;* Dave Tutelman - 8/86
- X;*
- X;*-------------------------------------------------------------------
- X;*
- X;* Fn 6 Scroll up - not yet implemented
- X;* Fn 7 Scroll down - not yet implemented
- X;* Fn 9 Write character with attribute
- X;* Fn 10 Write character normal
- X;* Fn 14 Write character Teletypewriter style
- X;*
- X;* Also includes subroutines to:
- X;* get_address convert page/row/col to display address
- X;* do_char write a character to an address on display
- X;* do_attrib change a display address to some attribute
- X;* full_screen_scroll used by Fn 14, when it needs to scroll
- X;* flash momentarily flash to reverse video and back
- X;*
- X;********************************************************************
- X;
- XINCLUDE hercbios.h
- X
- X;-----------------------------------------------
- Xextrn exit_herc_bios:near
- Xpublic writechar,scroll_up,scroll_down,tty
- Xpublic scr_start,scr_length,num_rows
- X;------------------------------------
- Xcseg segment public
- X assume cs:cseg,ds:bios_data
- X;
- X
- X;**************************************************************
- X;*
- X;* FUNCTION 6 & 7 - SCROLL UP & DOWN
- X;* (Placeholder only - not yet implemented)
- X;*
- X;* AL = Number of rows to scroll (if 0, blank scroll area)
- X;* BH = Fill attribute (we ignore, since writechar destroys old attrib)
- X;* CX = Upper left corner (CH=row, CL=col)
- X;* DX = Lower right corner (DH=row, DL=col)
- X;*
- X;****************************************************************
- X;
- Xscroll_up:
- Xscroll_down:
- X;
- X jmp exit_herc_bios
- Xpage
- X;********************************************************************
- X;*
- X;* FUNCTION 9 & 10 - WRITE A CHARACTER AT CURRENT CURSOR
- X;*
- X;* AL = character code to be written
- X;* AH = 9 (write char with attribute) or 10 (write char normal)
- X;* BL = new attribute (limited selection in graphics mode)
- X;* BH = display page number
- X;* CX = count of how many characters to write
- X;*
- X;********************************************************************
- X;
- Xwritechar:
- X; ; Get the address corresponding to cursor[page]
- X push bx
- X mov bl,bh ; page to BX
- X xor bh,bh
- X shl bx,1 ; *2 for word pointer
- X mov dx,curs_pos[bx] ; appropriate cursor position to DX
- X pop bx
- X call get_address ; get display address in DI
- X;
- Xwrchar_loop:
- X; ; Write a character to that address
- X call do_char ; arguments set up already
- X;
- X; ; If function 9, modify the character's attributes
- X cmp ah,9 ; Function 9?
- X jne no_attrib ; no, don't do attributes
- X call do_attrib ; yes, and arguments already set up
- Xno_attrib:
- X;
- X inc di ; move to next position, without moving
- X ; the official cursor
- X loop wrchar_loop ; continue until CX count exhausted
- X jmp exit_herc_bios
- Xpage
- X;*****************************************************************
- X;*
- X;* FUNCTION 14 - TELETYPEWRITER-STYLE CHARACTER WRITE
- X;*
- X;* AL = Character to be written
- X;*
- X;******************************************************************
- X;
- Xtty:
- X assume ds:bios_data
- X mov bl,active_page ; active page to BX
- X xor bh,bh
- X mov dx,curs_pos[bx] ; get cursor for active page
- X push bx
- X mov bh,bl ; move page to BH
- X call get_address ; address of character to DI
- X pop bx
- X;
- X; ; process the character
- X; ; check if CR
- X cmp al,13 ; carriage return?
- X jne not_cr
- X mov dl,0 ; go to first column
- X jmp fix_curs
- X; ; check if LF
- Xnot_cr: cmp al,10 ; line feed?
- X jne not_lf
- X inc dh ; next line
- X jmp fix_curs
- X; ; check if BS
- Xnot_lf: cmp al,8 ; backspace?
- X jne not_bs
- X cmp dl,0 ; already first column?
- X je fix_curs ; yup. do nothing
- X dec dl ; nope. move cursor left one
- X dec di ; also move address pointer left one
- X mov al,32 ; set character to space
- X call do_char ; and write the space, but don't move
- X jmp fix_curs
- X; ; check if BEL
- Xnot_bs: cmp al,7 ; bell character?
- X jne not_bl
- X pop es ; restore registers
- X pop di
- X pop si
- X pop dx
- X pop cx
- X pop bx
- X pop ds
- X jmp vid_bios ; ... and use the normal BIOS to ring the bell
- X; call flash ; can't do BEL standard. Blink display instead
- X; jmp fix_curs
- X; ; ordinary printing character, so display it
- Xnot_bl: call do_char ; write it to screen
- X inc dl ; cursor one to the right
- X;
- X; ; now look at the cursor, do what's necessary to
- X; ; fix it up, and save it away.
- Xfix_curs:
- X cmp dl,89 ; beyond last column?
- X jle chk_scroll ; not yet
- X xor dl,dl ; yes. do a CR
- X inc dh ; ... and a LF
- Xchk_scroll:
- X cmp dh,cs:num_rows ; now see if we're beyond last row?
- X jl exit_tty ; not yet
- X call full_screen_scroll
- X ; yes. Scroll the screen up one
- X dec dh ; ... and scroll cursor, too.
- X jmp chk_scroll
- X;
- Xexit_tty:
- X mov curs_pos[bx],dx ; save cursor position
- X jmp exit_herc_bios
- Xpage
- X;--------------------------------------------------------------------
- X;
- X; GET_ADDRESS SUBROUTINE
- X;
- X; BH = display page
- X; DX = cursor position (DH=row, DL=col)
- X;
- X; returns:
- X; DI = displacement of top row of pixels
- X;
- X;--------------------------------------------------------------------
- X;
- Xget_address:
- X push cx ; save it
- X
- X; ; compute display address from cursor_pos
- X mov cl,dh ; get row # in cx
- X xor ch,ch
- X shl cx,1 ; begin fast multiply by 90 (1011010 B)
- X mov di,cx
- X shl cx,1
- X shl cx,1
- X add di,cx
- X shl cx,1
- X add di,cx
- X shl cx,1
- X shl cx,1
- X add di,cx ; end fast multiply by 90
- X mov cx,di ; copy answer back to cx
- X shl di,1 ; *2 for ibm graphics mode
- X cmp video_mode,herc_mode
- X jne ibm_ad ; not herc mode
- X add di,cx ; *3 for herc mode
- Xibm_ad: xor ch,ch ; columns in CX
- X mov cl,dl
- X add di,cx ; add in col. address in DI
- X cmp bh,0 ; if page 1, set high-order bit of address
- X je pg0
- X or di,8000H
- Xpg0:
- X; ; address now in DI
- X;
- X pop cx ; restore it
- X ret
- Xpage
- X;--------------------------------------------------------------------
- X;
- X; DO_CHAR SUBROUTINE
- X;
- X; AL = character to write
- X; DI = diplacement (address) of top row of pixels
- X;
- X; Note: SI and ES are destroyed
- X;
- X;--------------------------------------------------------------------
- X;
- Xdo_char:
- X push ax
- X push bx
- X push cx
- X push di
- X push ds
- X;
- X; ; get scan pattern table pointer into BX
- X cmp video_mode,herc_mode
- X je herc_1
- X mov bx,offset ibm_pattern
- X ; IBM graphics mode - use appropriate table
- X jmp c_1
- Xherc_1: mov bx,offset herc_pattern
- X ; herc graphics mode - use appropriate table
- Xc_1:
- X;
- X; ; set up source address registers
- X xor ah,ah ; character to SI
- X mov si,ax
- XIFDEF iAPX286
- X shl si,3 ; *8 for 8-byte table entry
- XELSE
- X shl si,1 ; *8 for 8-byte table entry
- X shl si,1
- X shl si,1
- XENDIF
- X ; next, find beginning of table
- X cmp al,7Fh ; ROM or user table?
- X jg u_tbl
- X ; ROM table
- X add si,charbase ; character table base added to offset
- X mov ax,mpx_bios ; BIOS code segment to DS
- X mov ds,ax
- X jmp c_2
- Xu_tbl: ; user table
- X xor ax,ax ; zero (interrupt vector) to DS
- X mov ds,ax
- X mov ax,si ; save table offset in AX
- X assume ds:intvec
- X lds si,user_table ; load DS:SI from interrupt vector
- X add si,ax ; add offset into table base
- Xc_2:
- X;
- X; ; set up destination address registers
- X mov ax,pixbase ; get display segment in ES
- X mov es,ax
- X ; displacement already in DI
- X;
- X;
- X; ; transfer the character
- X mov ax,di ; save top-row displacement in AX
- X mov cx,8 ; transfer 8 rows
- X cld ; direction = up
- Xc_loop: mov di,ax ; top-row displacement
- X add di,cs:[bx] ; add entry from scan-pattern table
- X movsb ; actually transfer a byte and bump SI & DI
- X add bx,2 ; next entry in scan-pattern table
- X loop c_loop
- X;
- X; ; if hercules mode, blank the extra rows
- X pop ds ; restore DS to Bios data
- X assume ds:bios_data
- X cmp video_mode,herc_mode
- X jne c_3
- X ; Hercules mode
- X mov si,ax ; don't need SI. Save top-row displacement
- X xor ax,ax ; zero AX
- X mov cx,4 ; four rows to blank
- X cld
- Xc_blnk: mov di,si ; top-row displacement
- X add di,cs:[bx] ; add entry from scan-pattern table
- X stosb ; transfer a zero byte
- X add bx,2 ; next entry in scan-pattern table
- X loop c_blnk
- Xc_3:
- X;
- X; ; clean up and return
- X pop di
- X pop cx
- X pop bx
- X pop ax
- X ret
- Xpage
- X;---------------------------------------------------------------------
- X;
- X; DO_ATTRIB SUBROUTINE
- X;
- X; BL = attribute byte
- X; DI = displacement (address) of top row of pixels
- X; ES is destroyed
- X;
- X; Because attributes don't "just happen" in graphics mode, here's
- X; what we have to transform them to.
- X;
- X; CODE USUALLY MEANS IBM MODE HERC MODE
- X; 00 invisible invisible invisible
- X; 01 underline [normal] underline
- X; 07 normal normal normal
- X; 0F hi-intens [rev video] [rev video]
- X; 70 rev video rev video rev video
- X;
- X; Anything else displays as normal
- X; Note that there's no way to make blinking happen.
- X;
- X;-----------------------------------------------------------------------
- X;
- Xdo_attrib:
- X assume ds:bios_data
- X push ax
- X mov ax,pixbase ; Display base to ES
- X mov es,ax
- X pop ax
- X;
- X; ; which attribute, if any?
- X and bl,7Fh ; mask off blink bit
- X cmp bl,0 ; invisible?
- X je invisible
- X cmp bl,0Fh ; reverse video? (instead of bright)
- X je reverse
- X cmp bl,70H ; reverse video?
- X je reverse
- X cmp bl,01 ; underline?
- X je underline
- X ret ; none of the above. Display normal.
- X;
- X; ; underline the character
- Xunderline:
- X cmp video_mode,herc_mode
- X je ul_1
- X ret ; don't do it for IBM mode
- Xul_1: mov byte ptr es:[di+40B4h],0FFh
- X ; move ones to 11th line of pixel array
- X ; 40B4h is the 11th entry in herc_pattern
- X ret
- X;
- X; ; make it invisible
- Xinvisible:
- X push ax
- X push bx
- X push cx
- X push dx
- X xor ax,ax ; zero the AX
- X cmp video_mode,herc_mode
- X je herc_3
- X mov bx,offset ibm_pattern
- X ; point to scan pattern
- X jmp inv_1
- Xherc_3: mov bx,offset herc_pattern
- X ; point to scan pattern
- Xinv_1: mov dx,di ; save addr of top row of pixels in DX
- X mov cx,8 ; 8 bytes to be moved
- X cld ; direction = up
- Xinvis_loop:
- X mov di,dx ; top row address
- X add di,cs:[bx] ; add scan-table offset
- X stosb ; move a zero byte
- X add bx,2 ; bump the scan-table pointer
- X loop invis_loop
- X pop dx
- X pop cx
- X pop bx
- X pop ax
- X ret
- X;
- X; ; reverse video
- Xreverse:
- X push bx
- X push cx
- X push dx
- X cmp video_mode,herc_mode
- X je herc_4
- X mov bx,offset ibm_pattern
- X ; point to scan pattern
- X mov cx,8 ; 8 scan lines for IBM mode
- X jmp rev_1
- Xherc_4: mov bx,offset herc_pattern
- X ; point to scan pattern
- X mov cx,12 ; 12 scan lines for Hercules mode
- Xrev_1: mov dx,di ; save addr of top row of pixels in DX
- X cld ; direction = up
- Xrev_loop:
- X mov di,dx ; top row address
- X add di,cs:[bx] ; add scan-table offset
- X not es:byte ptr[di] ; invert one scan line
- X add bx,2 ; bump the scan-table pointer
- X loop rev_loop
- X pop dx
- X pop cx
- X pop bx
- X ret
- Xpage
- X;--------------------------------------------------------------
- X;
- X; SUBROUTINE FULL_SCREEN_SCROLL
- X;
- X; This scrolls the entire screen up one print line (8 or 12 pixels).
- X; Actually, we'll protect one line on the bottom (e.g.-function keys).
- X;
- X;-----------------------------------------------------------------
- X;
- X; ; A few constants, initialized by set_mode
- Xnum_rows db ? ; number of rows in display
- X ; = 42 (IBM) or 28 (Herc)
- Xscr_start dw ? ; 2*90 or 3*90 depending on mode
- Xscr_length dw ? ; number of words to transfer in a sweep
- X ; = 41*start /2 = 3690 (IBM)
- X ; = 27*start /2 = 3645 (Herc)
- X;
- Xfull_screen_scroll:
- X assume ds:bios_data
- X push ds
- X push ax
- X push cx
- X mov ax,pixbase ; start getting display segment
- X cmp active_page,0 ; page 0?
- X je scr_pg0
- X add ax,800H ; page 1. bump by half of 64K
- Xscr_pg0:
- X mov ds,ax ; save display segment in DS
- X mov es,ax ; ... and in ES
- X;
- X xor ax,ax ; zero AX
- X call scr_shift
- X mov ax,2000H ; bump interlace counter
- X call scr_shift
- X mov ax,4000H
- X call scr_shift
- X mov ax,6000H
- X call scr_shift
- X;
- X pop cx
- X pop ax
- X pop ds
- X ret
- X;
- X;
- X; scr_shift does the actual work of scrolling, one set of interlace
- X; lines at a time.
- X;
- Xscr_shift:
- X cld ; block moves will be UP
- X mov di,ax ; interlace scan ID to DI
- X mov si,ax ; ... and to SI
- X add si,cs:scr_start
- X ; but bump by "start"
- X mov cx,cs:scr_length
- X ; set counter for transfer
- X rep movsw ; and scroll a set of lines
- X xor ax,ax ; set up a zero word
- X mov cx,cs:scr_start ; set counter for one more line
- X shr cx,1 ; /2 for word transfers
- X rep stosw ; and blank the line
- X ret
- Xpage
- X;-----------------------------------------------------------
- X;
- X; SUBROUTINE FLASH
- X;
- X; Flashes the screen inverse video and back to normal.
- X; Used in place of an audible bell.
- X;
- X;-------------------------------------------------------------
- X;
- Xflash:
- X push cx
- X push di
- X push es
- X;
- X mov di,pixbase ; get display area base
- X cmp active_page,0 ; page 0?
- X je pg0_f
- X add di,800H ; no, page 1
- Xpg0_f: mov es,di ; put resulting pointer to display in ES
- X;
- X; ; loop to invert screen
- X xor di,di ; point to beginning of display area
- X mov cx,4000H ; number of words to invert
- Xflash_loop_1:
- X not word ptr es:[di]
- X ; invert one location
- X add di,2 ; bump location pointer a word
- X loop flash_loop_1
- X;
- X; ; and invert it back to normal
- X xor di,di ; point to beginning of display area
- X mov cx,4000H ; number of words to invert
- Xflash_loop_2:
- X not word ptr es:[di]
- X ; invert one location
- X add di,2 ; bump location pointer a word
- X loop flash_loop_2
- X;
- X pop es
- X pop di
- X pop cx
- X ret
- Xpage
- X;*****************************************************
- X;* Data areas for character handling
- X;*****************************************************
- X;
- Xpixels db 12 dup(?) ; 12 bytes for pixel pattern
- Xibm_pattern dw 0000h,2000h,4000h,6000h,005Ah,205Ah,405Ah,605Ah
- Xherc_pattern dw 4000h,6000h,005Ah,205Ah,405Ah,605Ah,00B4h,20B4h
- Xblank_pattern dw 0000h,2000h,40B4h,60B4h
- X;
- X;
- Xcseg ends
- X end
- SHAR_EOF
- echo x - extracting shar
- sed 's/^X//' << 'SHAR_EOF' > graph.asm
- X;*******************************************************
- X;*
- X;* SET OF GRAPHICS ROUTINES FOR HERCULES BIOS
- X;*
- X;* Dave Tutelman - 8/86
- X;*
- X;*-------------------------------------------------------
- X;*
- X;* do_pixel: draws, erases, or reads a pixel, given an
- X;* offset and mask.
- X;*
- X;**********************************************************
- X;
- XINCLUDE hercbios.h
- X
- X;------------------------------------------
- Xpublic wr_pixel,end_herc
- Xextrn exit_herc_bios:near
- X;-----------------------------------------
- X;
- Xcseg segment public
- X assume cs:cseg,ds:bios_data
- X;
- X;
- X;**********************************************
- X;*
- X;* read or write a pixel:
- X;* DX = row # ( y )
- X;* CX = col # ( x )
- X;* AH = 12 for write, 13 for read
- X;* AL = value (0,1, if bit 7=1 EXOR the value)
- X;*
- X;**********************************************
- X;
- Xwr_pixel:
- X mov bh,video_mode ; check for valid mode
- X cmp bh,herc_mode
- X je do_pixel
- X cmp bh,ibm_mode
- X je do_pixel
- X jmp exit_herc_bios ; invalid mode. don't do it.
- X;
- Xdo_pixel:
- X push ax ; save function and pixel value
- X;
- X; ; first compute the address of byte to be modified
- X; ; = 90*[row/4] + [col/8] + 2^D*[row/4] + 2^F*page
- X mov bh,cl ; col (low order) in BH
- X mov bl,dl ; row (low order) in BL
- X and bx,0703H ; mask the col & row remainders
- XIFDEF iAPX286
- X shr cx,3 ; col / 8
- X shr dx,2 ; row / 4
- X mov al,90
- X mul dx ; AX = 90*[ row/4 ]
- X add ax,cx ; ... + col/8
- X shl bl,5 ; align row remainder
- XELSE ; same as above, obscure but fast for 8086
- X shr cx,1 ; divide col by 8
- X shr cx,1
- X shr cx,1
- X shr dx,1 ; divide row by 4
- X shr dx,1
- X shl dx,1 ; begin fast multiply by 90 (1011010 B)
- X mov ax,dx
- X shl dx,1
- X shl dx,1
- X add ax,dx
- X shl dx,1
- X add ax,dx
- X shl dx,1
- X shl dx,1
- X add ax,dx ; end fast multiply by 90
- X add ax,cx ; add on the col/8
- X shl bl,1 ; align row remainder
- X shl bl,1
- X shl bl,1
- X shl bl,1
- X shl bl,1
- XENDIF
- X add ah,bl ; use aligned row remainder
- X cmp active_page,0 ; page 0 active?
- X je end_adr_calc ; yup
- X or ah,80H ; page 1 active. Set MSB of address
- Xend_adr_calc: ; address of byte is now in AX
- X;
- X mov dx,pixbase ; base of pixel display to DX
- X mov es,dx ; ...and thence to segment reg
- X mov si,ax ; address of byte w/ pixel to index reg
- X mov cl,bh ; bit addr in byte
- X mov al,80H ; '1000 0000' in AL
- X shr al,cl ; shift mask to line up with bit to read/write
- X mov bl,al
- X;
- X pop bx ; now retrieve original AX into BX
- X ; function=BH, pixel value=BL
- X cmp bh,13 ; what to do with the pixel?
- X je read_pix ; read the pixel.
- X cmp bl,0 ; write the pixel. But how?
- X je clr_pix ; clear the pixel
- X jl exor_pix ; exclusive-or the pixel
- X;
- Xset_pix: ; set the pixel
- X or es:[si],al ; or the mask with the right byte
- X jmp exit_herc_bios
- X;
- Xclr_pix: ;clear the pixel
- X not al ; invert the mask, so zero on bit to be cleared
- X and es:[si],al ; and the mask with the right byte
- X jmp exit_herc_bios
- X;
- Xexor_pix: ; exclusive-or the pixel
- X mov ah,07fH ; mask to rid 7th bit
- X and ah,bl ; pixval w/o XOR flag
- X jnz do_exor ; ExOr with a 1?
- X jmp exit_herc_bios ; no! XOR (0,x) = x. just return.
- Xdo_exor:
- X xor es:[si],al ; EXOR the pixel with the mask.
- X jmp exit_herc_bios
- X;
- Xread_pix: ; read the pixel
- X and al,es:[si] ; read the bit into AL
- X jz rd_zro
- X mov al,1 ; if it ain't zero, it's one
- Xrd_zro: jmp exit_herc_bios
- X;
- X;
- Xend_herc: ; label for end of package. Used by hercbios
- X ; to install it.
- X;
- Xcseg ends
- X end
- SHAR_EOF
- echo x - extracting shar
- sed 's/^X//' << 'SHAR_EOF' > hcharset.asm
- X;**************************************************************
- X;*
- X;* Tests Hercules BIOS, specifically the functions 9 & 10
- X;* to put characters on the screen in graphics mode.
- X;*
- X;***************************************************************
- XVIDI equ 10H ; video interrupt, 10H (50H for debug)
- Xcseg segment common
- X assume cs:cseg,ds:cseg
- XSTART proc
- X; ; prompt for IBM or Hercules graphics mode
- X mov ah,9 ; DOS 9 = display string
- X mov dx,offset mode_prmt+100H
- X ; display mode prompt
- X int 21H ; DOS function
- X mov ah,1 ; DOS 1 = kbd input
- X int 21H
- X mov bl,al ; input char --> BL
- X mov ax,6 ; ibm graphics mode
- X cmp bl,"h" ; input "h" for Hercules
- X jne i_mode
- X add ax,2 ; hercules mode
- Xi_mode: int VIDI
- X;
- X xor bh,bh ; page 0
- X mov bl,7 ; normal attribute
- X mov dh,1 ; cursor at <1,1> to start
- X mov dl,1
- X;
- X mov cx,24 ; do 24 rows
- Xrow: push cx ; save row counter
- X inc dh ; next row
- X mov dl,0 ; back to first column
- X mov ah,2 ; cursor move function
- X int VIDI
- X; ; compute video mode
- X mov bl,dh ; row # to BL
- X xor bh,bh
- X shr bl,1 ; 4 rows per mode
- X shr bl,1
- X mov bl,mode_seq[bx+100H] ; index into mode sequence for mode
- X;
- X; ; for debug, first print [row+64]
- X mov al,dh
- X add al,64
- X mov ah,10 ; fn 10 prints w/o attributes
- X mov cx,1
- X int VIDI
- X;
- X xor bh,bh ; page 0
- X mov cx,64 ; each row 64 characters
- Xachar: push cx ; save char counter
- X mov ah,9 ; write_char function
- X mov al,dh ; character = col + (row mod 2)*64
- X and al,1 ; row mod 2
- X ror al,1 ; *128
- X shr al,1
- X add al,dl ; + col
- X mov cx,1 ; write one of them
- X int VIDI
- X inc dl ; increment row counter
- X mov ah,2 ; cursor move function
- X int VIDI
- X pop cx ; restore character counter
- X loop achar
- X pop cx ; restore row counter
- X loop row
- X;
- X; ; draw a line where it should start
- X mov dx,5 ; row 5
- X mov cx,0 ; col 0
- Xline: push cx
- X push dx
- X mov ax,0C01H ; function 12=pixel
- X int VIDI
- X pop dx
- X pop cx
- X inc cx ; step col
- X cmp cx,700 ; ...until 700
- X jle line
- X;
- X; ; wait for a keystroke
- X mov ah,1
- X int 21H
- X;
- X mov ax,7 ; back to alpha mode
- X int VIDI
- X;
- X; ; Now return to system
- X xor ax,ax ; zero --> AX
- X int 21H ; DOS function call 0 - terminate normally
- X;
- Xmode_prmt db "hercules or ibm mode? [ibm] $"
- Xmode_seq db 7,0Fh,1,70h,0,9 ; sequence norm,hi,ul,rev,invis,norm
- XSTART endp
- Xcseg ends
- X end START
- SHAR_EOF
- echo x - extracting shar
- sed 's/^X//' << 'SHAR_EOF' > hercbios.asm
- X;*******************************************************
- X;*
- X;* Main program file for HERCBIOS
- X;*
- X;* Dave Tutelman - 8/86
- X;*
- X;*------------------------------------------------------
- X;*
- X;* INT10 -- acts as pre-handler for video interrupts
- X;* (BIOS calls) for Hercules & SuperComputer
- X;* monochrome graphics board. Calls real BIOS
- X;* if not a Hercules special. Handled here are:
- X;*
- X;* Fn 0 Set mode (only 6 & 8)
- X;* and all functions, when in mode 6 or 8.
- X;* Actually, we've only implemented:
- X;* Fn 2 Set cursor position
- X;* Fn 3 Read cursor position
- X;* Fn 5 New display page
- X;* Fn 9 Write character with attribute
- X;* Fn 10 Write character
- X;* Fn 12 Write pixel
- X;* Fn 13 Read pixel
- X;* Fn 14 Teletypewriter-style character write
- X;* Fn 15 Get video status
- X;*
- X;* The only allowable modes for these boards are:
- X;* 6 IBM graphics (we handle it, but poor aspect ratio).
- X;* 7 Monochrome (with 2 pages)
- X;* 8 Hercules graphics mode.
- X;*
- X;**********************************************************
- X;
- XINCLUDE hercbios.h
- X
- Xextrn writechar:near,tty:near,scroll_up:near,scroll_down:near
- Xextrn scr_start:word,scr_length:word,num_rows:byte
- Xextrn wr_pixel:near
- Xextrn end_herc:near
- Xpublic exit_herc_bios,int10,vid_vector
- Xpublic set_mode,set_curs,read_curs,new_page,status
- X;-----------------------------------------
- Xpage
- X;************************************************************
- X;*
- X;* Install the Hercules video handler
- X;*
- X;************************************************************
- Xcseg segment public
- X assume cs:cseg,ds:cseg
- X
- X ORG 100h
- X;
- XSTART:
- X;
- X push ax
- X push es
- X push ds
- X;
- X xor ax,ax ; zero the acc
- X mov es,ax ; ES points to zero (interrupt vector)
- X ; Get ROM BIOS video entry point, and save in "rom_bios"
- X mov ax,es:[4*VIDI]
- X mov word ptr cs:rom_bios,ax
- X mov ax,es:[4*VIDI+2]
- X mov word ptr cs:rom_bios+2,ax
- X ; Now plant the HERCBIOS entry point in interrupt vector
- X mov ax,offset int10 ; address of video handler to AX
- X mov es:[4*VIDI],ax ; and store it in interrupt vector 10H
- X mov ax,cs ; same for the segment of video handler
- X mov es:[4*VIDI+2],ax ; ...
- X;
- X; Leave the message that we're installed
- X mov ax,cs ; DS:DX pointing to message
- X mov ds,ax
- X mov dx,offset install_msg
- X mov ah,9 ; display-string function
- X int 21h
- X
- X pop ds
- X pop es
- X pop ax
- X;
- X mov dx,offset end_herc ; set dx to end of this program
- X int 27H ; terminate, but stay resident
- X;
- Xinstall_msg db "BIOS for Hercules-compatible Graphics - "
- X db "(DMT Aug 1986)",10,13,'$'
- Xpage
- X;************************************************************
- X;*
- X;* Beginning of video interrupt handler
- X;*
- X;************************************************************
- X;
- X;
- Xint10 proc far
- X;
- X sti ; allow further interrupts
- X push ds ; save DS
- X push ax ; save AX
- X mov ax,bios_data ; bios data segment --> AX
- X mov ds,ax ; now put bios data segment in DS
- X assume ds:bios_data ; and tell assembler about it
- X; ; check current mode
- X mov ah,video_mode ; get current mode
- X cmp ah,herc_mode ; test for a graphics mode
- X je herc_bios
- X cmp ah,ibm_mode
- X je herc_bios
- X; ; setmode to a graphics mode?
- X pop ax ; restore AX
- X push ax ; ...but leave it on stack
- X cmp ax,0006 ; Fn = set to IBM hi-res mode?
- X je herc_bios
- X cmp ax,0008 ; Fn = set to Herc graphics mode?
- X je herc_bios
- X;
- Xnorm_bios: ; if we get here, just go to real BIOS
- X pop ax ; restore stack to pre-interrupt state
- X pop ds
- X db 0EAh ; opcode for FAR JUMP to rom_bios
- Xrom_bios dd ? ; normal video bios address (in ROM)
- X;
- Xherc_bios: ; jump table for special Hercules BIOS
- X;
- X pop ax ; restore ax
- X push bx ; save regs
- X push cx
- X push dx
- X push si
- X push di
- X push es
- X;
- X push ax
- X mov al,ah ; function # to AX
- X xor ah,ah
- X shl ax,1 ; *2 for word vector
- X mov si,ax ; put in SI to index into vector
- X pop ax ; restore old AX
- X cmp si,offset vid_vec_end-offset vid_vector
- X ; function number within range?
- X jge exit_herc_bios ; function number out of range
- X add si,offset vid_vector
- X jmp word ptr cs:[si]
- X ; jump to routine via vector
- X;
- X
- Xvid_vector: ; jump vector for hercules video routines
- X dw offset set_mode ; 0 = set mode
- X dw offset exit_herc_bios ; 1 = cursor type (NA)
- X dw offset set_curs ; 2 = set cursor position
- X dw offset read_curs ; 3 = read cursor position
- X dw offset exit_herc_bios ; 4 = light pen (NA)
- X dw offset new_page ; 5 = choose active page
- X dw offset scroll_up ; 6 = scroll up
- X dw offset scroll_down ; 7 = scroll down
- X dw offset exit_herc_bios ; 8 = read character (NA)
- X dw offset writechar ; 9 = write char & attribute
- X dw offset writechar ;10 = write character
- X dw offset exit_herc_bios ;11 = set color palette (NA)
- X dw offset wr_pixel ;12 = write pixel
- X dw offset wr_pixel ;13 = read pixel
- X dw offset tty ;14 = teletype write
- X dw offset status ;15 = return video state
- Xvid_vec_end:
- X;
- Xexit_herc_bios:
- X pop es ; restore regs
- X pop di
- X pop si
- X pop dx
- X pop cx
- X pop bx
- X pop ds
- X iret ; and return
- Xpage
- X;********************************************************************
- X;*
- X;* FUNCTION 0 - SET VIDEO MODE
- X;*
- X;* Only gets here to set a hi-res graphics mode
- X;* 6=IBM
- X;* 8=Hercules
- X;* [ AX destroyed ]
- X;*
- X;*******************************************************************
- X;
- Xset_mode:
- X; ; is it a graphics mode?
- X cmp al,herc_mode ; set to hercules mode?
- X je g_mode
- X cmp al,ibm_mode ; set to IBM mode?
- X je g_mode
- X ; Neither. Leave it to normal BIOS
- X pop es ; restore regs
- X pop di
- X pop si
- X pop dx
- X pop cx
- X pop bx
- X pop ds
- X jmp vid_bios ; and go to MPX-16 BIOS
- X;
- Xg_mode: mov video_mode,al ; save video mode in BIOS data area
- X mov active_page,ah ; zero the active page in BIOS data
- X mov n_cols,90 ; 90 character columns in graphics mode
- X;
- X;* clear display area
- X mov ax,pixbase ; get starting address
- X mov es,ax ; page base to ES
- X mov cx,8000H ; word counter
- X mov di,0 ; start at beginning of display
- X cld ; direction "up"
- X xor ax,ax ; zero AX
- X rep stosw ; write zero to both pages
- X;
- X;* load the 6845 internal registers
- X;
- X; ; first set up the loop
- X push ds ; save DS
- X mov ax,cs ; get cseg into DS
- X mov ds,ax
- X assume ds:cseg
- X mov dx,vid_port ; 6845 index port address to DX
- X mov si,offset vid_parm_table
- X ; table pointer to SI
- X mov cx,16 ; 16 parameters in table
- X xor ax,ax ; zero AX (AH will be index counter)
- X; ; now execute the loop
- Xinit_6845_loop:
- X mov al,ah ; index counter to AL
- X out dx,al ; output index to 6845
- X inc dx ; point DX to data reg
- X mov al,[si] ; get table entry
- X out dx,al ; output to 6845 data reg
- X dec dx ; point DX back to index reg
- X inc ah ; bump index counter
- X inc si ; bump table pointer
- X loop init_6845_loop
- X pop ds ; restore DS
- X assume ds:bios_data ; restore DS assumed
- X;
- X;* now set the 6845 control register
- X mov dx,vid_port+4 ; control port address
- X mov al,0AH ; graphics control byte
- X cmp active_page,0 ; get current page
- X je pg0_F0 ; skip if zero
- X or al,80H ; page 1 to control byte
- Xpg0_F0: out dx,al ; and ship to 6845
- X mov chip_ctrl,al ; also save in bios data area
- X;
- X;* save cursor position (0,0) in bios data area
- X xor ax,ax ; zero AX
- X mov curs_pos,ax ; write zero to pg.0 cursor postion
- X mov curs_pos+2,ax ; write zero to pg.1 cursor postion
- X;
- X;* initialize scrolling parameters
- X;
- X cmp video_mode,herc_mode
- X je h_parm
- X mov cs:scr_start,180 ; IBM parameters
- X mov cs:scr_length,3690 ;
- X mov cs:num_rows,42 ;
- X jmp parm_done
- Xh_parm: mov cs:scr_start,270 ; Herc parameters
- X mov cs:scr_length,3645 ;
- X mov cs:num_rows,28 ;
- Xparm_done:
- X;
- X jmp exit_herc_bios
- X;
- X;* table of 6845 chip parameters
- X;
- Xvid_parm_table db 53,45,46,7,91,2,87,87,2,3,62H,3,0,0,0,0
- X;vid_parm_table db 54,45,46,8,91,2,87,87,2,3,62H,3,0,0,0,0
- X ;DMT's monitor
- Xpage
- X;********************************************************************
- X;*
- X;* FUNCTION 2 - SET CURSOR POSITION
- X;*
- X;* DX = new row (DH) and column (DL)
- X;* BH = display page number
- X;*
- X;********************************************************************
- X;
- Xset_curs:
- X;
- X; * save in BIOS data area
- X mov bl,bh ; page # to bl
- X xor bh,bh ; zero bh (page # = BX)
- X shl bx,1 ; times 2 for word
- X mov curs_pos[bx],dx ; store in data area
- X;
- X; * if page # = active page, then we should actually move cursor
- X; * However, cursor doesn't show in graphics mode, so we won't.
- X;
- X jmp exit_herc_bios
- X;
- Xpage
- X;********************************************************************
- X;*
- X;* FUNCTION 3 - READ CURSOR POSITION
- X;*
- X;* on entry
- X;* BH = display page number
- X;*
- X;* on exit
- X;* CX = cursor type/size
- X;* DX = current row (DH) and column (DL)
- X;*
- X;********************************************************************
- X;
- Xread_curs:
- X; ; uncover the return portion of the stack
- X pop es
- X pop di
- X pop si
- X pop dx
- X pop cx
- X; ; now get the data and push onto stack
- X push curs_mode ; cursor type to CX position in stack
- X mov bl,bh ; page # to BX
- X xor bh,bh
- X shl bx,1 ; *2 for word offset
- X push curs_pos[bx] ; cursor position for specified page
- X ; to DX position in stack
- X; ; refill the stack for return
- X push si
- X push di
- X push es
- X;
- X jmp exit_herc_bios
- Xpage
- X;********************************************************************
- X;*
- X;* FUNCTION 5 - SELECT NEW DISPLAY PAGE
- X;*
- X;* AL = new display page number
- X;*
- X;********************************************************************
- X;
- Xnew_page:
- X cmp al,2 ; page < 2?
- X jl f5_1 ; yup
- X jmp exit_herc_bios ; nope. can't do it.
- X;
- Xf5_1: mov active_page,al ; put away active page in bios data
- X; * put starting address in 6845 register 12
- X mov ah,al ; save page number in AH
- X mov dx,vid_port ; index pointer address
- X mov al,12 ; save in register 12
- X out dx,al ; and set index pointer to 12
- X mov al,ah ; restore page to AL
- X ror al,1 ; page to high-order bit
- X shr al,1 ; two bytes per word
- X inc dx
- X out dx,al ; ...and output it to register
- X; * put control byte in 6845 port
- X mov al,ah ; get back page number
- X ror al,1 ; page to high-order bit
- X or al,0AH ; create chip control byte
- X mov chip_ctrl,al ; save it in data area
- X mov dx,vid_port+4 ; control port address
- X out dx,al ; send control byte to chip
- X;
- X jmp exit_herc_bios
- Xpage
- X;***********************************************************************
- X;*
- X;* FUNCTION 15 - RETURN VIDEO STATUS
- X;*
- X;* On exit:
- X;* AL = current video mode
- X;* AH = number of active display columns
- X;* BH = current active page number
- X;*
- X;***********************************************************************
- X;
- Xstatus:
- X; ; first uncover the stack
- X pop es
- X pop di
- X pop si
- X pop dx
- X pop cx
- X pop bx
- X; ; now get the parameters needed
- X mov al,video_mode
- X mov ah,90 ; all our graphics modes have 90 cols
- X mov bh,active_page
- X; ; and push back onto the stack for return
- X push bx
- X push cx
- X push dx
- X push si
- X push di
- X push es
- X;
- X jmp exit_herc_bios
- X;
- Xint10 endp
- X;
- Xcseg ends
- X end START
- SHAR_EOF
- echo x - extracting shar
- sed 's/^X//' << 'SHAR_EOF' > hercbios.aut
- X
- X================================================================================
- X
- XNewsgroups: net.sources
- XPath: decwrl!pyramid!hplabs!hao!nbires!seismo!caip!clyde!cbatt!cbosgd!ihnp4!drutx!mtuxo!mtuxt!dmt
- XSubject: Hercules graphics BIOS
- XPosted: 28 Aug 86 02:47:07 GMT
- XOrganization: AT&T Information Systems, Holmdel NJ
- X
- X
- XWell, here's the promised Hercules driverfor the PC. It's in SHAR format,
- Xand the instructions for assembly and use are in "hercbios.doc".
- XEnjoy!
- X---------------------------------------------------------------
- X ---=== Dave Tutelman
- X -------===== Physical - AT&T Information Systems
- X ----------====== Room 1H120
- X ==--------======== Juniper Plaza, Route 9
- X ====---========= Freehold, NJ 07728
- X ============ Logical - ...ihnp4!mtuxo!mtuxt!dmt
- X ====== Audible - (201)-577-4232
- X---------------------------------------------------------------SHAR_EOF
- echo x - extracting shar
- sed 's/^X//' << 'SHAR_EOF' > hercbios.h
- X.XLIST
- X page 66,132
- X;************************************************************
- X;
- X; Header file for inclusion in HERCBIOS assemblies
- X;
- X; Dave Tutelman - 8/86
- X;
- X;*************************************************************
- X
- X;iAPX286 equ 1 ; UN-COMMENT FOR A 186 or 286 MACHINE!
- X ; Some of the "ugly" constructs are for speed
- X ; on the 808X, while the "obvious" constructs
- X ; run faster on the 186 & 286.
- XVIDI equ 10H ; video interrupt, 10H for real, 50H for debug
- Xpixbase equ 0B000H ; beginning segment of graphics board
- Xmpx_bios equ 0F000H ; MPX-16 BIOS segment address
- Xvid_offset equ 0F065H ; MPX-16 video offset in BIOS
- Xcharbase equ 0FA6EH ; MPX-16 BIOS character table offset
- Xherc_mode equ 8 ; Hercules graphics mode
- Xibm_mode equ 6 ; IBM Hi-Res color graphics mode.
- X ; we'll try to handle it.
- Xvid_port equ 03B4H ; 6845 index register (data reg = 3B5H )
- X ; (control port = 3B8H )
- X;------------------------------------------
- Xbios segment at mpx_bios ; setup call to vid_bios
- X org vid_offset
- Xvid_bios proc far
- Xvid_bios endp
- Xbios ends
- X;------------------------------------------------
- Xbios_data segment at 040h
- X org 049h
- Xvideo_mode db ? ; current video mode
- Xn_cols dw ? ; number of columns in video display
- X org 050h
- Xcurs_pos dw 8 dup(?) ; cursor for each of 8 pages
- Xcurs_mode dw ? ; cursor mode
- Xactive_page db ? ; current active display page
- Xvideo_base dw ? ; video port base
- Xchip_ctrl db ? ; current setting of 3X8 register
- Xbios_data ends
- X;------------------------------------
- Xintvec segment at 0 ; interrupt vector
- X org 4*1Fh ; interrupt 1FH
- Xuser_table dd ?
- Xintvec ends
- X;------------------------------------
- X
- XIFDEF iAPX286
- X .286c ; allow 286/186-only instructions
- XENDIF
- X
- X.LIST
- SHAR_EOF
- echo x - extracting shar
- sed 's/^X//' << 'SHAR_EOF' > hercdemo.asm
- X page ,132
- X title hercdemo - quick and dirty herc demo
- X;
- X; Hercdemo - (c) 1986 by Reid Brown, P.O. Box 1023, Issaquah, WA. 98027
- X;
- X; This is a quick and dirty program to show off the Hercules
- X; board. I place if freely into the public domain so others
- X; can diddle their Herc boards as well, so long as it is not
- X; used for any commercial purposes.
- X;
- X
- Xmessage macro row,col,string
- X mov cx,row
- X mov bx,col
- X mov si,offset string
- X call print
- X endm
- X
- Xhdraw macro row,col,len
- X mov cx,row
- X mov bx,col
- X mov dx,len
- X call hline
- X endm
- X
- Xvdraw macro row,col,len
- X mov cx,row
- X mov bx,col
- X mov dx,len
- X call vline
- X endm
- X
- Xcode segment
- X assume cs:code, ds:code, es:code, ss:code
- X org 100h
- Xstart: jmp begin
- X
- XIBMROM equ 0F000h
- XCHARTAB equ 0FA6Eh
- XHERCSEG equ 0B800h
- X
- XMODEPORT equ 3B8h
- X
- XSTRING0 db 'HERCULES DEMO',0
- XSTRING1 db 'A funny thing happened on the way to the forum.',0
- XSTRING2 db 'You, too, can have a rewarding career in computers...',0
- XSTRING3 db 'Strike any key to proceed...',0
- X
- X
- XCON8 db 8
- XCON180 db 180
- X
- Xbegin proc near
- X mov dx, MODEPORT ; select herc mode port
- X mov al, 08Ah
- X out dx, al ; graphics mode, video on, page 1
- X
- X call graphics ; set 6845 for graphics
- X call clear ; clear screen RAM
- X
- X vdraw 10,5,20 ; draw a vertical
- X vdraw 10,65,20 ; - hopefully, a box!
- X hdraw 10,6,60 ; draw a line
- X hdraw 30,6,60 ; and another
- X
- X message 12,29,STRING0 ; 1st message
- X message 17,10,STRING1 ; 2nd message
- X message 23,10,STRING2 ; 3nd message
- X message 29,20,STRING3 ; ...
- X
- X;
- X; done - clean up and reset
- X;
- X mov ax, 0C07h ; flush buffer, read char
- X int 21h ; wait for any input
- X
- X call text ; reset 6845
- X
- X mov dx, MODEPORT ; select herc mode port
- X mov al, 00001000B ; re-enable mono
- X out dx, al
- X
- X mov ax, 4C00h
- X int 21h ; exit
- Xbegin endp
- X
- X;
- X; print - print text in graphics mode
- X;
- X; cx = row
- X; bx = column
- X; si = address of string (null terminated) to print
- X;
- Xprint proc near
- X
- Xloop: lodsb ; get next char
- X or al, al ; end of display?
- X je pdone
- X call display
- X inc bx ; bump to next column
- X jmp loop
- Xpdone: ret
- X
- Xprint endp
- X
- X;
- X; display - output an 8x8 character from the IBM ROM to the Herc board
- X;
- X; AX = char, BX = column (0-89), CX = row(0-42) ** all preserved **
- X;
- Xdisplay proc near
- X push ds ; save the lot
- X push es
- X push ax
- X push bx
- X push cx
- X push dx
- X push si
- X push di
- X
- X; setup ds -> IBM ROM, and si -> index into IBM ROM character table located
- X; at 0fa6eh in the ROM
- X
- X and ax, 07fh
- X mul CS:CON8 ; mult by 8 bytes of table per char
- X mov si, ax
- X mov ax, IBMROM
- X mov ds, ax
- X assume ds:nothing
- X add si, CHARTAB ; add offset of character table
- X
- X; compute index into Hercules screen memory for scan line 0. The remaining
- X; seven scan lines are all at fixed offsets from the first.
- X;
- X; Since graphics mode treats the screen as sets of 16x4 "characters",
- X; we need to map an 8x8 real character onto the front or back of
- X; a pair of graphics "characters". The first four scan lines of our
- X; 8x8 character will map to the top graphics "character", and the second
- X; four scan lines map to the graphics character on the "line" (4 scan
- X; lines high) below it.
- X;
- X; For some exotic hardware reason (probably speed), all scan line 0
- X; bits (i.e. every fourth scan line) are stored in memory locations
- X; 0-2000h in the screen buffer. All scan line 1 bits are stored
- X; 2000h-4000h. Within these banks, they are stored by rows. The first
- X; scan line on the screen (scan line 0 of graphics character row 0)
- X; is the first 45 words of memory in the screen buffer. The next 45
- X; words are the first scan line graphics row 1, and since graphics
- X; "characters" are 4 bits high, this second scan line is physically
- X; the fifth scan line displayed on the screen.
- X;
- X; SO, to display an 8x8 character, the 1st and 5th rows of dots are
- X; both scan line 0 of the graphics "character", the 2nd and 6th are
- X; scan line 1, and so on.
- X;
- X; The column (0-89) tells which byte in a scan line we need to load.
- X; Since it takes two rows of graphics characters to hold one row of
- X; our characters, column+90 is a index to scan line 4 rows of pixels
- X; higher (n+4). Thus 180 bytes of screen memory in any bank (0h, 2000h,
- X; 4000h, 6000h) represent a row of 8x8 characters.
- X;
- X; The starting location in screen memory for the first scan line of
- X; a character to be displayed will be: (row*180)+column
- X; The 5th scan line will be at: (row*180)+column+90
- X;
- X; The second and 6th scan lines will be at the above offsets plus
- X; the bank offset of 2000h. The third and 7th, add 4000h and finally
- X; the 4th and 8th, add 6000h.
- X;
- X mov ax, HERCSEG
- X mov es, ax ; es = hercules page 0
- X mov ax, cx ; get row
- X mul CS:CON180 ; mult by 180(10)
- X mov di, ax ; di = index reg
- X cld ; insure right direction
- X
- X;output 8 segments of character to video ram
- X
- X lodsb ; line 0
- X mov es:[di+bx], al
- X lodsb
- X mov es:[di+bx+2000h], al ; line 1
- X lodsb
- X mov es:[di+bx+4000h], al ; line 2
- X lodsb
- X mov es:[di+bx+6000h], al ; line 3
- X lodsb
- X mov es:[di+bx+90], al ; line 4
- X lodsb
- X mov es:[di+bx+2000h+90], al ; line 5
- X lodsb
- X mov es:[di+bx+4000h+90], al ; line 6
- X lodsb
- X mov es:[di+bx+6000h+90], al ; line 7
- X
- X pop di
- X pop si
- X pop dx
- X pop cx
- X pop bx
- X pop ax
- X pop es
- X pop ds
- X ret
- Xdisplay endp
- X
- X;
- X; clear - clear page 1 of the screen buffer to zero (effectively, blank
- X; the screen)
- X;
- Xclear proc
- X push es
- X push ax
- X push cx
- X push di
- X
- X mov ax, HERCSEG
- X mov es, ax
- X xor di, di
- X mov cx, 4000h
- X xor ax, ax
- X cld
- X
- X rep stosw ; zero out screen page
- X
- X pop di
- X pop cx
- X pop ax
- X pop es
- X ret
- Xclear endp
- X
- X;
- X; hline - draw a horizontal line at scan line 0 of a specified 8x8 character
- X; cell sized row, for a specified no. of characters
- X;
- X; cx = row
- X; bx = col
- X; dx = len
- X;
- Xhline proc near
- X push es
- X push ax
- X push cx
- X push di
- X
- X mov ax,cx ; copy to accum for multiply
- X mul cs:CON180 ; mult by 180 to get offset
- X mov di,ax ; copy to dest ptr
- X add di,bx ; add column offset
- X mov cx,dx ; put byte count in count reg
- X mov ax, HERCSEG
- X mov es, ax
- X mov ax, 0ffh ; pattern = all bits ON
- X cld
- X
- X rep stosb ; put bits on screen
- X
- X pop di
- X pop cx
- X pop ax
- X pop es
- X ret
- X
- Xhline endp
- X
- X;
- X; vline - draw a vertical line in the last bit position of a given char
- X; cell, extending downward for a specified no. of chars
- X;
- X; cx = row
- X; bx = col
- X; dx = len
- X;
- Xvline proc near
- X push es
- X push ax
- X push cx
- X push di
- X
- X mov ax,cx ; copy to accum for multiply
- X mul cs:CON180 ; mult by 180 to get offset
- X mov di,ax ; copy to dest ptr
- X mov cx,dx ; put byte count in count reg
- X mov ax, HERCSEG
- X mov es, ax
- X mov ax, 1 ; pattern = last bit on
- X
- Xvloop: mov es:[di+bx], al
- X mov es:[di+bx+2000h], al ; line 1
- X mov es:[di+bx+4000h], al ; line 2
- X mov es:[di+bx+6000h], al ; line 3
- X mov es:[di+bx+90], al ; line 4
- X mov es:[di+bx+2000h+90], al ; line 5
- X mov es:[di+bx+4000h+90], al ; line 6
- X mov es:[di+bx+6000h+90], al ; line 7
- X add di,180 ; advance to next line
- X loop vloop ; continue for all rows
- X
- X pop di
- X pop cx
- X pop ax
- X pop es
- X ret
- X
- Xvline endp
- X
- Xgraphics proc near
- X mov si, offset graph_parms
- Xg_cont: mov dx, 3b4h ; point to index reg
- X mov cx, 16
- X xor ax, ax
- Xg_loop: mov al, ah
- X out dx, al
- X inc dx
- X mov al, [si]
- X out dx, al
- X dec dx
- X inc ah
- X inc si
- X loop g_loop
- X ret
- Xgraph_parms db 35h,2dh,2eh,7,5bh,2,57h,57h,2,3,0,0,0,0,0,0
- Xgraphics endp
- X
- Xtext proc near
- X mov si, offset text_parms
- X jmp g_cont
- Xtext_parms db 61h,50h,52h,0fh,19h,6,19h,19h,2,0dh,0bh,0ch,00,00,00,00
- Xtext endp
- X
- X
- Xcode ends
- X
- X end start
- SHAR_EOF
- echo x - extracting shar
- sed 's/^X//' << 'SHAR_EOF' > hercmake.att
- X
- X# Makefile for HERCBIOS.COM
- XSRC=hercbios gchar graph
- XDEST=a:
- X
- Xhercbios.com : hercbios.obj gchar.obj graph.obj
- X link hercbios gchar graph,,/MAP;
- X exe2bin hercbios.exe hercbios.com
- X del hercbios.exe
- X
- Xhercbios.obj : hercbios.asm hercbios.h
- Xgchar.obj : gchar.asm hercbios.h
- Xgraph.obj : graph.asm hercbios.h
- X
- X
- X# Makes for the demo & test program, using deSmet C
- X
- Xtestpix.exe : testpix.o hercpixl.o
- X bind testpix hercpixl
- X
- Xtestpix.o : testpix.c
- X c88 testpix
- X
- Xhercpixl.o : hercpixl.c
- X c88 hercpixl
- X
- X# Make a backup or distribution disk
- Xbackup :
- X for %f in ($(SRC)) do copy %f.asm $(DEST)
- X copy hercbios.h $(DEST)
- X copy hercbios.com $(DEST)
- X copy hercbios.doc $(DEST)
- X copy makefile $(DEST)
- X
- Xdistrib :
- X make backup
- X copy hercpixl.c $(DEST)
- X copy testpix.* $(DEST)
- X copy hcharset.* $(DEST)SHAR_EOF
- echo x - extracting shar
- sed 's/^X//' << 'SHAR_EOF' > hercmake.lcm
- X#
- X# Makefile for HERCBIOS.COM
- X# (designed for Larry Campbell's version of MAKE)
- X#
- X
- Xhercbios.com : hercbios.obj gchar.obj graph.obj
- X link hercbios gchar graph,,/MAP;
- X exe2bin hercbios.exe hercbios.com
- X del hercbios.exe
- X
- Xhercbios.obj : hercbios.asm hercbios.h
- X masm hercbios,,;
- X
- Xgchar.obj : gchar.asm hercbios.h
- X masm gchar,,;
- X
- Xgraph.obj : graph.asm hercbios.h
- X masm graph,,;
- X
- X
- X#
- X# Makes for the demo & test program, using Lattice
- X# (Note: you may have to change the drive and path specs)
- X#
- X
- Xtestpix.exe : testpix.obj hercpixl.obj
- X link g:\lc\s\c testpix hercpixl,testpix,testpix/m,g:\lc\s\lc
- X
- Xtestpix.obj : testpix.c
- X lc -ms -n -ig:\lc\ testpix
- X
- Xhercpixl.obj : hercpixl.c
- X lc -ms -n -ig:\lc\ hercpixl
- SHAR_EOF
- echo x - extracting shar
- sed 's/^X//' << 'SHAR_EOF' > hercpixl.dc
- X/*
- X * HERCPIXL.C
- X * Dave Tutelman - last modified 8/86
- X *
- X * This is a set of basic graphic routines for the Hercules
- X * Board (or at least the SuperComputer version of it; I assume
- X * that they work with the real thing).
- X * alfa () puts us in alphanumeric mode.
- X * grafix (page) puts us in graphics mode in page 0 or 1
- X * pixel (x,y,val) puts a pixel at <x,y>. Bright dot if
- X * val=1, dark dot if val=0.
- X * dchar (x,y,c) puts character "c" at <x,y>. Note that
- X * character raster is 90 x 29.
- X * swpage (page) switches to a different page.
- X * waitkey () just waits till a key is pressed.
- X *
- X * Actually, the routines should work with any board, since the
- X * BIOS calls are used throughout. It's Hercules-specific only
- X * because I've defined the graphics and alpha modes for my
- X * Hercules BIOS.
- X *
- X * Compile with deSmet C.
- X */
- X
- X#define VIDI 0x10 /* video interrupt, normally 10H */
- X#define KBD 0x16 /* keyboard interrupt */
- X#define ALFA_MODE 7 /* monochrome alpha mode */
- X#define GRAF_MODE 8 /* Hercules graphics mode */
- X
- Xint page = 0;
- Xextern unsigned _rax,_rbx,_rcx,_rdx;
- X
- X/*
- X * This puts us back in alphanumeric mode
- X */
- X
- Xalfa (dummy)
- X unsigned int dummy;
- X{
- X _rax = ALFA_MODE; /* mono 80-col mode */
- X _doint ( VIDI ); /* set mode */
- X}
- X
- X/*
- X * This one switches us to hercules graphics mode
- X * in page 0 or 1
- X */
- X
- Xgrafix (newpage)
- X int newpage;
- X{
- X
- X _rax = GRAF_MODE; /* herc grafix mode */
- X _doint ( VIDI ); /* set mode */
- X
- X /* now set the page */
- X swpage (newpage);
- X}
- X
- X/*
- X * This writes a pixel at (x,y), where (0,0) is the upper-left
- X * corner of the screen. If val = 0 then the pixel is erased.
- X */
- X
- Xpixel (x, y, val)
- X int x, y, val;
- X{
- X
- X _rax = 0x0C00 + val; /* function 12 */
- X _rcx = x;
- X _rdx = y;
- X _doint ( VIDI ); /* set mode */
- X
- X}
- X
- X
- X/*
- X * dchar (x,y,c) puts character "c" at <x,y>. Note that
- X * character raster is 90 x 25.
- X */
- X
- Xdchar (x,y,c)
- X int x,y;
- X char c;
- X{
- X
- X _rax = 2*256; /* AH=Fn#2 */
- X _rdx = 256*y + x; /* DH=row, DX=col */
- X _rbx = page * 256; /* BH=page */
- X _doint (VIDI); /* set cursor */
- X
- X _rax = 10*256 + (int) c; /* AH=Fn#10, AL=char */
- X _rbx = page * 256; /* BH=page */
- X _rcx = 1; /* CX=count */
- X _doint (VIDI); /* write character */
- X}
- X
- X
- X/*
- X * This one switches us to a different page, without changing
- X * the contents of that page.
- X */
- X
- Xswpage (newpage)
- X int newpage;
- X{
- X page = newpage;
- X _rax = 0x500 + page; /* new page function */
- X _doint ( VIDI ); /* interrupt call */
- X}
- X
- X
- Xwaitkey ()
- X{
- X _rax = 0; /* keyboard blocking read function */
- X _doint (KBD);
- X}
- SHAR_EOF
- echo x - extracting shar
- sed 's/^X//' << 'SHAR_EOF' > hercpixl.lc
- X/*
- X * HERCPIXL.C
- X * Dave Tutelman - last modified 8/86
- X *
- X * This is a set of basic graphic routines for the Hercules
- X * Board (or at least the SuperComputer version of it; I assume
- X * that they work with the real thing).
- X * alfa () puts us in alphanumeric mode.
- X * grafix (page) puts us in graphics mode in page 0 or 1
- X * pixel (x,y,val) puts a pixel at <x,y>. Bright dot if
- X * val=1, dark dot if val=0.
- X * dchar (x,y,c) puts character "c" at <x,y>. Note that
- X * character raster is 90 x 29.
- X * swpage (page) switches to a different page.
- X * waitkey () just waits till a key is pressed.
- X *
- X * Actually, the routines should work with any board, since the
- X * BIOS calls are used throughout. It's Hercules-specific only
- X * because I've defined the graphics and alpha modes for my
- X * Hercules BIOS.
- X *
- X * Modified for Lattice C: Reid L. Brown
- X * 9/4/86
- X */
- X
- X#define VIDI 0x10 /* video interrupt, normally 10H */
- X#define KBD 0x16 /* keyboard interrupt */
- X#define ALFA_MODE 7 /* monochrome alpha mode */
- X#define GRAF_MODE 8 /* Hercules graphics mode */
- X
- Xint page = 0;
- Xstruct {
- X unsigned ax,bx,cx,dx,si,di;
- X } _r;
- X
- X/*
- X * This puts us back in alphanumeric mode
- X */
- X
- Xalfa (dummy)
- X unsigned int dummy;
- X{
- X _r.ax = ALFA_MODE; /* mono 80-col mode */
- X int86 ( VIDI, &_r, &_r); /* set mode */
- X}
- X
- X/*
- X * This one switches us to hercules graphics mode
- X * in page 0 or 1
- X */
- X
- Xgrafix (newpage)
- X int newpage;
- X{
- X
- X _r.ax = GRAF_MODE; /* herc grafix mode */
- X int86 ( VIDI, &_r, &_r); /* set mode */
- X
- X /* now set the page */
- X swpage (newpage);
- X}
- X
- X/*
- X * This writes a pixel at (x,y), where (0,0) is the upper-left
- X * corner of the screen. If val = 0 then the pixel is erased.
- X */
- X
- Xpixel (x, y, val)
- X int x, y, val;
- X{
- X
- X _r.ax = 0x0C00 + val; /* function 12 */
- X _r.cx = x;
- X _r.dx = y;
- X int86 ( VIDI, &_r, &_r); /* set mode */
- X
- X}
- X
- X
- X/*
- X * dchar (x,y,c) puts character "c" at <x,y>. Note that
- X * character raster is 90 x 25.
- X */
- X
- Xdchar (x,y,c)
- X int x,y;
- X char c;
- X{
- X
- X _r.ax = 2*256; /* AH=Fn#2 */
- X _r.dx = 256*y + x; /* DH=row, DX=col */
- X _r.bx = page * 256; /* BH=page */
- X int86 ( VIDI, &_r, &_r); /* set cursor */
- X
- X _r.ax = 10*256 + (int) c; /* AH=Fn#10, AL=char */
- X _r.bx = page * 256; /* BH=page */
- X _r.cx = 1; /* CX=count */
- X int86 ( VIDI, &_r, &_r); /* write character */
- X}
- X
- X
- X/*
- X * This one switches us to a different page, without changing
- X * the contents of that page.
- X */
- X
- Xswpage (newpage)
- X int newpage;
- X{
- X page = newpage;
- X _r.ax = 0x500 + page; /* new page function */
- X int86 ( VIDI, &_r, &_r ); /* interrupt call */
- X}
- X
- X
- Xwaitkey ()
- X{
- X _r.ax = 0; /* keyboard blocking read function */
- X int86 (KBD, &_r, &_r );
- X}
- SHAR_EOF
- echo x - extracting shar
- sed 's/^X//' << 'SHAR_EOF' > testpix.c
- X
- X/* MAIN tests PIXEL by drawing lines on the screen */
- X
- X#include "stdio.h"
- X
- Xmain ()
- X{
- X int i,j;
- X char line [90];
- X
- X /* first clear screen */
- X grafix (0);
- X
- X /* now draw a couple of lines */
- X for (i=0; i<696; i++)
- X {
- X pixel (i, i/2, 1);
- X pixel (i, 348 - i/2, 1);
- X }
- X
- X waitkey(); /* wait for CR */
- X
- X /* a different pattern on page 1 */
- X swpage (1);
- X for (i=0; i<720; i++)
- X for (j=0; j<348; j=j+50)
- X pixel (i,j,1);
- X for (i=0; i<720; i=i+90)
- X for (j=0; j<348; j++)
- X pixel (i,j,1);
- X
- X /* switch back and forth a couple of times */
- X waitkey();
- X swpage (0);
- X waitkey();
- X swpage (1);
- X waitkey();
- X swpage (0);
- X waitkey();
- X swpage (1);
- X waitkey();
- X
- X#ifndef NOTONE
- X /* add some writing */
- X dline (10, 4, "Hello, there!");
- X dline (10, 5, "Second LINE of text.");
- X dline (10, 6, "all on display page 1.");
- X
- X waitkey();
- X for (i=0; i<8; i++)
- X for (j=0; j<32; j++)
- X dchar (j+5, i+13, (char) (32*i+j));
- X
- X waitkey();
- X#endif
- X /* repeat for page 0 */
- X swpage (0);
- X
- X#ifndef NOTZERO
- X /* add some writing */
- X dline (10, 4, "Hello, there!");
- X dline (10, 5, "Second LINE of text.");
- X dline (10, 6, "this time on display page 0.");
- X
- X waitkey();
- X for (i=0; i<8; i++)
- X for (j=0; j<32; j++)
- X dchar (j+5, i+13, (char) (32*i+j));
- X#endif
- X
- X waitkey();
- X
- X /* back to alpha mode */
- X waitkey();
- X alfa();
- X}
- X
- Xdline (x, y, chstr) /* write character-string at x,y */
- X int x,y;
- X char chstr [90];
- X{
- X int i;
- X char *p;
- X
- X i=0;
- X for ( p=chstr; *p != '\0'; p++ )
- X {
- X dchar ( x+i, y, *p );
- X i++;
- X }
- X}
- SHAR_EOF
- exit
-