1 TITLE Hercules graphics module
3 ; Michael Gordon - 8-Dec-86
5 ; Certain routines were taken from the Hercules BIOS of Dave Tutelman - 8/86
6 ; Others came from pcgraph.asm included in GNUPLOT by Colin Kelley
8 ; modified slightly by Colin Kelley - 22-Dec-86
9 ; added header.mac, parameterized declarations
10 ; added dgroup: in HVmodem to reach HCh_Parms and HGr_Parms - 30-Jan-87
11 ; modified by Russell Lang 3 Jun 1988
21 GPg1_Base equ 0B800h ; Graphics page 1 base address
25 public _H_line, _H_color, _H_mask, _HVmode, _H_puts
28 HCfg_Switch equ 03BFH ; Configuration Switch - software switch
29 ; to select graphics card memory map
32 mov al, 03H ; allow graphics in b8000:bffff
51 ; [couldn't this be done faster with a lookup table? -cdk]
53 ; first compute the address of byte to be modified
54 ; = 90*[row/4] + [col/8] + 2^D*[row/4] + 2^F*page
55 mov bh,cl ; col (low order) in BH
56 mov bl,dl ; row (low order) in BL
57 and bx,0703H ; mask the col & row remainders
62 mul dx ; AX = 90*[ row/4 ]
63 add ax,cx ; ... + col/8
64 shl bl,5 ; align row remainder
65 ELSE ; same as above, obscure but fast for 8086
66 shr cx,1 ; divide col by 8
69 shr dx,1 ; divide row by 4
71 shl dx,1 ; begin fast multiply by 90 (1011010 B)
80 add ax,dx ; end fast multiply by 90
81 add ax,cx ; add on the col/8
82 shl bl,1 ; align row remainder
88 add ah,bl ; use aligned row remainder
89 end_adr_calc: ; address of byte is now in AX
90 mov dx,GPg1_Base ; base of pixel display to DX
91 mov es,dx ; ...and thence to segment reg
92 mov si,ax ; address of byte w/ pixel to index reg
93 mov cl,bh ; bit addr in byte
94 mov al,80H ; '1000 0000' in AL
95 shr al,cl ; shift mask to line up with bit to read/write
96 set_pix: ; set the pixel
97 or es:[si],al ; or the mask with the right byte
106 lineproc _H_line, hpixel
109 ; clear - clear page 1 of the screen buffer to zero (effectively, blank
123 rep stosw ; zero out screen page
134 mov al,[bp+X] ; color
135 mov byte ptr color,al
144 mov word ptr bmask,ax
149 HCtrl_Port equ 03B8H ; Hercules 6845 control port IO addr
150 HIndx_Port equ 03B4H ; Hercules 6845 index port IO addr
151 HScrn_Enable equ 008h ; Control port bit to enable video
152 HCh_Mode equ 020h ; Character output mode
153 HGr_Mode equ 082h ; Graphics output mode page 1
163 mov al, HCh_Mode ; Assume character mode is wanted
164 mov si, offset dgroup:HCh_Parms
165 cmp ah, 0 ; nonzero means switch to graphics
167 call near ptr clear ; clear the graphics page
169 mov si, offset dgroup:HGr_Parms
172 out dx, al ; Set Hercules board to proper mode
173 call near ptr setParms ; Set the 6845 parameters
174 or al, HScrn_Enable ; Enable the video output
181 setParms proc near ; Send 6845 parms to Hercules board
185 mov dx, HIndx_Port ; Index port addr -> DX
186 mov ah, 0 ; 0 -> parameter counter
189 out dx, al ; output to 6845 addr register
190 inc dx ; next output to data register
191 mov al, [si] ; next control byte -> al
193 out dx, al ; output control byte
194 dec dx ; 6845 index addr -> dx
204 ; H_puts - print text in graphics mode
208 ; si = address of string (null terminated) to print
215 mov si, [bp+X] ; string offset
218 mov ds, [bp+X+2] ; string segment
219 mov cx, [bp+X+4] ; row
220 mov bx, [bp+X+6] ; col
222 mov cx, [bp+X+2] ; row
223 mov bx, [bp+X+4] ; col
226 ploop: lodsb ; get next char
227 or al, al ; end of display?
229 call near ptr display
230 inc bx ; bump to next column
239 ; display - output an 8x8 character from the IBM ROM to the Herc board
241 ; AX = char, BX = column (0-89), CX = row(0-42) ** all preserved **
249 push ds ; save the lot
258 ; setup ds -> IBM ROM, and si -> index into IBM ROM character table located
259 ; at 0fa6eh in the ROM
262 mul cs:CON8 ; mult by 8 bytes of table per char
267 add si, CHARTAB ; add offset of character table
269 ; compute index into Hercules screen memory for scan line 0. The remaining
270 ; seven scan lines are all at fixed offsets from the first.
272 ; Since graphics mode treats the screen as sets of 16x4 "characters",
273 ; we need to map an 8x8 real character onto the front or back of
274 ; a pair of graphics "characters". The first four scan lines of our
275 ; 8x8 character will map to the top graphics "character", and the second
276 ; four scan lines map to the graphics character on the "line" (4 scan
277 ; lines high) below it.
279 ; For some exotic hardware reason (probably speed), all scan line 0
280 ; bits (i.e. every fourth scan line) are stored in memory locations
281 ; 0-2000h in the screen buffer. All scan line 1 bits are stored
282 ; 2000h-4000h. Within these banks, they are stored by rows. The first
283 ; scan line on the screen (scan line 0 of graphics character row 0)
284 ; is the first 45 words of memory in the screen buffer. The next 45
285 ; words are the first scan line graphics row 1, and since graphics
286 ; "characters" are 4 bits high, this second scan line is physically
287 ; the fifth scan line displayed on the screen.
289 ; SO, to display an 8x8 character, the 1st and 5th rows of dots are
290 ; both scan line 0 of the graphics "character", the 2nd and 6th are
291 ; scan line 1, and so on.
293 ; The column (0-89) tells which byte in a scan line we need to load.
294 ; Since it takes two rows of graphics characters to hold one row of
295 ; our characters, column+90 is a index to scan line 4 rows of pixels
296 ; higher (n+4). Thus 180 bytes of screen memory in any bank (0h, 2000h,
297 ; 4000h, 6000h) represent a row of 8x8 characters.
299 ; The starting location in screen memory for the first scan line of
300 ; a character to be displayed will be: (row*180)+column
301 ; The 5th scan line will be at: (row*180)+column+90
303 ; The second and 6th scan lines will be at the above offsets plus
304 ; the bank offset of 2000h. The third and 7th, add 4000h and finally
305 ; the 4th and 8th, add 6000h.
308 mov es, ax ; es = hercules page 0
310 mul cs:CON180 ; mult by 180(10)
311 mov di, ax ; di = index reg
312 cld ; insure right direction
314 ;output 8 segments of character to video ram
319 mov es:[di+bx+2000h], al ; line 1
321 mov es:[di+bx+4000h], al ; line 2
323 mov es:[di+bx+6000h], al ; line 3
325 mov es:[di+bx+90], al ; line 4
327 mov es:[di+bx+2000h+90], al ; line 5
329 mov es:[di+bx+4000h+90], al ; line 6
331 mov es:[di+bx+6000h+90], al ; line 7
352 HCh_Parms db 61H, 50H, 52H, 0FH, 19H, 06H, 19H, 19H, 02H, 0DH, 0BH, 0CH
353 HGr_Parms db 35H, 2DH, 2EH, 07H, 5BH, 02H, 57H, 57H, 02H, 03H, 00H, 00H