Icons are changed
[gnuplot] / src / hrcgraph.asm
1 TITLE   Hercules graphics module
2
3 ;       Michael Gordon - 8-Dec-86
4 ;
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
7 ;
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
12 ;       added H_init
13
14 include header.mac
15
16 if1
17 include lineproc.mac
18 endif
19
20
21 GPg1_Base equ 0B800h    ; Graphics page 1 base address
22
23 _text   segment
24
25         public _H_line, _H_color, _H_mask, _HVmode, _H_puts
26         public _H_init
27
28 HCfg_Switch equ 03BFH   ; Configuration Switch - software switch 
29                         ; to select graphics card memory map
30
31 beginproc _H_init
32         mov al, 03H     ; allow graphics in b8000:bffff
33         mov dx, HCfg_Switch
34         out dx, al
35         ret
36 _H_init endp
37
38 hpixel  proc near
39         ror word ptr bmask,1
40         jc cont
41         ret
42 cont:
43         push ax
44         push bx
45         push cx
46         push dx
47         push si
48         mov cx,ax               ; x
49         mov dx,bx               ; y
50 ;
51 ; [couldn't this be done faster with a lookup table? -cdk]
52 ;
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
58 IFDEF iAPX286
59         shr     cx,3            ; col / 8
60         shr     dx,2            ; row / 4
61         mov     al,90
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
67         shr     cx,1
68         shr     cx,1
69         shr     dx,1            ; divide row by 4
70         shr     dx,1
71         shl     dx,1            ; begin fast multiply by 90 (1011010 B)
72         mov     ax,dx
73         shl     dx,1
74         shl     dx,1
75         add     ax,dx
76         shl     dx,1
77         add     ax,dx
78         shl     dx,1
79         shl     dx,1
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
83         shl     bl,1
84         shl     bl,1
85         shl     bl,1
86         shl     bl,1
87 ENDIF
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
98         pop si
99         pop dx
100         pop cx
101         pop bx
102         pop ax
103         ret
104 hpixel endp
105
106 lineproc _H_line, hpixel
107
108 ;
109 ; clear - clear page 1 of the screen buffer to zero (effectively, blank
110 ;       the screen)
111 ;
112 clear   proc near
113         push es
114         push ax
115         push cx
116         push di
117         mov ax, GPg1_Base
118         mov es, ax
119         xor di, di
120         mov cx, 4000h
121         xor ax, ax
122         cld
123         rep stosw                       ; zero out screen page
124         pop di
125         pop cx
126         pop ax
127         pop es
128         ret
129 clear   endp
130
131 beginproc _H_color
132         push bp
133         mov bp,sp
134         mov al,[bp+X]                   ; color
135         mov byte ptr color,al
136         pop bp
137         ret
138 _H_color endp
139
140 beginproc _H_mask
141         push bp
142         mov bp,sp
143         mov ax,[bp+X]                   ; mask
144         mov word ptr bmask,ax
145         pop bp
146         ret
147 _H_mask endp
148
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
154
155 parm_count equ 12
156
157 beginproc _HVmode
158         push bp
159         mov bp, sp
160         push si
161         mov ax, [bp+X]
162         or ah, al
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
166         jz vmode_ok
167         call near ptr clear             ; clear the graphics page
168         mov al, HGr_Mode
169         mov si, offset dgroup:HGr_Parms
170 vmode_ok:
171         mov dx, HCtrl_Port
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
175         out dx, al
176         pop si
177         pop bp
178         ret
179 _HVmode endp
180
181 setParms proc near              ; Send 6845 parms to Hercules board
182         push ax
183         push dx
184         push si                 
185         mov dx, HIndx_Port      ; Index port addr -> DX
186         mov ah, 0               ; 0 -> parameter counter
187 sp_loop:
188         mov al, ah
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
192         inc si
193         out dx, al              ; output control byte
194         dec dx                  ; 6845 index addr -> dx
195         inc ah                  ; bump addr
196         cmp ah, parm_count
197         jnz sp_loop
198         pop si
199         pop dx
200         pop ax
201         ret
202 setParms endp
203
204 ; H_puts - print text in graphics mode
205 ;
206 ;       cx = row
207 ;       bx = column
208 ;       si = address of string (null terminated) to print
209
210 beginproc _H_puts
211         push bp
212         mov bp, sp
213         push si
214         push ds
215         mov si, [bp+X]                  ; string offset
216
217 ifdef LARGE_DATA
218         mov ds, [bp+X+2]                ; string segment
219         mov cx, [bp+X+4]                ; row
220         mov bx, [bp+X+6]                ; col
221 else
222         mov cx, [bp+X+2]                ; row
223         mov bx, [bp+X+4]                ; col
224 endif
225
226 ploop:  lodsb                           ; get next char
227         or      al, al                  ; end of display?
228         je      pdone
229         call near ptr display
230         inc     bx                      ; bump to next column
231         jmp     ploop
232 pdone:  pop ds
233         pop si
234         pop bp
235         ret
236 _H_puts endp
237
238 ;
239 ; display - output an 8x8 character from the IBM ROM to the Herc board
240 ;
241 ; AX = char, BX = column (0-89), CX = row(0-42)  ** all preserved **
242 ;
243 CON8    db      8
244 CON180  db      180
245 IBMROM  equ     0F000h
246 CHARTAB equ     0FA6Eh
247
248 display proc near
249         push    ds                      ; save the lot
250         push    es
251         push    ax
252         push    bx
253         push    cx
254         push    dx
255         push    si
256         push    di
257
258 ; setup ds -> IBM ROM, and si -> index into IBM ROM character table located
259 ;       at 0fa6eh in the ROM
260
261         and     ax, 07fh
262         mul     cs:CON8                 ; mult by 8 bytes of table per char
263         mov     si, ax
264         mov     ax, IBMROM
265         mov     ds, ax
266         assume  ds:nothing
267         add     si, CHARTAB             ; add offset of character table
268
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.
271 ;
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.
278 ;
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.
288 ;
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.
292 ;
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.
298 ;       
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
302 ;
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.
306 ;
307         mov     ax, GPg1_Base
308         mov     es, ax                  ; es = hercules page 0
309         mov     ax, cx                  ; get row
310         mul     cs:CON180               ; mult by 180(10)
311         mov     di, ax                  ; di = index reg
312         cld                             ; insure right direction
313
314 ;output 8 segments of character to video ram
315
316         lodsb                           ; line 0
317         mov     es:[di+bx], al
318         lodsb
319         mov     es:[di+bx+2000h], al    ; line 1
320         lodsb
321         mov     es:[di+bx+4000h], al    ; line 2
322         lodsb
323         mov     es:[di+bx+6000h], al    ; line 3
324         lodsb
325         mov     es:[di+bx+90], al       ; line 4
326         lodsb
327         mov     es:[di+bx+2000h+90], al ; line 5
328         lodsb
329         mov     es:[di+bx+4000h+90], al ; line 6
330         lodsb
331         mov     es:[di+bx+6000h+90], al ; line 7
332
333         pop     di
334         pop     si
335         pop     dx
336         pop     cx
337         pop     bx
338         pop     ax
339         pop     es
340         pop     ds
341         ret
342 display endp
343
344 _text   ends
345
346 _data   segment
347 bmask   dw -1
348 color   db 1
349 _data   ends
350
351 const   segment
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
354 const   ends
355
356         end
357
358