;; Graphics support routines for T3X under DOS. ;; Copyright (C) 1996,1997,2003 Nils M. Holm ;; See the file LICENSE for conditions of use. ;; Timer routines (tctimer 1.0) by Richard S. Sadowsky, ;; released to the public domain 1988-10-08. THIS LIBRARY IS BROKEN. DO NOT COMPILE! IT HAS TO BE CONVERETD TO LARGE MEMORY MODEL. .text 0 X: equ 6 Y: equ 8 X2: equ 10 Y2: equ 12 XLIM: equ 16000 YLIM: equ 16000 FX: equ 50 ;; 16000 * 2 / 640 FY: equ 67 ;; 16000 * 2 / 480 GCLEAR: equ 0 GSET: equ 1 GXOR: equ 2 gfx_oldmode: db 255 gfx_rowsize: dw 0 gfx_xmax: dw 0 gfx_ymax: dw 0 gfx_cmax: dw 0 gfx_vmem_off: dw 0 gfx_vmem_seg: dw 0 xinc: dw 0 yinc: dw 0 ainc: dw 0 binc: dw 0 delta: dw 0 lmask: db 0 rmask: db 0 lbord: dw 0 rbord: dw 0 bmask: dw 0 ;; gfxctl.init() ;; gfxctl_init: mov ax,$0F00 int $10 mov gfx_oldmode,al mov ax,$0011 int $10 mov ax,$0F00 int $10 cmp al,$11 jz init1 mov ax,-1 ret init1: mov gfx_rowsize,80 mov gfx_xmax,640 mov gfx_ymax,480 mov gfx_cmax,2 mov gfx_vmem_off,0 mov gfx_vmem_seg,$0A000 xor ax,ax ; mouse present? int $33 or ax,ax jnz init2 mov ax,-2 ret init2: mov ax,7 ; set mouse area xor cx,cx ; x mov dx,640 ; x size int $33 inc ax mov dx,480 ; y size int $33 mov ax,4 ; set mouse cursor position mov cx,320 ; center of screen mov dx,240 int $33 xor ax,ax ret ;; gfxctl.fini() ;; gfxctl_fini: mov al,gfx_oldmode cmp al,255 jz endend xor ah,ah int $10 endend: ret ;; internal: scale X,Y arguments ;; gscale2: mov bx,FX mov cx,FY mov ax,[bp+8] add ax,XLIM xor dx,dx div bx cmp ax,640 jb noclp1 dec ax noclp1: mov [bp+8],ax mov ax,[bp+6] add ax,YLIM xor dx,dx div cx cmp ax,480 jb noclp1a dec ax noclp1a: mov [bp+6],ax ret ;; internal: scale (X,Y),(DX,DY) arguments ;; gscale4: mov bx,FX mov cx,FY mov ax,[bp+12] add ax,XLIM xor dx,dx div bx cmp ax,640 jb noclp2 dec ax noclp2: mov [bp+12],ax mov ax,[bp+10] add ax,YLIM xor dx,dx div cx cmp ax,480 jb noclp2a dec ax noclp2a: mov [bp+10],ax mov ax,[bp+8] add ax,XLIM xor dx,dx div bx cmp ax,640 jb noclp3 dec ax noclp3: mov [bp+8],ax mov ax,[bp+6] add ax,YLIM xor dx,dx div cx cmp ax,480 jb noclp3a dec ax noclp3a: mov [bp+6],ax ret ;; gfxctl.point(x, y, m) ;; gfxctl_point: push bp mov bp,sp call gscale2 push es mov ax,gfx_vmem_seg mov es,ax mov dx,[bp+10] mov ax,[bp+8] mov bx,[bp+6] call gfxplot pop es pop bp ret ;; internal: place a pixel ;; gfxplot: push bx push dx mov cx,gfx_rowsize mul cx mov bx,ax mov cl,3 pop dx mov ax,dx shr dx,cl add bx,dx and al,7 mov ah,7 xchg al,ah sub al,ah mov cl,al mov al,1 shl al,cl pop cx or cx,cx ;; cmp cx,GCLEAR jz clrpx cmp cx,GXOR jz xorpx eseg or [bx],al ret xorpx: eseg xor [bx],al ret clrpx: xor al,255 eseg and [bx],al ret ;; gfxctl.line() subroutines ;; doswap: mov ax,[bp+8] mov bx,[bp+12] mov [bp+12],ax mov [bp+8],bx mov ax,[bp+6] mov bx,[bp+10] mov [bp+10],ax mov [bp+6],bx ret xline: mov ax,[bp+12] cmp ax,[bp+8] jle noswap1 call doswap noswap1: mov yinc,1 ;; yinc = y>y2 -> 1, -1; mov ax,[bp+10] cmp ax,[bp+6] jg noneg1 neg yinc noneg1: mov dx,[bp+8] ;; dx = x2-x1 sub dx,[bp+12] mov bx,[bp+6] ;; dy = abs(y2-y1) sub bx,[bp+10] jns nosign1 neg bx nosign1: mov ax,bx ;; delta = 2*dy - dx shl ax,1 sub ax,dx mov delta,ax mov ax,bx ;; ainc = 2 * (dy-dx) sub ax,dx shl ax,1 mov ainc,ax shl bx,1 ;; binc = 2*dy mov binc,bx mov si,[bp+12] mov di,[bp+10] mov ax,si ;; plot(x, y, c) mov dx,di mov bx,[bp+4] call gfxplot inc si mov cx,[bp+8] sub cx,si inc cx or cx,cx jz endxl line1: cmp delta,0 jl noinc1 add di,yinc mov dx,delta add dx,ainc mov delta,dx jmp incd1 noinc1: mov dx,delta add dx,binc mov delta,dx incd1: mov ax,si mov dx,di mov bx,[bp+4] push cx call gfxplot pop cx inc si loop line1 endxl: ret yline: mov ax,[bp+10] cmp ax,[bp+6] jle noswap2 call doswap noswap2: mov xinc,1 ;; xinc = x2>x2 -> 1, -1; mov ax,[bp+8] cmp ax,[bp+12] jg noneg2 neg xinc noneg2: mov dx,[bp+6] ;; dy = y2-y1 sub dx,[bp+10] mov bx,[bp+8] ;; dx = abs(x2-x1) sub bx,[bp+12] jns nosign2 neg bx nosign2: mov ax,bx ;; delta = 2*dx - dy shl ax,1 sub ax,dx mov delta,ax mov ax,bx ;; ainc = 2 * (dx-dy) sub ax,dx shl ax,1 mov ainc,ax shl bx,1 ;; binc = 2*dy mov binc,bx mov si,[bp+12] mov di,[bp+10] mov ax,si ;; plot(x, y, c) mov dx,di mov bx,[bp+4] call gfxplot inc di mov cx,[bp+6] sub cx,di inc cx or cx,cx jz endyl line2: cmp delta,0 jl noinc2 add si,xinc mov dx,delta add dx,ainc mov delta,dx jmp incd2 noinc2: mov dx,delta add dx,binc mov delta,dx incd2: mov ax,si mov dx,di mov bx,[bp+4] push cx call gfxplot pop cx inc di loop line2 endyl: ret ;; gfxctl.line(x, y, dx, dy, m) ;; gfxctl_line: push bp mov bp,sp call gscale4 push es push si push di mov ax,gfx_vmem_seg mov es,ax mov ax,[bp+8] sub ax,[bp+12] jns _p1 neg ax _p1: mov bx,[bp+6] sub bx,[bp+10] jns _p2 neg bx _p2: cmp ax,bx jge _doxline call yline jmp _done _doxline: call xline _done: pop di pop si pop es pop bp ret ;; gfxctl.box(x, y, dx, dy, c) ;; gfxctl_box: push bp mov bp,sp call gscale4 mov ax,[bp+10] cmp ax,[bp+6] jl x_lt_dx xchg ax,[bp+6] mov [bp+10],ax x_lt_dx: mov ax,[bp+12] cmp ax,[bp+8] jl y_lt_dy xchg ax,[bp+8] mov [bp+12],ax y_lt_dy: push es push si push di mov ax,gfx_vmem_seg mov es,ax mov cx,[bp+10] and cx,7 xor al,al or cx,cx jz endshr mov al,$80 cmp cx,1 jle endshr dec cx shrnxt: sar al,1 loop shrnxt endshr: xor al,255 mov lmask,al mov cx,[bp+6] and cx,7 xor al,al or cx,cx jz endshl mov al,$80 cmp cx,1 jle endshl dec cx shlnxt: sar al,1 loop shlnxt endshl: mov rmask,al mov ax,[bp+10] mov cl,3 shr ax,cl mov lbord,ax mov ax,[bp+6] shr ax,cl mov rbord,ax cmp ax,lbord jnz fillwide mov al,lmask xor al,rmask xor al,255 mov lmask,al mov cx,[bp+8] mov bx,[bp+12] sub cx,bx inc cx mov ax,gfx_rowsize mul bx mov bx,ax add bx,lbord mov al,lmask mov dx,gfx_rowsize cmp word [bp+4],0 jz nclear cmp word [bp+4],2 jz putnext2 putnext1: eseg or [bx],al add bx,dx loop putnext1 jmp endbox nclear: xor al,255 putnext0: eseg and [bx],al loop putnext0 jmp endbox putnext2: eseg xor [bx],al add bx,dx loop putnext2 jmp endbox fillwide: mov cx,[bp+8] mov bx,[bp+12] sub cx,bx inc cx mov ax,gfx_rowsize mul bx mov bx,ax add bx,lbord mov dx,cx mov cl,3 mov si,[bp+6] shr si,cl mov di,[bp+10] shr di,cl sub si,di dec si cld push ax mov ax,GCLEAR cmp word [bp+4],ax pop ax jz wclear push ax mov ax,GXOR cmp word [bp+4],ax pop ax jz nextrow2 nextrow1: mov di,bx mov al,lmask eseg or [di],al inc di or si,si jz skip1 mov cx,si mov al,255 rep stosb skip1: mov al,rmask eseg or [di],al add bx,gfx_rowsize dec dx jnz nextrow1 jmp endbox wclear: not byte lmask not byte rmask nextrow0: mov di,bx mov al,lmask eseg and [di],al inc di or si,si jz skip0 mov cx,si xor al,al rep stosb skip0: mov al,rmask eseg and [di],al add bx,gfx_rowsize dec dx jnz nextrow0 jmp endbox nextrow2: mov di,bx mov al,lmask eseg xor [di],al inc di or si,si jz skip2 mov cx,si wfill: eseg not byte [di] inc di loop wfill skip2: mov al,rmask eseg xor [di],al add bx,gfx_rowsize dec dx jnz nextrow2 endbox: pop di pop si pop es pop bp ret ;; gfxctl.clear(mode) ;; gfxctl_clear: push bp mov bp,sp push es push di mov ax,gfx_vmem_seg mov es,ax mov ax,gfx_rowsize mov cx,gfx_ymax mul cx mov cx,ax mov ax,[bp+10] or ax,ax jz clear0 mov al,$FF jmp clear clear0: xor al,al clear: cld xor di,di rep stosb pop di pop es pop bp ret ;; gfxctl.sync() ;; gfxctl_sync: ret ;; gfxctl.poll(eventp, block) ;; gfxctl_poll: push bp mov bp,sp mov ax,1 ; mouse cursor on int $33 ; Without the following delay loop, the mouse ; cursor starts flirring and motions become ; jerky. To be improved mov ax,[bp+4] ; block or ax,ax jnz nodelay mov ax,30 call delay nodelay: mov di,[bp+6] ; eventp mov word [di+4],0 ; buttons mov word [di+6],-1 ; key event_loop: mov ax,3 ; get mouse status int $33 push dx ; save y mov ax,FX ; compute x mul cx sub ax,XLIM mov word [di],ax pop ax ; compute y mov cx,FY mul cx sub ax,YLIM mov word [di+2],ax and bx,7 ; button mask mov word [di+4],bx mov ax,$0100 ; keyboard status int $16 jz nokey xor ax,ax ; read keyboard int $16 or al,al jnz gotkey mov al,ah mov ah,1 gotkey: mov word [di+6],ax nokey: mov ax,[di+4] cmp ax,bmask ; button change? jnz got_event cmp word [di+6],-1 ; got key? jnz got_event cmp word [bp+4],0 ; non-blocking? jz got_no_event jmp event_loop got_no_event: xor ax,ax jmps finish_event got_event: xor ax,ax dec ax finish_event: push ax mov ax,[di+4] mov bmask,ax mov ax,2 int $33 ; mouse cursor off pop ax pop bp ret ;; gfxctl.reshaped() ;; gfxctl_reshaped: xor ax,ax ret ;; gfxctl.wait(msec) ;; gfxctl_wait: push bp mov bp,sp mov ax,[bp+4] call delay pop bp ret ;; Timer routines by Richard S. Sadowsky, ;; longhi: equ $6C t0l: dw 0 t0h: dw 0 dtl: dw 0 dth: dw 0 initializetimer: mov al,$34 jmps Common ;common to return restoretimer: mov al,$36 ;/* outp(0x043,0x036); */ Common: mov dx,$43 outb jmps L1 L1: mov dx,$40 ;/* outp(0x040,0x000); */ xor ax,ax outb jmps L2 L2: outb ;/* outp(0x040,0x000); */ ret readtimer: cli ;/* Disable interrupts */ mov dx,$20 ;/* Address PIC ocw3 */ mov al,$A ;/* Ask to read irr */ outb mov al,0 ;/* Latch timer 0 */ mov dx,$43 outb mov dx,$20 inb ;/* Read irr */ mov di,ax ;/* Save it in DI */ mov dx,$40 inb ;/* Counter --> bx*/ mov dx,$20 mov bl,al ;/* LSB in BL */ mov dx,$40 inb mov dx,$20 mov bh,al ;/* MSB in BH */ not bx ;/* Need ascending counter */ mov dx,$21 inb ;/* Read PIC imr */ mov dx,$20 mov si,ax ;/* Save it in SI */ mov al,$FF ;/* Mask all interrupts */ mov dx,$21 outb mov dx,$20 mov ax,$40 ;/* read low word of time */ push es mov es,ax ;/* from BIOS data area */ eseg mov dx,longhi ;here's the timer long.hi pop es mov ax,si ;/* Restore imr from SI */ mov dx,$21 outb mov dx,$20 sti ;/* Enable interrupts */ mov ax,di ;/* Retrieve old irr */ test al,1 ;/* Counter hit 0? */ jz Done ;/* Jump if not */ cmp bx,$FF ;/* Counter > 0x0FF? */ ja Done ;/* Done if so */ inc dx ;/* Else count int req. */ Done: mov ax,bx ;/* set function result */ ret delay: mov cx,1193 mul cx mov dtl,ax mov dth,0 call initializetimer call readtimer mov t0l,ax mov t0h,dx goon: call readtimer sub ax,t0l sbb dx,t0h cmp ax,dtl jb goon cmp dx,dth jb goon call restoretimer ret