TITLE PC graphics module ; uses LINEPROC.MAC ; Michael Gordon - 8-Dec-86 ; ; Certain routines were taken from the Hercules BIOS of Dave Tutelman - 8/86 ; Others came from pcgraph.asm included in GNUPLOT by Colin Kelley ; ; modified slightly by Colin Kelley - 22-Dec-86 ; added header.mac, parameterized declarations ; added dgroup: in HVmodem to reach HCh_Parms and HGr_Parms - 30-Jan-87 ; ; modified and added to for use in plot(3) routines back end. ; Gil Webster. ; ; Assemble with masm ver. 4. include header.mac if1 include lineproc.mac endif GPg1_Base equ 0B800h ; Graphics page 1 base address extrn _inter:far _text segment public _PC_line, _PC_color, _PC_mask, _PC_curloc, _PC_puts, _Vmode public _erase, _save_stack, _ss_interrupt pcpixel proc near ror word ptr linemask,1 jc cont ret cont: push ax push bx push cx push dx push bp mov cx,ax ; x mov dx,bx ; y mov ah,0ch ; ah = write pixel mov al,byte ptr color mov bh, 0 ; page 0 int 10h pop bp pop dx pop cx pop bx pop ax ret pcpixel endp lineproc _PC_line, pcpixel ; ; erase - clear page 1 of the screen buffer to zero (effectively, blank ; the screen) ; beginproc _erase push es push ax push cx push di mov ax, GPg1_Base mov es, ax xor di, di mov cx, 4000h xor ax, ax cld rep stosw ; zero out screen page pop di pop cx pop ax pop es ret _erase endp beginproc _PC_color push bp mov bp,sp mov al,[bp+X] ; color mov byte ptr color,al pop bp ret _PC_color endp beginproc _PC_mask push bp mov bp,sp mov ax,[bp+X] ; mask mov word ptr linemask,ax pop bp ret _PC_mask endp beginproc _Vmode push bp mov bp,sp push si push di mov ax,[bp+X] int 10h pop di pop si pop bp ret _Vmode endp beginproc _PC_curloc push bp mov bp,sp mov dh, byte ptr [bp+X] ; row number mov dl, byte ptr [bp+X+2] ; col number mov bh, 0 mov ah, 2 int 10h pop bp ret _PC_curloc endp ; ; thanks to watale!broehl for finding a bug here--I wasn't pushing BP ; and reloading AH before INT 10H, which is necessary on genuine IBM ; boards... ; beginproc _PC_puts push bp mov bp,sp push si mov bl,byte ptr color mov si,[bp+X] ; offset ifdef LARGE_DATA mov es,[bp+X+2] ; segment if large or compact data model endif puts2: ifdef LARGE_DATA mov al,es:[si] else mov al,[si] endif or al,al jz puts3 mov ah,0eh ; write TTY char int 10h inc si jmp short puts2 puts3: pop si pop bp ret _PC_puts endp ; int kbhit(); ; for those without MSC 4.0 ; Use BIOS interrupt 16h to determine if a key is waiting in the buffer. ; Return nonzero if so. ; beginproc _kbhit mov ah, 1 ; function code 1 is keyboard test int 16h ; keyboard functions jnz kbfin ; Exit if char available xor ax, ax ; No char: return zero. kbfin: ret _kbhit endp ; _save_stack and _ss_interrupt are needed due to a bug in the MSC 4.0 ; code when run under MS-DOS 3.x. Starting with 3.0, MS-DOS automatically ; switches to an internal stack during system calls. This leaves SS:SP ; pointing at MS-DOS's stack when the ^C interrupt (INT 23H) is triggered. ; MSC should restore its own stack before calling the user signal() routine, ; but it doesn't. ; ; Presumably this code will be unnecessary in later releases of the compiler. ; ; _save_stack saves the current SS:SP to be loaded later by _ss_interrupt. ; beginproc _save_stack mov ax,ss mov cs:save_ss,ax mov ax,sp mov cs:save_sp,ax ret _save_stack endp ; _ss_interrupt is called on ^C (INT 23H). It restores SS:SP as saved in ; _save_stack and then jumps to the C routine interrupt(). ; beginproc _ss_interrupt cli ; no interrupts while the stack is changed! mov ax,-1 ; self-modifying code again save_ss equ this word - 2 mov ss,ax mov sp,-1 ; here too save_sp equ this word - 2 sti jmp far ptr _inter; now it's safe to call the real routine _ss_interrupt endp _text ends const segment linemask dw -1 color db 1 const ends end