home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
High Voltage Shareware
/
high1.zip
/
high1
/
DIR2
/
BYTE24.ZIP
/
WINSUBS.ASM
< prev
Wrap
Assembly Source File
|
1990-05-13
|
37KB
|
2,671 lines
; character windows
;
; Windowing subroutines for the byte benchmarks. These may be extended
; for use in a general purpose windowing library, but as they stand they
; are suited only for this task.
;
; This code is for the interface only, and has no effect on benchmark
; results.
;
; MASM, TASM compatible subroutines
;
; includes:
; _mk_window, _kill_window, _link_array, _new_cursor, _hide_window
; scroll, _chattr, _winputch, _win_set_curpos, _clearscreen
; _win_erase_region, _cgainit
;
; style of asm subroutines ( the stack frame struc) is adapted
; from Michael J. Young's _MS-DOS_Advanced_Programming_ c.1988 by Sybex
;
; equates for offsets in handle structure
made equ [di+0]
ptr_win_name equ [di+1]
handx1 equ [di+3]
handy1 equ [di+4]
ulx equ [di+5]
uly equ [di+6]
frame_flag equ [di+7]
immortal_flag equ [di+8]
hidden_flag equ [di+9]
ptr_behind_window equ [di+10]
w equ [di+12]
h equ [di+13]
image_w equ [di+14]
image_h equ [di+15]
hand_frame_attrib equ [di+16]
interior_attrib equ [di+17]
ptr_displayed_array equ [di+18]
dax equ [di+20]
day equ [di+22]
dax_off_log equ [di+24]
day_off_log equ [di+26]
dax_off_ul equ [di+28]
day_off_ul equ [di+30]
da_ulx equ [di+32]
da_uly equ [di+33]
da_im_w equ [di+34]
da_im_h equ [di+35]
num_valid equ [di+36]
ptr_valid_lines equ [di+37]
_data segment word public 'DATA'
extrn _machine_config: BYTE
graphics_type equ word ptr [_machine_config+15]
snowflag equ word ptr [_machine_config+25]
line_buffer dw 80 dup (?)
video_seg dw 0b000h
win_ul_x db 0
win_ul_y db 0
screen_image dw ?
win_width db 0
win_height db 0
win_clip_width db 0
win_clip_height db 0
frame_attrib db 0
int_attrib db 0
win_clip_x1 db 0
win_clip_x2 db 0
win_clip_y1 db 0
win_clip_y2 db 0
win_name_len db 0
ul_sym db 0
hori_sym db 0
l_nm_bnd_sym db 0
r_nm_bnd_sym db 0
ur_sym db 0
vert_sym db 0
ll_sym db 0
lr_sym db 0
_data ends
dgroup group _data
assume cs:_text, ds:dgroup
public _mk_window, _kill_window, _link_array, _new_cursor, _hide_window
public _scroll, _chattr, _winputch, _win_set_curpos, _clearscreen
public _win_erase_region, _winstrlen, _cgainit
public video_seg
_text segment byte public 'CODE'
; sleazy data for cga snow stuff
snow_write_type db ?
cga_timeout dw ?
localsnow dw ?
_mk_window proc near
; win_handle *mk_window(win_handle *handle,
; char * win_name,
; int x1, int y1,
; int x2, int y2,
; int frame_bg, int frame_fg,
; int int_bg, int int_fg,
; int frameflag, int immortalflag);
; returns window handle for later operations
;
stackframe struc
bptr dw ?
raddr dw ?
handle dw ?
win_name dw ?
x1 db ?
db ?
y1 db ?
db ?
x2 db ?
db ?
y2 db ?
db ?
fr_bg dw ?
fr_fg dw ?
int_bg dw ?
int_fg dw ?
frameflag dw ?
immortalflag dw ?
stackframe ends
frame equ [bp-bptr]
push bp ; Stack frame manipulations
mov bp,sp
sub sp,bptr
push es
push di
push si
push ds
pop es
mov ax, frame.handle
mov di, ax
xor ax, ax
or al, made
je NOTMADE
jmp ERREXIT
NOTMADE:
; zero calculated values, just in case
xor ax,ax
mov di, offset dgroup:win_ul_x
stosw
inc di
inc di
mov cx,11
rep stosb
; symbols if frame requested
or ax,frame.frameflag
jnz FRAME_REQ
mov cx,8
rep stosb
jmp short NO_FRAME_REQ
FRAME_REQ:
mov al, 0c9h
stosb
mov al, 0cdh
stosb
mov al, 0b5h
stosb
mov al, 0c6h
stosb
mov al, 0bbh
stosb
mov al, 0bah
stosb
mov al, 0c8h
stosb
mov al, 0bch
stosb
NO_FRAME_REQ:
; calculate window parameters
mov ah, frame.x2
mov al, frame.x1
mov bx, ax
cmp al, 79
jg BAD_WINDOW
cmp ah, 0
jl BAD_WINDOW
; window width
sub ah, al
cmp ah, 7
jle BAD_WINDOW
mov win_width, ah
; window x clips
mov ax,bx
cmp ah, 80
jl NOCLIP
sub ah, 80
mov win_clip_x2, ah
NOCLIP:
cmp al, 0
jge NOCLIP2
neg al
mov win_clip_x1, al
NOCLIP2:
; window ul_x
mov al, frame.x1
add al, win_clip_x1
mov win_ul_x, al
; visible width
mov ah, win_width
sub ah, win_clip_x1
sub ah, win_clip_x2
mov win_clip_width, ah
; window height
mov ah, frame.y2
mov al, frame.y1
mov bx, ax
cmp al, 25
jg BAD_WINDOW
cmp ah, 0
jl BAD_WINDOW
sub ah, al
cmp ah, 2
jle BAD_WINDOW
mov win_height, ah
jmp LBL0
BAD_WINDOW:
xor ax, ax
pop si
pop di
pop es
pop bp
ret
LBL0:
; window y clips
mov ax,bx
cmp ah, 25
jl NOCLIP3
sub ah, 25
mov win_clip_y2, ah
NOCLIP3:
cmp al, 0
jge NOCLIP4
neg al
mov win_clip_y1, al
NOCLIP4:
; window ul_x
mov al,frame.y1
add al, win_clip_y1
mov win_ul_y, al
; visible height
mov ah, win_height
sub ah, win_clip_y1
sub ah, win_clip_y2
mov win_clip_height, ah
; win_name length
mov cl, win_width
sub cl, 4
jle NONAME
xor ch, ch
mov dx, cx
mov di, frame.win_name
or di, di
je NONAME
xor al, al
dec di
L0:
inc di
cmp al, [di]
loopne L0
inc cx
sub dx, cx
mov win_name_len, dl
NONAME:
; get attributes together
mov ax, frame.fr_bg
mov ah, al
xor al, al
or ax, frame.fr_fg
mov bx, frame.int_bg
mov bh, bl
xor bl, bl
or bx, frame.int_fg
; truncate... for backgrounds, shave off blink bits, too
and ah, 07h
and bh, 07h
and bl, 0fh
and al, 0fh
; if monochrome, convert all but white backgrounds to no backgrounds
push ax
push bx
mov ah, 0fh
int 10h
cmp al, 07h
pop bx
pop ax
je MDAMODE
cmp graphics_type, 4
jl COLOR
MDAMODE:
cmp ah, 07h
jz SET_BG
xor ah, ah
; if you clear the background, make sure foreground is not black
or al, 02h
jmp short CLR_BG
; if you set it, make foreground black
SET_BG:
xor al,al
CLR_BG:
cmp bh, 07h
jz SET_BG2
xor bh,bh
or bl, 02h
jmp short CLR_BG2
SET_BG2:
xor bl,bl
CLR_BG2:
; and all foregrounds but white foregrounds to low intensity
cmp al, 0fh
jz SET_FRCLR
and al, 07h
SET_FRCLR:
cmp bl, 0fh
jz SET_FRCLR2
and bl, 07h
SET_FRCLR2:
; zap underline bits
and al, 0eh
and bl, 0eh
COLOR:
mov cl, 4
shl ah, cl
or al, ah
shl bh, cl
or bl, bh
mov frame_attrib, al
mov int_attrib, bl
; if not immortal, get some memory for screen image
mov ax, frame.immortalflag
or ax, 0
jne IMMORTAL
mov bl, win_clip_height
mov al, win_clip_width
mul bl
mov bx, ax
dec cl
shr bx, cl
inc bx ; paranoia
mov ah, 48h
int 21h
jnc GOT_MEMORY
; lose with memory
xor ax, ax
pop si
pop di
pop es
pop bp
ret
IMMORTAL:
xor ax, ax
GOT_MEMORY:
mov screen_image, ax
; calculate addresses
mov cl, win_clip_height
xor ch, ch
mov bh, win_ul_x
mov bl, win_ul_y
mov dl, win_clip_width
; if not immortal, make copy
or ax, 0
je IMMORTAL2
mov es, ax
call stow_screen_image
push ds
pop es
IMMORTAL2:
; if top is clipped, don't bother with titlebar
or win_clip_y1, 0
jnz NOTB
; create titlebar
push cx
mov al, ul_sym
mov ah, frame_attrib
mov di, offset dgroup:line_buffer
stosw
; now for the interior
push ds
pop es
mov cl, win_clip_width
mov al, win_name_len
or al, al
jnz HASNAME
sub cl, 2
mov al, hori_sym
rep stosw
jmp short NONAME2
HASNAME:
sub cl, 4
sub cl, al
sar cl, 1
push cx
jnc NO_ROUNDOFF
inc cl
NO_ROUNDOFF:
mov al, hori_sym
rep stosw
mov al, l_nm_bnd_sym
stosw
mov cl, win_name_len
mov dx, frame.win_name
mov si, dx
L3:
mov al, [si]
mov [di], ax
inc si
inc di
inc di
loop L3
mov al, r_nm_bnd_sym
stosw
pop cx
mov al, hori_sym
rep stosw
; and the right frame
NONAME2:
mov al, ur_sym
mov [di], ax
; screen it
mov al, win_clip_x1
shl al, 1
xor ah, ah
add ax, offset dgroup:line_buffer
mov si, ax
mov cl, win_clip_width
xor ch, ch
mov ax, video_seg
call sho_word_buff
; fix counters
pop cx
dec cx
jcxz EXIT_JUMPOFF
inc bl
jmp short CONT0
EXIT_JUMPOFF:
jmp EXIT
CONT0:
NOTB:
; create generic middle line
push cx
mov al, vert_sym
mov ah, frame_attrib
mov di, offset dgroup:line_buffer
stosw
; now for the interior
xor al,al
mov ah, int_attrib
push ds
pop es
mov cl, win_clip_width
sub cl, 2
rep stosw
; and the right frame
mov al, vert_sym
mov ah, frame_attrib
mov word ptr [di], ax
pop cx
; if bottom is not clipped, reserve last line
or win_clip_y2, 0
jnz NOLASTLINE
dec cl
NOLASTLINE:
; screen it
mov al, win_clip_x1
shl al, 1
xor ah, ah
add ax, offset dgroup:line_buffer
mov dx, ax
mov ax, video_seg
L1:
push cx
mov si, dx
mov cl, win_clip_width
call sho_word_buff
inc bl
pop cx
loop L1
; if bottom is not clipped, continue
or win_clip_y2, 0
jnz EXIT
; create bottom line
mov al, ll_sym
mov ah, frame_attrib
mov di, offset dgroup:line_buffer
stosw
; now for the interior
mov al, hori_sym
push ds
pop es
mov cl, win_clip_width
sub cl, 2
rep stosw
; and the right frame
mov al, lr_sym
stosw
; screen it
mov al, win_clip_x1
shl al, 1
xor ah, ah
add ax, offset dgroup:line_buffer
mov si, ax
mov cl, win_clip_width
xor ch, ch
mov ax, video_seg
call sho_word_buff
EXIT:
; give handle information
push ds
pop es
mov ax, frame.handle
mov di, ax
mov al, 1
stosb
mov ax, frame.win_name
stosw
mov al, frame.x1
stosb
mov al, frame.y1
stosb
mov al, win_ul_x
stosb
mov al, win_ul_y
stosb
mov ax, frame.frameflag
stosb
mov ax, frame.immortalflag
stosb
xor al, al ; clear hidden flag
stosb
mov si, offset dgroup:screen_image
movsw
mov cx, 6
rep movsb
xor ax, ax ; clear array
stosw
; outta here
ERREXIT:
pop si
pop di
pop es
pop bp
ret
_mk_window ENDP
; ------------------------------------------
stow_screen_image proc near
; on entry, registers should be
; bh - x coordinate
; bl - y coordinate
; cl - height of image
; dl - length of image
; es - destination segment
push ax
push bx
push cx
push ds
push di
push si
; get segment stuff straight
xor ax, ax
mov di, ax
mov ax, video_seg
mov ds, ax
; calculate initial offset
mov al, 160
mul bl
mov bl,bh
xor bh, bh
shl bl,1
add ax, bx
SSIL0:
mov si, ax
push cx
mov cl, dl
rep movsw
pop cx
add ax, 160
loop SSIL0
pop si
pop di
pop ds
pop cx
pop bx
pop ax
ret
stow_screen_image ENDP
; ---------------------------------------------
sho_word_buff proc near
; on entry, registers should be
; ax - video segment
; bh - x coordinate
; bl - y coordinate
; cx - length of string
; ds - source string segment
; si - source offset
push ax
push bx
push es
push di
mov es, ax
mov al, 160
mul bl
mov bl,bh
xor bh, bh
shl bl,1
add ax, bx
mov di, ax
; kludge for snow
cmp cs:localsnow, 0
je SWNOSNOW
mov cs:snow_write_type, 2
call snowwrite
jmp short SWBEXIT
SWNOSNOW:
rep movsw
SWBEXIT:
pop di
pop es
pop bx
pop ax
ret
sho_word_buff ENDP
; ---------------------------------------------
_kill_window proc near
; void kill_window( win_handle *)
killframe struc
kbptr dw ?
kraddr dw ?
khandle dw ?
killframe ends
kframe equ [bp - kbptr]
push bp ; Stack frame manipulations
mov bp,sp
sub sp,kbptr
push di
push si
push ds
push es
mov ax, kframe.khandle
mov di, ax
; unlinked, immortal or hidden?
xor al, al
cmp al, made
je KANTKILL
or al, immortal_flag
jne KANTKILL
; committed to removing window -- set made flag
mov made, al
; determine if hidden
or al, hidden_flag
je KNOTHIDDEN
mov ax, ptr_behind_window
mov es, ax
jmp short KHIDDEN
KNOTHIDDEN:
mov ax, video_seg
push ax
mov ah, ulx ; ulx
mov al, uly ; uly
mov cl, image_h ; image_h
mov bl, image_w ; image_w
mov dx, ptr_behind_window ; allocated_segment
mov ds, dx
mov dl, bl
xor ch, ch
mov bx, ax
xor ax, ax
mov si, ax
pop ax
KB0:
push cx
mov cl, dl
call sho_word_buff
inc bl
pop cx
loop KB0
; try to put memory back
push ds
pop es
KHIDDEN:
mov ah, 49h
int 21h
KANTKILL:
pop es
pop ds
pop si
pop di
pop bp
ret
_kill_window ENDP
; ---------------------------------------------
_link_array proc near
; void link_array( win_handle *,
; char * ary_ptr,
; int aryx,
; int aryy,
; int aryoffx,
; int aryoffy
; )
linkframe struc
lbptr dw ?
lraddr dw ?
lhandle dw ?
ary_ptr dw ?
aryx dw ?
aryy dw ?
aryoffx dw ?
aryoffy dw ?
linkframe ends
lframe equ [bp - lbptr]
push bp ; Stack frame manipulations
mov bp,sp
sub sp,lbptr
push di
push si
push ds
; made?
mov ax, lframe.lhandle
mov di, ax
xor ax, ax
cmp al, made
jne LMADE
jmp BAD_LINK
LMADE:
; calculate x, y point for array display
mov bh, handx1
mov bl, handy1
mov ah, w ; w
mov al, h ; h
mov cl, image_h
mov dl, image_w
xor ch, ch
xor dh, dh
; correct image widths and heights
push bx
cmp bh, 0
jl LCLIP0
dec dl
LCLIP0:
add bh, ah
cmp bh, 80
jge LCLIP1
dec dl
LCLIP1:
cmp bl, 0
jl LCLIP2
dec cl
LCLIP2:
add bl, al
cmp bl, 80
jge LCLIP3
dec cl
LCLIP3:
pop bx
; dump off some handle stuff
mov ax, lframe.lhandle
mov di, ax
mov da_im_h, cl ; da_im_h
mov da_im_w, dl ; da_im_w
xor ax, ax
; calculate addresses for bx and offsets for si
inc bh
inc bl
cmp bh, 0
jge LNOCLIP0
neg bh
mov ah, bh
xor bh, bh
LNOCLIP0:
cmp bl, 0
jge LNOCLIP1
neg bl
mov al, bl
xor bl, bl
LNOCLIP1:
; total offsets
push bx
push ax
xor ah,ah
add ax, lframe.aryoffy
mov bx, lframe.aryy ; total y dimension
sub bx, ax
jg LOK0
pop ax
pop bx
jmp BAD_LINK
LOK0:
cmp cx, bx
jl LCXSMALLER
mov cx, bx
LCXSMALLER:
mov bx, lframe.lhandle
mov di, bx
mov day_off_ul, ax ; day_off_ul
mov bx, lframe.aryx ; total x dimension
push dx
mul bx
pop dx
mov si, ax ; row offset acounted for
; borrow si for a spell
pop ax
mov al, ah
xor ah,ah
add ax, lframe.aryoffx ; x offset
mov bx, lframe.aryx ; total x dimension
sub bx, ax
jg LOK1
pop bx
jmp BAD_LINK
LOK1:
cmp dx, bx
jl LDXSMALLER
mov dx, bx
LDXSMALLER:
mov bx, lframe.lhandle
mov di, bx
mov dax_off_ul, ax ; dax_off_ul
mov bx,si
add ax, bx
add ax, lframe.ary_ptr
mov si, ax ; column offset acounted for
pop bx
; give params to handle
mov ax, lframe.lhandle
mov di, ax
mov da_ulx, bh ; da_ulx
mov da_uly, bl ; da_uly
; now, si is okay, dl is width counter, cl is height counter
mov dh, interior_attrib ; interior_attrib
mov ax, si
LLB0:
push cx
mov cl, dl
push ax
mov ax, video_seg
call showbuffer
pop ax
add ax, lframe.aryx
mov si, ax
inc bl
pop cx
loop LLB0
; scroll bar?
push ds
pop es
mov ax, lframe.lhandle
mov di, ax
mov al, h
mov bx, lframe.aryy
dec al
dec al
xor bh, bh
cmp al, bl
jge NOSCROLLBAR
mov ax, video_seg
mov bh, handx1
add bh, w
dec bh
dec bh
mov bl, handy1
inc bl
mov cx, lframe.aryy
mov ch, cl
mov cl, h
mov dx, lframe.aryoffy
call scrollbar
NOSCROLLBAR:
; fix handle stuff
mov ax, lframe.lhandle
push ax
add ax, 18
mov di, ax
mov ax, lframe.ary_ptr
stosw
mov ax, lframe.aryx
stosw
mov ax, lframe.aryy
stosw
mov ax, lframe.aryoffx
stosw
mov ax, lframe.aryoffy
stosw
pop ax
jmp short LEXIT
BAD_LINK:
xor ax, ax
LEXIT:
pop ds
pop si
pop di
pop bp
ret
_link_array ENDP
; ---------------------------------------------
showbuffer proc near
; on entry, registers should be
; ax - video segment
; bh - x coordinate
; bl - y coordinate
; cx - length of string
; ds - source string segment
; si - source offset
; dh - attribute
push es
push di
push ds
pop es
push ax
push cx
mov ax, offset dgroup:line_buffer
mov di, ax
mov ah, dh
push di
SBL0:
lodsb
stosw
loop SBL0
pop si
pop cx
pop ax
call sho_word_buff
pop di
pop es
ret
showbuffer ENDP
; ---------------------------------------------
scrollbar proc near
; on entry, registers should be
; ax - video segment
; bh - x coordinate
; bl - y coordinate
; cl - window height
; ch - array length
; dx - height offset into array
push es
push di
mov es, ax
cmp bh, 79
jg SBAREXIT
cmp bl, 25
jg SBAREXIT
dec cl
dec cl
sub ch, cl
jle SBAREXIT
mov ax, 25
sub al, bl
push ax ; screen limitation
mov ax, cx
xor ah, ah
push ax ; window height
mul dl ;
mov cl, ch
xor ch, ch ; number of lines available
div cl ; number of 'empty blocks'
xor ah, ah
mov cx, ax
pop ax
sub ax, cx ; number of 'full blocks'
push ax
mov dx, 160
mov al, bl
mov bl, bh
xor ah, ah
xor bh, bh
mul dl
shl bx, 1
add ax, bx
mov di, ax ; offset into video seg
pop bx ; number of full blocks
pop dx ; screen limitation
cmp cx, dx
jle SBCXISMALL
mov cx, dx
SBCXISMALL:
push dx
mov dx, di
push cx ; do empty blocks cx times
mov ax, 02b0h
jcxz SCRDONEL0
SCRBL0:
stosw
add dx, 160
mov di, dx
loop SCRBL0
SCRDONEL0:
pop cx
pop dx
sub dx, cx
jle SBAREXIT
mov cx, bx
cmp cx, dx
jle SBCXISMALL2
mov cx, dx
SBCXISMALL2:
; do full blocks cx times
mov dx, di
mov ax, 0cb2h
jcxz SBAREXIT
SCRBL1:
stosw
add dx, 160
mov di, dx
loop SCRBL1
SBAREXIT:
pop di
pop es
ret
scrollbar ENDP
;---------------------------------------------
_new_cursor proc near
; int new_cursor ( int value)
ncurseframe struc
ncbptr dw ?
ncraddr dw ?
ncvalue dw ?
ncurseframe ends
ncframe equ [bp - ncbptr]
push bp ; Stack frame manipulations
mov bp,sp
sub sp,ncbptr
push di
push si
mov ah, 0fh
int 10h ; status
mov ah, 03h
int 10h ; get type
push cx
mov cx, ncframe.ncvalue
mov ah, 01h
int 10h
pop ax
pop si
pop di
pop bp
ret
_new_cursor ENDP
; ---------------------------------------------
_hide_window proc near
; void hide_window( win_handle *)
hideframe struc
hbptr dw ?
hraddr dw ?
hhandle dw ?
hideframe ends
hframe equ [bp - hbptr]
push bp ; Stack frame manipulations
mov bp,sp
sub sp,hbptr
push di
push si
push ds
; grab some temorary memory
mov ax, hframe.hhandle
mov di, ax
; made?
xor al, al
cmp al, made
je CANTHIDE
; immortal?
mov al, immortal_flag
or al, 0
jne CANTHIDE
mov bl, image_h ; image_h
mov al, image_w ; image_w
mul bl
mov bx, ax
push bx ; length of screen image in words
mov cl, 3
shr bx, cl
inc bx ; paranoia
mov ah, 48h
int 21h
jc HIDELOSER
jmp short GOT_TEMP_BUFFER
HIDELOSER:
; debug
mov ax, 5900h
xor bx, bx
int 21h
pop bx
; lose with memory, or it's immortal
CANTHIDE:
pop ds
pop si
pop di
pop bp
ret
GOT_TEMP_BUFFER:
; store screen in temp buffer
push ax ; save address of temporary buffer
mov es, ax
mov ax, hframe.hhandle
mov di, ax
mov bh, ulx ; ulx
mov bl, uly ; uly
mov cl, image_h ; image_h
mov dl, image_w ; image_w
xor ch, ch
call stow_screen_image
; dump old buffer on screen
mov ax, video_seg
push ax
mov ax, ptr_behind_window ; segment of old screen
mov ds, ax
xor ax, ax
mov si, ax
pop ax
H0:
push cx
mov cl, dl
call sho_word_buff
inc bl
pop cx
loop H0
; now put temp buffer into old location
push ds ; old screen
pop es ; old screen
pop ds ; temp buffer
pop cx ; length of screen image, in words
xor ax, ax
mov di, ax
mov si, ax
rep movsw
; put temp memory back
push ds
pop es ; temp_buffer
mov ah, 49h
int 21h
pop ds
; toggle hidden flag
mov ax, hframe.hhandle
mov di, ax
not byte ptr hidden_flag
; go home
pop si
pop di
pop bp
ret
_hide_window ENDP
; ---------------------------------------------
_scroll proc near
; int scroll( win_handle *, int upflag)
; returns non-zero if successful, zero on failure
scrollframe struc
sbptr dw ?
sraddr dw ?
shandle dw ?
upflag dw ?
scrollframe ends
sframe equ [bp - sbptr]
push bp ; Stack frame manipulations
mov bp,sp
sub sp,sbptr
push di
push si
push es
; check if window is made and linked
mov ax, sframe.shandle
mov di, ax
xor ax, ax
cmp al, made
jnz C0
cmp ax, ptr_displayed_array
jnz C0
jmp SCROLL_FAILED
C0:
cmp ax, sframe.upflag
jz SCROLL_DOWN
; check if array is at scroll limit
cmp ax, day_off_ul ; day_off_log
jnz C1
jmp SCROLL_FAILED
C1:
mov bx, da_ulx ; bh=da_uly, bl=da_ulx
xchg bh, bl
mov ax, da_im_w ; ah=da_im_h, al=da_im_w
xchg ah, al
add ax, bx
dec al ; now ah=lrx, al=lry
mov dx, bx
inc dl
call charblit
push ds
pop es
sub ah, bh
dec ah ; now ah=length
; call showbuffer with pointer to row above
mov cx, dax
or ch, 0
jnz CAHSMALLER
cmp ah, cl
jl CAHSMALLER
jmp short CCLSMALLER
CAHSMALLER:
mov cl, ah
xor ch, ch
CCLSMALLER:
push bx
mov ax,day_off_ul ; day_off_ul
dec ax
mov bx, dax ; dax
mul bx
add ax, dax_off_ul ; dax_off_ul
add ax, ptr_displayed_array ; array pointer
mov si, ax
mov ax, video_seg
mov dh, interior_attrib ; interior attrib
pop bx
call showbuffer
; update offsets
dec word ptr day_off_log
dec word ptr day_off_ul
jmp short SBUPDATE
SCROLL_DOWN:
mov ax, day ; day
sub ax, day_off_log ; day_off_log
or ah, 0 ; if difference is greater than 128, forget it
jne SCROLL_FAILED
inc al
inc al ; trick for height - frame
cmp al, h ; logical height
jle SCROLL_FAILED
mov bx, da_ulx ; bh=da_uly, bl=da_ulx
xchg bh, bl
mov ax, da_im_w ; ah=da_im_h, al=da_im_w
xchg ah, al
add ax, bx
mov dx, bx
inc bl
call charblit
push ds
pop es
sub ah, bh
dec ah ; now ah=length
mov bl, al ; now bl = destination
dec bl
push bx
; call showbuffer with pointer to row below
mov cx, dax ; dax
or ch, 0
jnz CAHSMALLER2
cmp ah, cl
jl CAHSMALLER2
jmp short CCLSMALLER2
CAHSMALLER2:
mov cl, ah
xor ch, ch
CCLSMALLER2:
xor ah, ah
mov al, da_im_h
add ax, day_off_ul ; day_off_ul
mov bx, dax ; dax
mul bx
add ax, dax_off_ul ; dax_off_ul
add ax, ptr_displayed_array ; array pointer
mov si, ax
mov ax, video_seg
mov dh, interior_attrib ; interior attrib
pop bx
call showbuffer
; update offsets
inc word ptr day_off_log
inc word ptr day_off_ul
jmp short SBUPDATE
SCROLL_FAILED:
xor ax, ax
jmp short SEXIT
SBUPDATE:
push ds
pop es
mov ax, sframe.shandle
mov di, ax
mov ax, video_seg
mov bh, handx1
add bh, w
dec bh
dec bh
mov bl, handy1
inc bl
mov cx, day
mov ch, cl
mov cl, h
mov dx, day_off_log
call scrollbar
SEXIT:
pop es
pop si
pop di
pop bp
ret
_scroll ENDP
; ---------------------------------------------
charblit proc near
; on entry, registers should be
; bh - source x ul
; bl - source y ul
; ah - source x lr
; al - source y lr
; dh - dest x ul
; dl - dest y ul
push ds
push ax
push bx
push cx
push dx
push di
; check for y-overlap
xor ch, ch
cmp bl, dl
jg NOVERLAP
inc ch
NOVERLAP:
push dx
push bx
sub bl, al
jg CNN1
neg bl
CNN1:
mov cl, bl ; height
xor dh, dh
sub bh, ah
jg CNN2
neg bh
CNN2:
mov dl, bh ; length
; get source offset, move into si
pop bx
mov al, bl
or ch, 0
jz NOVERLAP1
add al, cl
dec al
NOVERLAP1:
mov bl, 160
mul bl
mov bl, bh
xor bh, bh
shl bx,1
add ax, bx
mov si, ax
; get destination offset, move into di
pop bx
mov al, bl
or ch, 0
jz NOVERLAP2
add al, cl
dec al
NOVERLAP2:
mov bl, 160
mul bl
mov bl, bh
xor bh, bh
shl bx,1
add ax, bx
mov di, ax
; determine positive or negative updating
mov bx, 160
or ch, 0
jz NOVERLAP3
neg bx
NOVERLAP3:
xor ch, ch
mov ax, video_seg
mov es, ax
cmp cs:localsnow, 0
je CBNOSNOW
mov cs:snow_write_type, 2
mov ds, ax
CBSNOW0:
push si
push di
push cx
mov cl, dl
call snowwrite
pop cx
pop ax
add ax, bx
mov di, ax
pop ax
add ax, bx
mov si, ax
loop CBSNOW0
jmp short CBEXIT
CBNOSNOW:
mov ds, ax
CB0:
push si
push di
push cx
mov cl, dl
rep movsw
pop cx
pop ax
add ax, bx
mov di, ax
pop ax
add ax, bx
mov si, ax
loop CB0
CBEXIT:
pop di
pop dx
pop cx
pop bx
pop ax
pop ds
ret
charblit ENDP
; ---------------------------------------------
_chattr proc near
; int chattr( win_handle *, int chxoff, int chyoff,
; int chw, int chh, int ch_bg_attr, ch_fg_attr)
;
; if both attribute ints are zeroes, resets default color
;
; returns non-zero if successful, zero on failure
chattrframe struc
chbptr dw ?
chraddr dw ?
chhandle dw ?
chxoff db ?
db ?
chyoff db ?
db ?
chw db ?
db ?
chh db ?
db ?
ch_bg_attr db ?
db ?
ch_fg_attr db ?
db ?
chattrframe ends
chframe equ [bp - chbptr]
push bp ; Stack frame manipulations
mov bp,sp
sub sp,chbptr
push di
push si
push es
mov ax, chframe.chhandle
mov di, ax
xor ax, ax
cmp al, made
je BAD_CHATTR
; determine screen location to be chattred
mov bh, handx1 ; handx1
inc bh
mov bl, handy1 ; handy1
inc bl
add bl, chframe.chyoff
jc BAD_CHATTR
jl BAD_CHATTR
add bh, chframe.chxoff
jc BAD_CHATTR
jl BAD_CHATTR
mov cl, chframe.chh
mov dl, chframe.chw
or cl, 0
je BAD_CHATTR
or dl, 0
je BAD_CHATTR
xor dh, dh
xor ch, ch
; check limits
mov ax, bx
add bl, cl
jc BAD_CHATTR
cmp bl, 25
jg BAD_CHATTR
add bh, dl
jc BAD_CHATTR
cmp bl, 80
jg BAD_CHATTR
mov bx, ax
jmp short GOOD_CHATTR
BAD_CHATTR:
xor ax, ax
pop es
pop si
pop di
pop bp
ret
GOOD_CHATTR:
; get attributes together
mov ah, chframe.ch_bg_attr
mov al, chframe.ch_fg_attr
or ax, 0
jnz NOT_RESET
mov al, interior_attrib
jmp short CHRESETREADY
NOT_RESET:
; truncate... for background, shave off blink bits, too
and ax, 070fh
; if monochrome, convert all but white backgrounds to no backgrounds
cmp graphics_type, 4
jl CHCOLOR
cmp ah, 07h
jz CHSET_BG
xor ah, ah
; if you clear the background, make sure foreground is not black
or al, 02h
jmp short CHCLR_BG
; if you set it, make foreground black
CHSET_BG:
xor al,al
CHCLR_BG:
; and all foregrounds but white foregrounds to low intensity
cmp al, 0fh
jz CHSET_FRCLR
and al, 07h
CHSET_FRCLR:
; zap underline bits
and al, 0eh
CHCOLOR:
push cx
mov cl, 4
shl ah, cl
or al, ah
pop cx
CHRESETREADY:
push ax
mov al, 160
mul bl
mov bl,bh
xor bh, bh
shl bl,1
add ax, bx
mov di, ax
mov bx, ax
mov ax, video_seg
mov es, ax
pop ax
CHL0:
push cx
mov cl, dl
; since chattr is almost always one line, put snow check in here.
cmp cs:localsnow, 0
je CHL1
mov cs:snow_write_type, 0
CHLSNOW1:
inc di
call snowwrite
loop CHLSNOW1
jmp short CHLCONTINUE
CHL1:
inc di
stosb
loop CHL1
CHLCONTINUE:
pop cx
add bx, 160
mov di, bx
loop CHL0
pop es
pop si
pop di
pop bp
ret
_chattr ENDP
; ---------------------------------------------
_winputch proc near
; int winputch(win_handle *, int wpxoff, int wpyoff, char wpch)
;
; returns non-zero if successful, zero on failure
winputchframe struc
wpbptr dw ?
wpraddr dw ?
wphandle dw ?
wpxoff db ?
db ?
wpyoff db ?
db ?
wpch db ?
db ?
winputchframe ends
wpframe equ [bp - wpbptr]
push bp ; Stack frame manipulations
mov bp,sp
sub sp,wpbptr
push di
push si
push es
mov ax, wpframe.wphandle
mov di, ax
; check if window valid
xor ax, ax
cmp al, made
jne NOT_BAD_WP
jmp BAD_WP
NOT_BAD_WP:
; check array width if linked
xor ax, ax
cmp ax, ptr_displayed_array ; array pointer
jz WPNOTLINKED
mov bl, wpframe.wpxoff
add bx, dax_off_log ; dax_off_log
mov dx, dax ; dax
cmp bx, dx
jl WPNOTLINKED
jmp BAD_WP
WPNOTLINKED:
mov bh, handx1 ; handx1
inc bh
mov bl, handy1 ; handy1
inc bl
mov ax, bx
add bl, wpframe.wpyoff
jc BAD_WP
jl BAD_WP
add bh, wpframe.wpxoff
jc BAD_WP
jl BAD_WP
add al, h ; h
add ah, w ; w
dec al
dec al
dec ah
dec ah
cmp bh, ah
jge BAD_WP
cmp bl, al
jge BAD_WP
; write to screen
push di
mov al, 160
mul bl
mov bl,bh
xor bh, bh
shl bl,1
add ax, bx
mov di, ax
mov ax, video_seg
mov es, ax
mov al, wpframe.wpch
cmp cs:localsnow, 0
je WPNOSNOW
mov cs:snow_write_type, 0
call snowwrite
jmp short WPDONESCREEN
WPNOSNOW:
stosb
WPDONESCREEN:
; write to array, if linked
push ds
pop es
pop di
xor bx, bx
cmp bx, ptr_displayed_array ; array pointer
jz WPEXIT
xor ah, ah
mov al, wpframe.wpyoff
mov bl, wpframe.wpxoff
add ax, day_off_log ; day_off_log
add bx, dax_off_log ; dax_off_log
mov cx, dx ; dax
mul cx
add ax, bx
add ax, ptr_displayed_array ; array_pointer
mov di, ax
mov al, wpframe.wpch
stosb
jmp short WPEXIT
BAD_WP:
xor ax, ax
WPEXIT:
pop es
pop si
pop di
pop bp
ret
_winputch ENDP
; ---------------------------------------------
_win_set_curpos proc near
; void win_set_curpos ( win_handle *, int scxoff, int scyoff)
scurseframe struc
scbptr dw ?
scraddr dw ?
schandle dw ?
scxoff db ?
db ?
scyoff db ?
db ?
scurseframe ends
scframe equ [bp - scbptr]
push bp ; Stack frame manipulations
mov bp,sp
sub sp,scbptr
push di
push si
mov ax, scframe.schandle
mov di, ax
; check if made
xor ax, ax
cmp al, made
je BAD_SC
mov bh, handx1 ; handx1
inc bh
mov bl, handy1 ; handy1
inc bl
mov ax, bx
add bl, scframe.scyoff
jc BAD_SC
jl BAD_SC
add bh, scframe.scxoff
jc BAD_SC
jl BAD_SC
add al, h ; h
add ah, w ; w
dec al
dec ah
cmp bh, ah
jg BAD_SC
cmp bl, al
jg BAD_SC
; write to screen
mov dx, bx
xchg dh, dl
mov ah, 0fh
int 10h ; status
mov ah, 02h
int 10h ; move it
jmp short SCEXIT
BAD_SC:
xor ax, ax
SCEXIT:
pop si
pop di
pop bp
ret
_win_set_curpos ENDP
; ---------------------------------------------
_clearscreen proc near
; void clearscreen ( void )
clsframe struc
clsbptr dw ?
clsraddr dw ?
clsframe ends
push bp ; Stack frame manipulations
mov bp,sp
sub sp,clsbptr
mov ah, 0fh
int 10h ; status
push bx ; save display page (bh)
xor ah, ah
int 10h ; reset current mode
pop bx
xor dx, dx ; set cursor position to 0,0
mov ah, 02h
int 10h
pop bp
ret
_clearscreen ENDP
; ---------------------------------------------
_win_erase_region proc near
; void win_erase_region ( win_handle *, int erxoff, int eryoff
; erw, erh )
eraseframe struc
erbptr dw ?
erraddr dw ?
erhandle dw ?
erxoff db ?
db ?
eryoff db ?
db ?
erw db ?
db ?
erh db ?
db ?
eraseframe ends
erframe equ [bp - erbptr]
push bp ; Stack frame manipulations
mov bp,sp
sub sp,erbptr
push di
push si
push es
mov ax, erframe.erhandle
mov di, ax
; check if made
xor ax, ax
cmp al, made
jne ERDUMMY0
jmp BAD_ER
ERDUMMY0:
mov bh, handx1 ; handx1
inc bh
mov bl, handy1 ; handy1
inc bl
mov ax, bx
; make sure offsets in widow
add bl, erframe.eryoff
jc BAD_ER
jl BAD_ER
add bh, erframe.erxoff
jc BAD_ER
jl BAD_ER
push bx
; and offsets plus h and w are in window
add bl, erframe.erh
jc BAD_ER_JMPOFF
add bh, erframe.erw
jc BAD_ER_JMPOFF
add al, h ; h
add ah, w ; w
dec al
dec ah
cmp bh, ah
jg BAD_ER_JMPOFF
cmp bl, al
jg BAD_ER_JMPOFF
pop bx
jmp short SLOOP
BAD_ER_JMPOFF:
pop bx
jmp short BAD_ER
SLOOP:
; setup loop
mov ah, interior_attrib
xor al, al
push ax
xor ch, ch
xor dh, dh
mov dl, erframe.erw
mov cl, erframe.erh
mov al, 160
mul bl
mov bl,bh
xor bh, bh
shl bl,1
add ax, bx
mov di, ax
mov bx, ax
mov ax, video_seg
mov es, ax
pop ax
cmp cs:localsnow, 0
je ERL0
mov cs:snow_write_type, 1
ERSNOWL0:
push cx
mov cl, dl
call snowwrite
add bx,160
mov di, bx
pop cx
loop ERSNOWL0
jmp short DONE_ER
ERL0:
push cx
mov cl, dl
rep stosw
add bx,160
mov di, bx
pop cx
loop ERL0
DONE_ER:
BAD_ER:
pop es
pop si
pop di
pop bp
ret
_win_erase_region ENDP
; -----------------------------------------------
_winstrlen proc near
; int winstrlen (win_handle * hand, int x, int y)
; window based strlen. finds length of asciiz string located
; at x, y within a given window
;
; returns -1 on error
;
stlenframe struc
slbptr dw ?
slraddr dw ?
slhandle dw ?
slx db ?
db ?
sly db ?
db ?
stlenframe ends
slframe equ [bp - slbptr]
push bp ; Stack frame manipulations
mov bp,sp
sub sp,slbptr
push di
push si
push es
mov ax, slframe.slhandle
mov di, ax
; check if made
xor ax, ax
cmp al, made
je BAD_SLN
mov bh, handx1 ; handx1
inc bh
mov bl, handy1 ; handy1
inc bl
mov ax, bx
; make sure offsets in window
add bl, slframe.sly
jc BAD_SLN
jl BAD_SLN
add bh, slframe.slx
jc BAD_SLN
jl BAD_SLN
xor ah, ah
mov al, w
dec al
dec al
sub al, slframe.slx
jc BAD_SLN
shl ax, 1 ; words
mov cx, ax
push cx
mov ax, video_seg
mov es, ax
; calculate initial offset
mov al, 160
mul bl
mov bl,bh
xor bh, bh
shl bl,1
add ax, bx
mov di, ax
xor al, al
repne scasb
pop ax ; original cx
sub ax, cx
shr ax, 1
jmp short SLNEXIT
BAD_SLN:
mov ax, -1
SLNEXIT:
pop es
pop si
pop di
pop bp
ret
_winstrlen ENDP
; -----------------------------------------------
snowwrite proc near
; registers preserved (except flags)
; function is determined by cs:snow_write_type, which is a last-minute
; kludge.
;
; Method adapted from Richard Wilton's video book.
;
; type = 0 ; do a stosb
; type =1 ; do a rep stosw
; type =2 ; do a rep movsw
push ax
push bx
push dx
mov dx, 3dah
cmp cs:snow_write_type, 0
jne REPS
push cx
mov cx, 1
REPS:
mov bx, cx
mov cx, cs:cga_timeout
push ax
cli
SW0:
in al, dx
test al, 1
loopnz SW0
pop ax
jz HORIZ
cmp cs:snow_write_type, 2
jne ONEOR2
lodsw
ONEOR2:
cmp cs:snow_write_type, 0
je TYPE0
stosw
jmp short V0DONE
TYPE0:
stosb
V0DONE:
sti
mov cx, bx
loop REPS
jmp short SWEXIT
; dummy horizontal blanking write
HORIZ:
push ax
sti
HORILOOP:
mov cx, cs:cga_timeout
cli
SWH0:
in al, dx
test al, 1
loopnz SWH0
jnz VERT2
SWH1:
in al, dx
test al, 1
jz SWH1
sti
jmp short HORILOOP
VERT2:
sti
pop ax
mov cx, bx
cmp cs:snow_write_type, 2
jl SWNEXT0
rep movsw
jmp short SWEXIT
SWNEXT0:
cmp cs:snow_write_type, 1
jl SWNEXT1
rep stosw
jmp short SWEXIT
SWNEXT1:
stosb
SWEXIT:
cmp cs:snow_write_type, 0
jne NOPOPCX
pop cx
NOPOPCX:
pop dx
pop bx
pop ax
ret
snowwrite ENDP
; -----------------------------------------------
_cgainit proc near
; int cgainit (void)
;
; determines timeout value
; puts snowflag in local code segment
;
;
cinitframe struc
cgabptr dw ?
cgaraddr dw ?
cinitframe ends
cgaframe equ [bp - cgabptr]
push bp ; Stack frame manipulations
mov bp,sp
sub sp,cgabptr
push es
mov ax, snowflag
mov cs:localsnow, ax
mov ax, video_seg
mov dx, 3dah
cmp graphics_type, 3
jne CGAINOTCGA
mov es, ax
CGAI0:
in al, dx
test al, 8
jz CGAI0
CGAI1:
in al, dx
test al, 8
jnz CGAI1
mov cx, 0ffffh
cli
CGAI2:
in al, dx
test al, 1
jnz CGAI2
CGAI3:
in al, dx
test al, 1
jz CGAI3
CGAI4:
in al, dx
test al, 1
loopnz CGAI4
sti
neg cx
shl cx, 1
mov cs:cga_timeout, cx
CGAINOTCGA:
pop es
pop bp
ret
_cgainit ENDP
; ---------------------------------------------
_text ends
END