;Hercules Graphics Card driver ;************************************************************************** ;* DEVICE SPECIFIC ROUTINES * ;* * ;* These routines and equates are device dependent. * ;* * ;* * ;* * ;************************************************************************** ;Hist ;Name Date Modification ; dseg copyright db 'GEMVDI V1.2 5/25/85' db 'Hercules Card' db 'Serial No. XXXX-0000-654321 ' db 'All Rights Reserved' db 'Copyright (C) 1985 ' db 'Digital Research Inc.' cseg ; public INIT_G,DINIT_G public CONCAT public TRAN_FM public EX_TIMV public S_COLMAP public I_COLMAP ; extrn entry:near ;the place to jump to if this module ;integer array indexing equates W_1 equ word ptr 0 W_2 equ word ptr 2 W_3 equ word ptr 4 W_4 equ word ptr 6 W_5 equ word ptr 8 W_6 equ word ptr 10 W_7 equ word ptr 12 W_8 equ word ptr 14 W_9 equ word ptr 16 W_10 equ word ptr 18 ; include externs.a86 ibmvdi equ 0 ;leave out the old code if for retail ; ;**************************************************************** ; IBM STANDARD ROM BIOS CALLS * ;**************************************************************** SCREEN equ 10H ;interrupts to use for rom routine I/O KEYBD equ 16H rev_vid_on equ 70h ;turn on reverse video bits rev_vid_off equ 07h ;turn off reverse video bits ; read_cur_pos equ 3 ;bios rom calls for char I/O set_cur_pos equ 2 read_char equ 8 write_char equ 9 set_palette equ 0bh get_character equ 0 ;keyboard read ; EJECT ; jmp entry ;if we come in from here, go to real entry ;**************************************** ;escape func 2 ; Enter Graphics Mode ;**************************************** INIT_G: pushf mov ax,cs mov usermot+2,ax ;init the user call vectors segs mov userbut+2,ax mov usercur+2,ax mov ax,offset umotvec mov usermot,ax mov ax,offset ubutvec mov userbut,ax mov ax,offset mov_cur mov usercur,ax popf escfn2: mov dispmode,0 ; call clearmem ; clear graphics display mov dx, 03bfh mov al, 1 out dx, al ; allow graphics on new cards mov si,offset crt_init_table_g mov al,2h call crt_init if mouse mov bl,1 call mouse_function ;initialize the mouse mov bl,2 call mouse_function mov bl,1 call mouse_function endif ret ; ;**************************************** ;escape func 3 ; Exit Graphics Mode ;**************************************** DINIT_G: escfn3: ; if mouse mov bl,2 ;de init the mouse call mouse_function endif mov dispmode,1 ; call clearmem ; clear graphics display. mov si,offset crt_init_table_a mov al,20h ; alpha mode call crt_init mov attribute,rev_vid_off if ibmvdi call escfn8 ;home call escfn9 ;clear to end of screen else mov ah,2 ;set cursor position 0,0 xor dx, dx mov bh, dh int 10h mov ah, 9 xor bh, bh mov cx, 2000 mov al, 20h mov bl, 7 int 10h endif ret ; ;***************************************************************** ;crt_init ; initializes the display controller with data from table ;***************************************************************** crt_init: push ax mov dx,3b8h out dx,al mov dx,03b4h ;select port mov cx,12 xor ah,ah crt_init_loop: mov al,ah out dx,al inc dx lodsb out dx,al inc ah dec dx loop crt_init_loop mov dx,3b8h pop ax add al,8 out dx,al ret EJECT ;**************************************************************** ;I_COLMAP * ; ENTRY * ; INTIN[0] = color index * ; INTIN[1] = req or actual flag * ; * ; EXIT * ; INTOUT[0] = color index * ; INTOUT[1] = RED * ; INTOUT[2] = GRN * ; INTOUT[3] = BLU * ; * ; Reg. Used. AX, BX, CX, DX, DI * ; * ;**************************************************************** I_COLMAP: mov bx, INTIN ;check if the index is in range of dev cmp bx, 0 jge i_colmap_chkix jmps i_colmap_badix i_colmap_chkix: cmp bx, num_colors-1 ;test if index is too high jle i_colmap_ixok jmps i_colmap_badix i_colmap_ixok: shl bx, 1 mov bx, MAP_COL[bx] mov di, bx ; di = ptr to act/req col tbls shl di, 1 shl di, 1 add di, bx add di, bx ; mpy ix by 6 to point into table mov si, offset INTOUT+2 mov cx, 3 mov INTOUT, bx ; return the color index mov bx, offset req_col_tbl test INTIN+2, 0ffffh ; if != 0 then return actual values jz i_colmap_load mov bx, offset act_col_tbl i_colmap_load: mov ax, [bx+di] mov [si], ax add di, 2 add si, 2 loop i_colmap_load ret i_colmap_badix: mov INTOUT, -1 ret EJECT ;**************************************************************** ;S_COLMAP * ; ENTRY * ; INTIN[0] = color index * ; INTIN[1] = RED 0 - 1000 * ; INTIN[1] = GRN 0 - 1000 * ; INTIN[1] = BLU 0 - 1000 * ; * ; EXIT * ; * ; * ; Reg. Used. AX, BX, CX, DX, DI * ; * ;**************************************************************** S_COLMAP: mov bx, INTIN ;check if the index is in range of dev cmp bx, 0 jge s_colmap_chkix jmp s_colmap_exit s_colmap_chkix: cmp bx, num_colors-1 ;test if index is too high jle s_colmap_ixok jmp s_colmap_exit s_colmap_ixok: shl bx, 1 mov bx, MAP_COL[bx] mov di, bx ; di = ptr to act/req col tbls shl di, 1 shl di, 1 add di, bx add di, bx ; mpy ix by 6 to point into table mov dx, INTIN+2 ; get the red value call s_colmap_val mov dx, INTIN+4 ; get the grn value call s_colmap_val mov dx, INTIN+6 ; get the blu values call s_colmap_val s_colmap_exit: ret ; s_colmap_val: mov req_col_tbl[di], dx ; save the requested value add di, 2 ; move to the next value ret EJECT ;**************************************************************** ;CONCAT * ; ENTRY Reg. BX - X-coordinate (dev. coord.) * ; Reg. AX - Y-coordinate (dev. coord.) * ; * ; EXIT Reg. DI - Physical address * ; Reg. BL - Byte index * ; * ; Reg. Used. AX, BX, CX, DX, DI * ; * ;**************************************************************** concat: ; mov cx, yresmx ;normalize y-coordinate ; sub cx, ax ; mov ax, cx and bx, 03ffh ;mask off 10 lsb for x-coord. mov dh,al shr ax,1 shr ax,1 mov dl, bl ;save low order byte of x-coord and dl, 07h ;mask off data bit index. mov cl, 3 ;set count to 3 shr bx, cl ;shift out 3 lsb of x-coord. mov cl,bytes_line mul cl ;brute force calculation ;use shift and add if possible add ax, bx ;concatenate y and x coordinates in AX and dh,3 jz concat1 mov cl,dh xor ch,ch concat0: add ax,next_line ;if odd address, then start at next_line loop concat0 concat1:mov di, ax ;di = memory address xor dh, dh mov bx, dx ;bx = bit index into data byte ret EJECT ;**************************************************************** ;TRAN_FM * ; ENTRY * ; * ; * ; EXIT * ; * ; * ; Reg. Used. AX, BX, CX, DX, DI * ; * ;**************************************************************** TRAN_FM: push bp push es push ds les di,contrl_ptr mov ax, es: word ptr 14[di] mov bx, es: word ptr 16[di] ; get smfdb pointer mov dx, es: word ptr 18[di] mov bp, es: word ptr 20[di] ; get dmfdb pointer mov es, bx mov di, ax ; set es:di to it mov ax, es: word ptr 12[di] ; get num of planes in source ; xform n to n planes push ax ; save the plane count call calc_src_form call calc_des_form call calc_seg_off pop bx ; get the plane count back col_to_col_lp: push si push di push bx push cx col_to_col_loop: lodsw if not byte_swap xchg ah,al endif if rev_vid not ax endif stosw loop col_to_col_loop pop cx pop bx pop di pop si call tran_next_seg dec bx jnz col_to_col_lp pop ds pop es pop bp ret tran_next_seg: push cx mov ax, cx mov cl, 3 shr ax, cl ;get the segment increment mov bp, es add bp, ax mov es, bp mov bp, ds add bp, ax mov ds, bp pop cx mov ax, cx ;get the byte increment and ax, 0007h shl ax, 1 add si, ax add di, ax ret ; calc_seg_off: mov bp, cx ; find the next seg shr bp,1 shr bp,1 shr bp,1 mov dx, cx shl dx, 1 and dx, 000fh ; find the incremental offset ; mov bx,num_planes ret ; calc_des_form: mov ds, bp mov si, dx ; load dmfdb pointer not bx and bx,1 ; invert format mov 10[si],bx ; toggle dest form mov ax, es: word ptr 2[di] ; get source ptr seg mov di, es: word ptr [di] ; offset mov es, ax mov ax, 2[si] mov si, [si] ; get dest ptr seg,offset mov ds, ax xchg si,di ; swap pointers mov ax, es mov dx, ds mov es, dx mov ds, ax ret ; calc_src_form: mov bx, es: word ptr 10[di] ; get the format flag mov ax, es: word ptr 8[di] ; get the width in words mov cx, es: word ptr 6[di] ; get the height in pixels push dx mul cx pop dx mov cx, ax ; cx = word count and bx,bx ; if bx = 0 then dev spec form ret ;**************************************************************** ;EX_TIMV * ; ENTRY * ; CONTRL 7,8 = NEW VEC * ; EXIT * ; * ; CONTRL 9,10 = OLD VEC * ; INTOUT [0] = TIMER TICK COUNT IN MILLISECS * ; * ;**************************************************************** EX_TIMV: pushf cli push es push ds les di,contrl_ptr xor ax,ax mov ds,ax mov si,4 * 1ch ;setup the offset to timer int vector mov ax,[si] mov es:word ptr 18[di],ax ;save old timer vector mov ax,2[si] mov es:word ptr 20[di],ax mov ax, es:word ptr 14[di] mov [si],ax mov ax, es:word ptr 16[di] mov 2[si],ax pop ds pop es popf mov ax,1 mov CONTRL+8,ax ; flag that data is to be returned mov ax, 55 mov INTOUT, ax ; return the millisec/tick count ret EJECT include ibmmdvsp.a86 if mouse cseg include imouse.a86 endif cseg include monmmre1.a86 include monmmre2.a86 dseg include devdata.a86 crt_init_table_g db 35h,2dh,2eh,07h db 5bh,2h,57h,57h db 2,3,0,0 ; crt_init_table_a db 61h,50h,52h,0fh,19h,6h,19h,19h,2,0dh,0bh,0ch ; dispmode dw 1 ; if not rev_vid act_col_tbl dw 0, 0, 0 ;black dw 1000, 1000, 1000 ;white req_col_tbl dw 0, 0, 0 ;black dw 1000, 1000, 1000 ;white else act_col_tbl dw 1000, 1000, 1000 ;white dw 0, 0, 0 ;black req_col_tbl dw 1000, 1000, 1000 ;white dw 0, 0, 0 endif MAP_COL dw 0 dw 1 ;red dw 1 ;green dw 1 ;blue dw 1 ;cyan dw 1 ;yellow dw 1 ;magenta dw 1 ;white dw 1 dw 1 dw 1 dw 1 dw 1 dw 1 dw 1 dw 1