1992 lines
64 KiB
NASM
1992 lines
64 KiB
NASM
name graphics
|
||
title PC Scheme Graphics
|
||
page 60,132
|
||
;-----------------------------------------------------------------------------
|
||
;
|
||
; TITLE: PC Scheme Graphics
|
||
; AUTHOR: Medford W. Haddock II (Rusty)
|
||
; DATE: October 20, 1983
|
||
; COMPUTER: Texas Instruments Professional Computer with 3-plane graphics
|
||
; IBM PC with Color, Enhanced, or Professional Graphics Adapters
|
||
; ABSTRACT: These routines are designed to interface between PC Scheme
|
||
; and the color graphics board for both the IBM and TI PCs.
|
||
; REVISIONS: ds - 9/25/86 - added support for the IBM EGA modes 14 and 16
|
||
; rb 11/7/86 - added point, line, box clipping (both TI and IBM)
|
||
; rb 11/24/86 - fix line drawn from p1 to p2 not same as
|
||
; line drawn from p2 to p1
|
||
; mrm 4/15/87 - modified set-mode! to run w/o screen flicker
|
||
; modified set-palette! to save EGA colors
|
||
; rb 6/13/87 - use CR for EGA mode 16 for illegal mode values
|
||
;
|
||
;-----------------------------------------------------------------------------
|
||
|
||
include pcmake.equ
|
||
|
||
page
|
||
;-----------------------------------------------------------------------------
|
||
; The "intersect" macro. in: none
|
||
; out: AX=intersect value
|
||
; destroys: AX,BX,CX,DX,SI
|
||
; usage: intersect L,y2,x2,x1,y1 (be careful of the funny ordering)
|
||
;
|
||
; Given a line that crosses a clipping edge, determine the point of
|
||
; intersection: one of the coordinates is that of the clipping edge,
|
||
; and this macro calculates the other coordinate.
|
||
;
|
||
; The equation pattern is: new-y = y1 + (y2 - y1) * (L - x1) / (x2 - x1).
|
||
;-----------------------------------------------------------------------------
|
||
intersect macro L,y2,x2,x1,y1
|
||
mov AX,L
|
||
mov BX,y2
|
||
mov CX,x2
|
||
mov DX,x1
|
||
mov SI,y1
|
||
sub BX,SI ;; y2 - y1
|
||
sub CX,DX ;; x2 - x1
|
||
sub AX,DX ;; L - x1
|
||
imul BX ;; (y2 - y1) * (L - x1) = q
|
||
idiv CX ;; q / (x2 - x1)
|
||
add AX,SI ;; y1 + q / (x2 - x1)
|
||
endm
|
||
|
||
;-----------------------------------------------------------------------------
|
||
; The "overlap" macro. in: none
|
||
; out: none (look at Z flag)
|
||
; destroys AX,BX,CX
|
||
; usage: overlap contained,disjoint
|
||
;
|
||
; Compares the two rectangles:
|
||
; (Curr_X,Curr_Y) - (Stop_X,Stop_Y) and
|
||
; (Clip_left,Clip-top) - (Clip_right,Clip-bottom)
|
||
; and returns status on their intersection.
|
||
;
|
||
; If the Curr/Stop rectangle is totally contained in the clipping rectangle,
|
||
; jump to label "contained" with the Z flag on. If they are disjoint, jump
|
||
; to label "disjoint" with the Z flag off. Otherwise, they intersect, so
|
||
; fall through. Both jumps are short relative jumps.
|
||
;-----------------------------------------------------------------------------
|
||
overlap macro contained,disjoint
|
||
mov AX,Curr_X
|
||
mov BX,Curr_Y
|
||
call Encode_XY
|
||
mov CH,CL
|
||
mov AX,Stop_X
|
||
mov BX,Stop_Y
|
||
call Encode_XY
|
||
cmp CX,0
|
||
jz contained ;;jump if Curr/Stop totally contained in CR
|
||
test CH,CL
|
||
jnz disjoint ;;jump if they're disjoint
|
||
endm
|
||
|
||
page
|
||
;-----------------------------------------------------------------------------
|
||
|
||
TI_CRT equ 49h
|
||
IBM_CRT equ 10h
|
||
DOS_FUN equ 21h
|
||
|
||
page
|
||
XGROUP group PROGX
|
||
DGROUP group DATA
|
||
DATA segment byte public 'DATA'
|
||
assume DS:DGROUP
|
||
public VID_MODE
|
||
extrn PC_MAKE:word
|
||
extrn char_hgt:word
|
||
;------------------------------------------------------------------------------
|
||
; Some TIPC system constants.
|
||
;------------------------------------------------------------------------------
|
||
X_MAX equ 720 ; Horizontal resolution
|
||
Y_MAX equ 300 ; Vertical resolution
|
||
Num_Colors equ 8 ; Number of colors displayable by TIPC
|
||
Bytes_per_Line equ 92 ; (720-displayed + extra word)/ 8-bits/byte
|
||
;-----------------------------------------------------------------------------
|
||
; These are the default values of the palette & misc. output latches.
|
||
;-----------------------------------------------------------------------------
|
||
DEF_RED equ 0AAh
|
||
DEF_GRN equ 0CCh
|
||
DEF_BLU equ 0F0h
|
||
TEXT_ON equ 040h ; This value is needed for bit-twiddling
|
||
TEXT_OFF equ 00h
|
||
YES_GRPH equ 0FFh
|
||
NO_GRAPH equ 00h
|
||
TRUE equ 0FFh
|
||
FALSE equ 00h
|
||
;-----------------------------------------------------------------------------
|
||
; Local variable storage.
|
||
;-----------------------------------------------------------------------------
|
||
Curr_X dw ? ; Current x-coordinate
|
||
Curr_Y dw ? ; Current y-coordinate
|
||
Stop_X dw ? ; Second endpoint x-coordinate for drawing
|
||
Stop_Y dw ? ; Second endpoint y-coordinate for drawing
|
||
clip_left dw ? ; Clipping rectangle (in screen coordinates)
|
||
clip_top dw ?
|
||
clip_right dw ?
|
||
clip_bottom dw ?
|
||
px dw ? ; Points to the independent variable
|
||
py dw ? ; Points to the dependent variable
|
||
Delta_X dw ? ; = Stop_X - Start_X
|
||
Delta_Y dw ? ; = Stop_Y - Start_Y
|
||
X_Dir dw ? ; -1,0,+1 : step of independent variable
|
||
Y_Dir dw ? ; -1,0,+1 : step of dependent variable
|
||
Xend dw ? ; End value of independent variable
|
||
Incr1 dw ? ; Step for using pnt below desired value
|
||
Incr2 dw ? ; Step for using pnt above desired value
|
||
GRAFIX_ON dw YES_GRPH ; TI Graphics are initially enabled
|
||
VID_MODE dw 3 ; Current video mode for TI (text & grafx on)
|
||
Box_Hite dw ? ; Box is this number of pixels high
|
||
Box_Width dw ? ; Number of bytes the box's width occupies
|
||
Left_Offset dw ? ; Byte offset into graphx planes of upper left box
|
||
Left_End dw ? ; Bit pattern of left end of solid box
|
||
Left_Side dw ? ; Bit pattern of left side of hollow box
|
||
Right_End dw ? ; Bit pattern of right end of solid box
|
||
Right_Side dw ? ; Bit pattern of right side of hollow box
|
||
Fill_Fig db ? ; True if box is to be filled
|
||
func db ? ; EGA function 0 or 18h
|
||
f_code db 7 ; and or xor function
|
||
st_word dw ? ; start sceen offset
|
||
st_bit dw ? ; start bit offset
|
||
ed_word dw ? ; ending word offset
|
||
ed_bit dw ? ; ending bit offset
|
||
w_p_row dw 40 ; # of words per row
|
||
b_p_wrds db 16 ; 16 bits per word
|
||
two dw 2 ; two
|
||
pix_c dw ? ; pixel color
|
||
gra_ram dw 0a000h ; EGA graphics ram address
|
||
y_val dw ?
|
||
|
||
;-----------------------------------------------------------------------------
|
||
; Local constants storage.
|
||
;-----------------------------------------------------------------------------
|
||
X_Resolution dw X_MAX
|
||
Y_Resolution dw Y_MAX
|
||
Bits_per_Byte dw 8
|
||
Color_Cycle db 8
|
||
;-----------------------------------------------------------------------------
|
||
; Stored here will be the current values for the latches should
|
||
; the (ab)user decide to change them later with (set-palette!).
|
||
;-----------------------------------------------------------------------------
|
||
RED_Latch db DEF_RED
|
||
GRN_Latch db DEF_GRN
|
||
BLU_Latch db DEF_BLU
|
||
;-----------------------------------------------------------------------------
|
||
; A table of zeroes for clearing the palettes before a mode change on
|
||
; the EGA.
|
||
; A table of current values for the EGA colors. The table will be
|
||
; modified by each set-palette! command for the EGA. These values
|
||
; will be used to restore the colors after a mode change on the EGA.
|
||
;-----------------------------------------------------------------------------
|
||
clear_pal db 17 dup(0)
|
||
save_pal db 0,1,2,3,4,5,6,7,38h,39h,3ah,3bh,3ch,3dh,3eh,3fh,0
|
||
;-----------------------------------------------------------------------------
|
||
; These are the segments for the three graphics bit-planes
|
||
; in the TIPC color graphics board. The order below is
|
||
; important - see XPCINIT
|
||
;-----------------------------------------------------------------------------
|
||
Bank_A dw 0C000h
|
||
Bank_B dw 0C800h
|
||
Bank_C dw 0D000h
|
||
Misc_Latch dw 0DF82h
|
||
;-----------------------------------------------------------------------------
|
||
; These are the segments of the Red, Green, Blue palette latches.
|
||
;-----------------------------------------------------------------------------
|
||
RED_Palette dw 0DF01h
|
||
GRN_Palette dw 0DF02h
|
||
BLU_Palette dw 0DF03h
|
||
;-----------------------------------------------------------------------------
|
||
; Color to palette bits translation
|
||
;-----------------------------------------------------------------------------
|
||
Palette_Trans label byte
|
||
db 00000001b
|
||
db 00000010b
|
||
db 00010000b
|
||
db 00100000b
|
||
db 00000100b
|
||
db 00001000b
|
||
db 01000000b
|
||
db 10000000b
|
||
;-----------------------------------------------------------------------------
|
||
; Single-bit-on words for setting individual pixels
|
||
;-----------------------------------------------------------------------------
|
||
Bit_Table label byte
|
||
; 01234567 (Pixel numbering - not bit numbering)
|
||
db 10000000b
|
||
db 01000000b
|
||
db 00100000b
|
||
db 00010000b
|
||
db 00001000b
|
||
db 00000100b
|
||
db 00000010b
|
||
db 00000001b
|
||
;-----------------------------------------------------------------------------
|
||
; Gradual bit filled bytes for the "left-side" of horizontal lines
|
||
;-----------------------------------------------------------------------------
|
||
Start_Line label byte
|
||
; 01234567 (Pixel numbering - not bit numbering)
|
||
db 11111111b
|
||
db 01111111b
|
||
db 00111111b
|
||
db 00011111b
|
||
db 00001111b
|
||
db 00000111b
|
||
db 00000011b
|
||
db 00000001b
|
||
;-----------------------------------------------------------------------------
|
||
; Gradual bit filled bytes for the "right-side" of horizontal lines
|
||
;-----------------------------------------------------------------------------
|
||
End_Line label byte
|
||
; 01234567 (Pixel numbering - not bit numbering)
|
||
db 10000000b
|
||
db 11000000b
|
||
db 11100000b
|
||
db 11110000b
|
||
db 11111000b
|
||
db 11111100b
|
||
db 11111110b
|
||
db 11111111b
|
||
;-----------------------------------------------------------------------------
|
||
; Clipping masks
|
||
;-----------------------------------------------------------------------------
|
||
; LTRB (left, top, right, bottom)
|
||
left_mask db 00001000b
|
||
top_mask db 00000100b
|
||
right_mask db 00000010b
|
||
bottom_mask db 00000001b
|
||
;-----------------------------------------------------------------------------
|
||
; Screen resolution table (for the different IBM video modes)
|
||
;-----------------------------------------------------------------------------
|
||
; The table contains the maximum *plottable* X,Y value for the mode.
|
||
Res_Table_IBM label word
|
||
dw 0,0 ;mode 0 not a graphics mode
|
||
dw 0,0 ;mode 1 not a graphics mode
|
||
dw 0,0 ;mode 2 not a graphics mode
|
||
dw 0,0 ;mode 3 not a graphics mode
|
||
dw 319,199 ;mode 4 is a graphics mode
|
||
dw 319,199 ;mode 5 is a graphics mode
|
||
dw 639,199 ;mode 6 is a graphics mode
|
||
dw 0,0 ;mode 7 not a graphics mode
|
||
dw 0,0 ;mode 8 PCjr only
|
||
dw 0,0 ;mode 9 PCjr only
|
||
dw 0,0 ;mode 10 PCjr only
|
||
dw 0,0 ;mode 11 EGA internal mode
|
||
dw 0,0 ;mode 12 EGA internal mode
|
||
dw 319,199 ;mode 13 is a graphics mode
|
||
dw 639,199 ;mode 14 is a graphics mode
|
||
dw 639,349 ;mode 15 is a graphics mode
|
||
dw 639,349 ;mode 16 is a graphics mode
|
||
;-----------------------------------------------------------------------------
|
||
; Jump table for graphit() based on op_code
|
||
;-----------------------------------------------------------------------------
|
||
OP_CODE dw SET_MODE
|
||
dw SETP
|
||
dw SET_PAL ; This used to be RESETP
|
||
dw LINE
|
||
dw GETP
|
||
dw VIDEO_MODE
|
||
dw BOX
|
||
dw FILLD_BX
|
||
dw SET_CLIP_RECT
|
||
table_len equ $ - OP_CODE
|
||
DATA ends
|
||
;-----------------------------------------------------------------------------
|
||
;-----------------------------------------------------------------------------
|
||
page
|
||
PROGX segment byte public 'PROGX'
|
||
assume CS:XGROUP,DS:DGROUP
|
||
;-----------------------------------------------------------------------------
|
||
;-----------------------------------------------------------------------------
|
||
; name GRAPHIT -- Scheme interface to Rusty's graphics routines
|
||
;
|
||
; synopsis graphit(op, arg1, arg2, arg3, arg4, arg5, arg6);
|
||
;
|
||
; description call the appropriate graphics routine based on the "op"
|
||
; argument:
|
||
; 0 - (set-video-mode! mode)
|
||
; 1 - (setp x y color)
|
||
; 2 - (set-palette! curr-color-id new-color-id)
|
||
; 3 - (line x1 y1 x2 y2 color)
|
||
; 4 - (point x y)
|
||
; 5 - (get-video-mode)
|
||
; 6 - (box x-ul y-ul x-len y-len color)
|
||
; 7 - (filled_box x-ul y-ul x-len y-len color xor)
|
||
; 8 - (set-clipping-rectangle! left top right bottom)
|
||
;
|
||
gr_args struc
|
||
dw ? ; caller's BP
|
||
dd ? ; return address
|
||
arg6 dw ? ; argument 6 -- dbs 10/10/86
|
||
arg5 dw ? ; argument 5
|
||
arg4 dw ? ; argument 4
|
||
arg3 dw ? ; argument 3
|
||
arg2 dw ? ; argument 2
|
||
arg1 dw ? ; argument 1
|
||
opcode dw ? ; sub operation code
|
||
gr_args ends
|
||
|
||
public graphit
|
||
graphit proc far
|
||
push BP ; save caller's BP
|
||
mov BP,SP
|
||
|
||
; Load sub opcode
|
||
mov BX,[BP].opcode ; load sub operation code
|
||
add BX,BX ; adjust for index into jump table
|
||
cmp BX,table_len ; bad op_code?
|
||
jae bad_op
|
||
; cmp BX,0 ; "jae" serves as well
|
||
; jl bad_op
|
||
|
||
; Call desired graphics function
|
||
call OP_CODE[BX]
|
||
jmp short gr_end
|
||
|
||
bad_op: mov AX,-1
|
||
|
||
; Return to caller
|
||
gr_end: mov SP,BP ; dump arguments off TIPC's stack
|
||
pop BP ; restore caller's BP
|
||
ret ; return to caller
|
||
graphit endp
|
||
page
|
||
;-----------------------------------------------------------------------------
|
||
;-----------------------------------------------------------------------------
|
||
;
|
||
; name SET_MODE - graphics initialize
|
||
;
|
||
; synopsis (set-video-mode! mode_number)
|
||
;
|
||
; description TIPC | IBM-PC
|
||
; MODE ACTION | MODE ACTION(same as AH=0,INT 10H)
|
||
; --------------------------+---------------------------
|
||
; 0 Clear graphics | 0 40x25 BW 4 320x200 Col
|
||
; 1 Text Enable | 1 40x25 Color 5 320x200 BW
|
||
; 2 Graphics Enable | 2 80x25 BW 6 640x200 BW
|
||
; 3 Text & Graphics Ena | 3 80x25 Color
|
||
; +---------------------------
|
||
; | extra EGA modes:
|
||
; | 13 320x200 16col 40x25 8x8cbox
|
||
; | 14 640x200 16col 80x25 8x8cbox
|
||
; | 15 640x350 4col 80x25 8x14cbox
|
||
; | 16 640x350 16col 80x25 8x14cbox
|
||
;
|
||
; returns nothing
|
||
;
|
||
SET_MODE proc near
|
||
push BP
|
||
push ES
|
||
mov AX,[BP].arg1 ; Get mode-number
|
||
push AX ; Save mode number for later
|
||
cmp PC_MAKE,TIPC ; set IBM mode?
|
||
je ti_mode
|
||
|
||
ibm_mode label near
|
||
|
||
comment % ;;; Protected Mode
|
||
|
||
Commented out 8/3/87 by TC
|
||
|
||
mov AH,12H ; Test for presence of EGA
|
||
mov BX,10H
|
||
int IBM_CRT ; IBM's video BIOS interrupt
|
||
cmp CX,0 ; Is there an EGA here ?
|
||
je ibm_cga ; Apparently not; assume CGA
|
||
push DS
|
||
pop ES
|
||
mov DX,offset clear_pal
|
||
mov AX,1002H ; Set EGA palettes to black for mode
|
||
int IBM_CRT ; change without screen flicker
|
||
pop AX
|
||
push AX
|
||
xor AH,AH ; Set video I/O mode (AH=0) (AL=MODE)
|
||
int IBM_CRT ; IBM's video BIOS interrupt
|
||
call Reset_CR_IBM ; reset clipping rectangle to full screen
|
||
Initialize a delay loop
|
||
mov AH,2CH ; Get time
|
||
int DOS_FUN ; DOS function request
|
||
inc DH ; Add 1 second delay to start time
|
||
mov BX,DX ; Save the ending time
|
||
cmp BH,59 ; Test for 59 seconds (impossible limit)
|
||
jl tm_loop ; OK
|
||
mov BH,0 ; Set it = 0 to avoid a long delay
|
||
tm_loop: mov AH,2CH ; Get time
|
||
int DOS_FUN ; DOS function request
|
||
cmp DX,BX ; Enough time yet ?
|
||
jle tm_loop ; No, loop again
|
||
|
||
mov DX,offset save_pal
|
||
mov AX,1002H ; Set EGA palettes to saved colors
|
||
int IBM_CRT ; IBM's video BIOS interrupt
|
||
jmp short mode_end
|
||
%
|
||
|
||
ibm_cga label near
|
||
pop AX
|
||
push AX
|
||
xor AH,AH ; Set video I/O mode (AH=0) (AL=MODE)
|
||
int IBM_CRT ; IBM's video BIOS interrupt
|
||
call Reset_CR_IBM ; reset clipping rectangle to full screen
|
||
jmp short mode_end
|
||
|
||
ti_mode: call Reset_CR_TI ; reset clipping rectangle to full screen
|
||
cmp AL,0 ; Clear TI graphics and re-init palette
|
||
je clr_grfx
|
||
cmp AL,1 ; Turn off Graphics and Text on
|
||
je textonly
|
||
cmp AL,2 ; Turn on Graphics and Text off
|
||
je grfxonly
|
||
cmp AL,3 ; Turn on both Graphics and Text
|
||
jne ti_err
|
||
jmp all_on
|
||
ti_err:
|
||
pop AX
|
||
xor AX,AX ; Bad op-code
|
||
not AX ; AX = -1
|
||
jmp short err_ret
|
||
|
||
mode_end: pop AX
|
||
mov VID_MODE,AX ; Save VID-MODE for (get-video-mode)[TI-only]
|
||
xor AX,AX ; Return something nice(?)
|
||
|
||
mov char_hgt,8
|
||
cmp vid_mode,14
|
||
jle err_ret
|
||
mov char_hgt,14
|
||
|
||
err_ret: pop ES ; Get the heck outta here
|
||
pop BP
|
||
ret
|
||
|
||
clr_grfx:
|
||
|
||
IFDEF PROMEM ;;; Protected Mode
|
||
reg_block struc ; register block
|
||
dw ? ; AX
|
||
dw ? ; BX
|
||
dw ? ; CX
|
||
dw ? ; DX
|
||
reg_block ends
|
||
|
||
push AX
|
||
push BX
|
||
push CX
|
||
push DX
|
||
|
||
mov DX,SP
|
||
|
||
|
||
mov AH,0C4h ; Issue Real Interrupt
|
||
mov AL,TI_CRT ; TI CRT interrupt number
|
||
int DOS_FUN ; (extended dos function for protected mode)
|
||
ELSE
|
||
mov AH,14h ; Clear graphics planes
|
||
int TI_CRT ; Send command to CRT device driver
|
||
ENDIF
|
||
|
||
mov RED_Latch,DEF_RED ; Reset palettes to default values
|
||
mov GRN_Latch,DEF_GRN
|
||
mov BLU_Latch,DEF_BLU
|
||
cmp byte ptr GRAFIX_ON,YES_GRPH
|
||
jne short mode_end
|
||
mov AL,RED_Latch ; if graphics are enabled reset the palettes
|
||
mov BL,GRN_Latch
|
||
mov CL,BLU_Latch
|
||
mov DL,YES_GRPH
|
||
call pal_set ; Set the graphics palettes on
|
||
jmp short mode_end
|
||
|
||
grfxonly label near
|
||
mov AL,RED_Latch
|
||
mov BL,GRN_Latch
|
||
mov CL,BLU_Latch
|
||
mov DL,YES_GRPH
|
||
call pal_set ; Set the graphics palettes on
|
||
mov AL,TEXT_OFF
|
||
call txt_set ; Turn text off
|
||
jmp short mode_end
|
||
|
||
textonly label near
|
||
xor AL,AL
|
||
mov BL,AL
|
||
mov CL,AL
|
||
mov DL,NO_GRAPH
|
||
call pal_set ; Set the graphics palettes off
|
||
mov AL,TEXT_ON
|
||
call txt_set ; Turn text on
|
||
jmp short mode_end
|
||
|
||
all_on label near
|
||
mov AL,RED_Latch
|
||
mov BL,GRN_Latch
|
||
mov CL,BLU_Latch
|
||
mov DL,YES_GRPH
|
||
call pal_set ; Set the graphics palettes on
|
||
mov AL,TEXT_ON
|
||
call txt_set ; Turn text on
|
||
jmp mode_end
|
||
|
||
pal_set label near
|
||
xor BP,BP ; Zero offset from palette segments
|
||
mov ES,RED_Palette
|
||
mov byte ptr ES:[BP],AL ; Set red palette
|
||
mov byte ptr ES:[BP]+16,BL ; Set green palette
|
||
mov byte ptr ES:[BP]+32,CL ; Set blue palette
|
||
mov byte ptr GRAFIX_ON,DL ; if graphics are on or not
|
||
ret
|
||
|
||
txt_set label near
|
||
xor BP,BP
|
||
mov ES,Misc_Latch
|
||
mov byte ptr ES:[BP],AL
|
||
ret
|
||
SET_MODE endp
|
||
|
||
;-----------------------------------------------------------------------------
|
||
;-----------------------------------------------------------------------------
|
||
page
|
||
;-----------------------------------------------------------------------------
|
||
;-----------------------------------------------------------------------------
|
||
;
|
||
; name SETP -- turn on a pixel at the given coordinates with
|
||
; the specified color.
|
||
;
|
||
; synopsis (setp x y color)
|
||
;
|
||
; description Turn on the pixel at (x,y) [origin at upper left] with
|
||
; one of 8 colors specified by 'color'.
|
||
; Point clipping is done; ignore the ";;" comments.
|
||
;
|
||
;; The arguments
|
||
;; need not be in their proper range (i.e. a MOD of x, y,
|
||
;; and color will be done with their proper values to get
|
||
;; them into the correct range. [0 <= x <= 719, 0 <= y <= 299,
|
||
;; 0 <= color <= 7]). This will give a "wrap-around" effect.
|
||
;; On the IBM-PC with graphics adapter no range checking is done
|
||
;; on either the (x,y) coordinates or the color.
|
||
;
|
||
; returns nothing
|
||
;
|
||
SETP proc near
|
||
push BP
|
||
push DI
|
||
push ES
|
||
;
|
||
mov AX,[BP].arg1 ; Get `x'
|
||
mov BX,[BP].arg2 ; Get `y'
|
||
; call Fix_XY ; Force x and y into their proper ranges
|
||
call Encode_XY ; Encode point's visibility
|
||
cmp CL,0 ; is it visible?
|
||
jnz Set_exit ; no, jump
|
||
mov CX,[BP].arg6 ; xor code
|
||
mov f_code,CL
|
||
mov CX,[BP].arg3 ; Get `color'
|
||
call LCL_SETP ; Display pixel
|
||
Set_exit: xor AX,AX ; Return code of zero
|
||
pop ES
|
||
pop DI
|
||
pop BP
|
||
ret
|
||
SETP endp ; End of SETP(,,)
|
||
;-----------------------------------------------------------------------------
|
||
;-----------------------------------------------------------------------------
|
||
page
|
||
;-----------------------------------------------------------------------------
|
||
;-----------------------------------------------------------------------------
|
||
;
|
||
; name SET_PAL -- Modify the current palette according to PC_MAKE
|
||
;
|
||
; synopsis (set-palette! curr-color-id new-color-id)
|
||
;
|
||
; description If PC_MAKE == TIPC then set-palette twiddles the TIPC
|
||
; graphics palette latches according to the colors specified.
|
||
;
|
||
; If PC_MAKE == [PC,XT,jr,AT] then use the IBM video I/O
|
||
; interrupt (10h), function 11, set color palette;
|
||
; or function 16, set palette registers if EGA is present.
|
||
;
|
||
; returns nothing
|
||
;
|
||
SET_PAL proc near
|
||
push BP
|
||
push ES
|
||
mov BX,[BP].arg1 ; Get current-color-id
|
||
mov CX,[BP].arg2 ; Get new-color-id
|
||
; **** WARNING **** Fix the IBM side of this swapping of A,BX <=> B,CX
|
||
;
|
||
cmp PC_MAKE,TIPC
|
||
jne ibm_pal
|
||
and BX,7 ; use only lower three bits
|
||
mov AL,Palette_Trans[BX] ; convert BL to 1-in-8 bits
|
||
mov AH,AL
|
||
not AH ; AH = 7-in-8 mask
|
||
mov BL,RED_Latch
|
||
call twiddle
|
||
mov RED_Latch,BL
|
||
mov BL,BLU_Latch
|
||
call twiddle
|
||
mov BLU_Latch,BL
|
||
mov BL,GRN_Latch
|
||
call twiddle
|
||
mov GRN_Latch,BL
|
||
cmp byte ptr GRAFIX_ON,YES_GRPH ; are graphics enabled?
|
||
jne pal_ret
|
||
mov AL,RED_Latch ; if yes, then update display palettes
|
||
mov CL,BLU_Latch
|
||
mov DL,YES_GRPH
|
||
call pal_set ; Set the graphics palettes on
|
||
jmp short pal_ret
|
||
|
||
twiddle label near
|
||
sar CL,1 ; Do we turn the bit on or off
|
||
jnc turn_off
|
||
or BL,AL ; Turn it on
|
||
ret
|
||
turn_off: and BL,AH ; Turn it off
|
||
ret
|
||
|
||
ibm_pal: mov AH,15 ; Get current video mode
|
||
int IBM_CRT ; IBM video I/O interrupt
|
||
cmp AL,4 ; Is mode = 4 ?
|
||
jne pal_ega ; No, jump
|
||
; CGA palette
|
||
mov BH,BL ; BH = palette color id being set
|
||
mov BL,CL ; BL = color value
|
||
mov AH,11 ; Set CGA color palette
|
||
int IBM_CRT ; IBM video I/O interrupt
|
||
jmp short pal_ret
|
||
; EGA palette
|
||
pal_ega: mov BH,CL ; BL = palette color id being set
|
||
; BH = color value
|
||
cmp BL,16 ; Is color id reasonable ?
|
||
jge pal_ret ; No, forget it
|
||
mov AX,1000H ; Set EGA color palette
|
||
int IBM_CRT ; IBM video I/O interrupt
|
||
mov BH,0 ; Use palette color id (BL) as index
|
||
mov DS:save_pal[BX],CL ; Save color value in palette table
|
||
|
||
pal_ret: xor AX,AX ; Return code of zero
|
||
pop ES
|
||
pop BP
|
||
ret
|
||
SET_PAL endp ; End of (set-palette!...)
|
||
;-----------------------------------------------------------------------------
|
||
;-----------------------------------------------------------------------------
|
||
page
|
||
;-----------------------------------------------------------------------------
|
||
;-----------------------------------------------------------------------------
|
||
;
|
||
; name VIDEO_MODE - return the current video mode
|
||
;
|
||
; synopsis (get-video-mode)
|
||
;
|
||
; description Returns the video mode number for the appropriate PC.
|
||
;
|
||
; returns video mode number
|
||
;
|
||
public VIDEO_MODE
|
||
VIDEO_MODE proc near
|
||
cmp PC_MAKE,TIPC
|
||
je get_ti_m
|
||
mov AH,15 ; IBM's get current video state
|
||
int IBM_CRT
|
||
cbw ; Convert to full word.
|
||
ret
|
||
|
||
get_ti_m: mov AX,VID_MODE ; This was squirreled away by SET_MODE (TI)
|
||
ret
|
||
VIDEO_MODE endp
|
||
;-----------------------------------------------------------------------------
|
||
;-----------------------------------------------------------------------------
|
||
page
|
||
;-----------------------------------------------------------------------------
|
||
;-----------------------------------------------------------------------------
|
||
;
|
||
; name LINE -- draw a line between the two sets of coordinates
|
||
; given with the specified color.
|
||
;
|
||
; synopsis (line x1 y1 x2 y2 color)
|
||
;
|
||
; description Draw a line between (x1,y1) and (x2,y2) with one of the 8
|
||
; colors specified by 'color'. The line is clipped.
|
||
;
|
||
; This routine is based upon Bresenham's Line Algorithm
|
||
; from page 435 in "Fundamentals of Interactive Computer
|
||
; Graphics" by Foley and Van Dam.
|
||
;
|
||
; The clipping algorithm is Cohen and Sutherland's.
|
||
; See pages 65-67, "Principles of Interactive Computer Graphics"
|
||
; (2nd edition) by Newman and Sproull.
|
||
;
|
||
; returns nothing
|
||
;
|
||
LINE proc near
|
||
push DI
|
||
push SI
|
||
push ES
|
||
|
||
; Clip line
|
||
|
||
mov AX,[BP].arg1 ; Get x1
|
||
mov BX,[BP].arg2 ; Get y1
|
||
mov CX,[BP].arg3 ; Get x2
|
||
mov DX,[BP].arg4 ; Get y2
|
||
cmp AX,CX ; is x1 <= x2?
|
||
jle x1_first ; yes, jump
|
||
; always draw from p1 to p2; otherwise the same line drawn
|
||
; in the opposite direction may not exactly overlay it
|
||
xchg AX,CX ; no, interchange the two points
|
||
xchg BX,DX
|
||
x1_first: mov Curr_X,AX
|
||
mov Curr_Y,BX
|
||
mov Stop_X,CX
|
||
mov Stop_Y,DX
|
||
call Clip_line
|
||
jz Do_line ; jump if line is visible
|
||
jmp Line_exit ; jump if line is invisible
|
||
|
||
; Line drawing proper
|
||
|
||
Do_line: mov px,offset Curr_X ; px = address of Curr_X
|
||
mov py,offset Curr_y ; py = address of Curr_Y
|
||
;
|
||
mov BX,[BP].arg6 ; get xored or not
|
||
mov f_code,BL
|
||
;
|
||
mov AX,Stop_X
|
||
mov BX,Stop_Y
|
||
mov Xend,AX ; Independent var's end-value unless swapped
|
||
|
||
sub BX,Curr_Y ; Delta_Y = y2 - y1
|
||
mov Delta_Y,BX
|
||
sub AX,Curr_X ; Delta_X = x2 - x1
|
||
mov Delta_X,AX
|
||
xchg AX,BX ; Put Delta_Y into ax; Delta_X into bx
|
||
;
|
||
jz Swap_Things ; Is Delta_X == 0 ?
|
||
cwd ; Ready dx for division
|
||
idiv BX
|
||
neg AX
|
||
jge Test_Slope
|
||
neg AX ; slope = ax = ABS(INT(dy/dx))
|
||
Test_Slope label near
|
||
cmp AX,1 ; IF slope >= 1 THEN
|
||
jl Get_X_Increment
|
||
;
|
||
Swap_Things label near
|
||
xchg Delta_Y,BX
|
||
mov Delta_X,BX ; swap(dx,dy)
|
||
mov CX,px
|
||
xchg py,CX
|
||
mov px,CX ; swap(px,py)
|
||
mov CX,Stop_Y
|
||
mov Xend,CX ; Xend = Stop_Y since variables'
|
||
; dependence was swapped.
|
||
; ENDIF
|
||
Get_X_Increment label near
|
||
or BX,BX ; X_Dir = sgn(Delta_X)
|
||
jz Save_X_Dir ; IF it's zero THEN we're done
|
||
mov BX,1 ; ELSE force bx = 1
|
||
jg Save_X_Dir ; IF Delta_X was < zero THEN
|
||
neg BX ; bx = -1
|
||
Save_X_Dir label near
|
||
mov X_Dir,BX
|
||
;
|
||
mov BX,Delta_Y
|
||
or BX,BX ; Y_Dir = sgn(Delta_Y)
|
||
jz Save_Y_Dir ; IF it's zero THEN we're done
|
||
mov BX,1 ; ELSE force bx = 1
|
||
jg Save_Y_Dir ; IF Delta_X was < zero THEN
|
||
neg BX ; bx = -1
|
||
Save_Y_Dir label near
|
||
mov Y_Dir,BX
|
||
;
|
||
mov AX,Delta_X ; Delta_X = ABS(Delta_X)
|
||
neg AX
|
||
jge Save_ABS_Dx
|
||
neg AX
|
||
Save_ABS_Dx label near
|
||
mov Delta_X,AX
|
||
;
|
||
mov BX,Delta_Y ; Delta_Y = ABS(Delta_Y)
|
||
neg BX
|
||
jge Save_ABS_Dy
|
||
neg BX
|
||
Save_ABS_Dy label near
|
||
mov Delta_Y,BX
|
||
;
|
||
shl BX,1
|
||
mov Incr1,BX ; Incr1 = Delta_Y * 2
|
||
sub BX,AX
|
||
push BX ; d = Delta_Y * 2 - Delta_X
|
||
sub BX,AX
|
||
mov incr2,BX ; Incr2 = (Delta_Y - Delta_X) * 2
|
||
;
|
||
mov CX,[BP].arg5 ; Push `color' for call to SETP
|
||
mov BX,Curr_Y ; Push `y'
|
||
mov AX,Curr_X ; Push `x'
|
||
call LCL_SETP ; Plot beginning point
|
||
;
|
||
mov DI,px ; Get pointer to independent variable
|
||
mov SI,py ; Get pointer to dependent variable
|
||
mov AX,X_Dir
|
||
mov BX,Y_Dir
|
||
mov CX,Xend
|
||
pop DX ; get D from stack
|
||
;
|
||
While label near
|
||
cmp CX,DS:[DI] ; While (px->start != xend) {
|
||
je While_End
|
||
add DS:[DI],AX ; Px->start += X_Dir
|
||
or DX,DX ; IF (D < 0) THEN
|
||
jge Inc_Dependent
|
||
add DX,Incr1 ; D += Incr1
|
||
jmp short End_If
|
||
Inc_Dependent label near ; ELSE
|
||
add [SI],BX ; Py->start += Y_Dir
|
||
add DX,Incr2 ; D += Incr2
|
||
End_If label near ; ENDIF
|
||
push AX ; Save X_Dir
|
||
push BX ; Save Y_Dir
|
||
push CX ; Save Xend
|
||
push DX ; Save D
|
||
push DI
|
||
;
|
||
mov CX,[BP].arg5 ; Push `color' for call to SETP
|
||
mov BX,Curr_Y ; Push `y'
|
||
mov AX,Curr_X ; Push `x'
|
||
call LCL_SETP ; Plot beginning point
|
||
;
|
||
pop DI
|
||
pop DX
|
||
pop CX
|
||
pop BX
|
||
pop AX
|
||
jmp short While
|
||
;
|
||
While_End label near
|
||
Line_exit label near
|
||
xor AX,AX ; Return code of zero
|
||
pop ES
|
||
pop SI
|
||
pop DI
|
||
ret
|
||
LINE endp ; End of LINE(,,,,)
|
||
;-----------------------------------------------------------------------------
|
||
;-----------------------------------------------------------------------------
|
||
page
|
||
;-----------------------------------------------------------------------------
|
||
;-----------------------------------------------------------------------------
|
||
;
|
||
; name GETP -- return the attribute (color) at the specified
|
||
; coordinates.
|
||
;
|
||
; synopsis (getp x y)
|
||
;
|
||
; description Return the pixel value (0 - 7) at the coordinates given
|
||
; as arguments. The coordinates are clipped.
|
||
;
|
||
; returns An unsigned integer in the range 0 to 7 , inclusive,
|
||
; if the pixel lies inside the clipping rectangle.
|
||
; The first bit-plane starting at 0C0000h will have its
|
||
; bit represented by the lsb of the returned word. The
|
||
; last bit-plane starting at 0D0000h will have its bit
|
||
; represented by bit number 2 (lsb = bit 0) of the returned
|
||
; word.
|
||
;
|
||
; If the pixel lies outside the clipping rectangle, return -1.
|
||
;
|
||
GETP proc near
|
||
push BP
|
||
push DI
|
||
push ES
|
||
;
|
||
mov AX,[BP].arg1 ; Get `x'
|
||
mov BX,[BP].arg2 ; Get `y'
|
||
; call Fix_XY ; Force x and y into their proper ranges
|
||
call Encode_XY ; Encode point's visibility in the CR
|
||
cmp CL,0 ; is point visible in the CR?
|
||
mov AX,-1
|
||
jne IBM_Ret_Clr ; no, jump (return -1 in AX)
|
||
mov AX,[BP].arg1 ; restore AX to 'x'
|
||
|
||
cmp PC_MAKE,TIPC
|
||
je ti_getp
|
||
;
|
||
mov dx,bx ; Do it the IBM way (ugh!)
|
||
mov cx,ax
|
||
mov ah,13
|
||
int IBM_CRT ; IBM Video BIOS
|
||
xor ah,ah ; Color is in AL
|
||
mov dx,ax
|
||
jmp short IBM_Ret_Clr
|
||
|
||
|
||
ti_getp label near
|
||
call GM_Offset ; Convert (x,y) to linear offset
|
||
;
|
||
; Read the specified bit in each of the graphics memory banks.
|
||
;
|
||
xor DX,DX ; Clear value to be returned
|
||
mov ES,Bank_C ; Get segment of 3rd bank
|
||
mov BH,ES:[DI] ; Copy the selected byte in graphics memory
|
||
and BH,AH ; Was the bit on ?
|
||
jz short Test_Bank_B
|
||
inc DX
|
||
;
|
||
Test_Bank_B label near
|
||
shl DX,1
|
||
mov ES,Bank_B ; Get segment of 2nd bank
|
||
mov BH,ES:[DI] ; Copy the selected byte in graphics memory
|
||
and BH,AH ; Was the bit on ?
|
||
jz short Test_Bank_A
|
||
inc DX
|
||
;
|
||
Test_Bank_A label near
|
||
shl DX,1
|
||
mov ES,Bank_A ; Get segment of 1st bank
|
||
mov BH,ES:[DI] ; Copy the selected byte in graphics memory
|
||
and BH,AH ; Was the bit on ?
|
||
jz short Return_Color
|
||
inc DX
|
||
;
|
||
Return_Color label near
|
||
mov AX,DX ; Put returning value into ax
|
||
|
||
IBM_Ret_Clr label near
|
||
pop ES
|
||
pop DI
|
||
pop BP
|
||
ret
|
||
GETP endp ; End of GETP(,)
|
||
;-----------------------------------------------------------------------------
|
||
;-----------------------------------------------------------------------------
|
||
page
|
||
;-----------------------------------------------------------------------------
|
||
; Encode_XY in: AX=X, BX=Y
|
||
; out: CL=code
|
||
; destroyed: CL
|
||
;
|
||
; Encode X,Y into a 4-bit code indicating its visibility in the clipping rectangle.
|
||
; The code is returned in CL: CL =0: point is visible
|
||
; CL<>0: point is invisible.
|
||
;-----------------------------------------------------------------------------
|
||
Encode_XY proc near
|
||
mov CL,0 ; clear CL; code is constructed here
|
||
cmp AX,clip_left ; x >= clip_left?
|
||
jge Enc_1 ; yes, jump
|
||
or CL,left_mask ; no, set bit
|
||
Enc_1: cmp BX,clip_top ; y >= clip_top?
|
||
jge Enc_2 ; yes, jump
|
||
or CL,top_mask ; no, set bit
|
||
Enc_2: cmp AX,clip_right ; x <= clip_right?
|
||
jle Enc_3 ; yes, jump
|
||
or CL,right_mask ; no, set bit
|
||
Enc_3: cmp BX,clip_bottom ; y <= clip_bottom?
|
||
jle Enc_4 ; yes, jump
|
||
or CL,bottom_mask ; no, set bit
|
||
Enc_4: ret
|
||
Encode_XY endp
|
||
|
||
page
|
||
;-----------------------------------------------------------------------------
|
||
; Clip_line in: none
|
||
; out: none (Z flag)
|
||
; destroyed: AX,BX,CX,DX,SI,DI
|
||
;
|
||
; The line between (Curr_X, Curr_Y) and (Stop_X, Stop_Y) is clipped.
|
||
; The two points' coordinates are possibly modified during the process.
|
||
; On exit: Z=0 if line is visible (onscreen); the final coordinates
|
||
; are in the Curr and Stop memory locations
|
||
; Z=1 if line is invisible (offscreen)
|
||
;-----------------------------------------------------------------------------
|
||
Clip_line proc
|
||
mov DI,offset Stop_X
|
||
overlap Cli_exit,Cli_exit ; if line's extents rectangle lies wholly
|
||
; inside or wholly outside clipping rectangle,
|
||
; exit immediately
|
||
|
||
jmp short Cli_loop ; else start clipping
|
||
|
||
; At this point AX=new X and BX=new Y.
|
||
; (Note this is executed *after* the loop. It's rearranged to
|
||
; get all the relative branches within range.)
|
||
|
||
Cli_join:
|
||
mov [DI],AX ; store X back into memory
|
||
mov [DI+2],BX ; ditto for Y
|
||
pop CX ; restore codes
|
||
call Encode_XY ; get code for new X and Y
|
||
|
||
cmp CX,0 ; is combined code zero?
|
||
jz Cli_exit ; yes, jump; line totally visible at last
|
||
test CH,CL ; do any encoded bits line up?
|
||
jz Cli_loop ; no, jump; some part of line is visible.
|
||
; if fall thru, line was invisible after all
|
||
Cli_exit: ret
|
||
|
||
; We have to clip the line.
|
||
|
||
Cli_loop: cmp CL,0 ; is this point visible?
|
||
jnz Cli_1 ; no, jump
|
||
xchg CH,CL ; yes, go work on other point
|
||
sub DI,4 ; set pointer to other point
|
||
Cli_1: push CX ; tempsave the codes
|
||
test CL,left_mask ; is point off left side?
|
||
jz Cli_2 ; no, jump
|
||
; The endpoint is to the left of the clipping rectangle.
|
||
intersect clip_left,Stop_Y,Stop_X,Curr_X,Curr_Y
|
||
mov BX,AX ; new Y
|
||
mov AX,clip_left ; new X
|
||
jmp Cli_join
|
||
Cli_2: test CL,top_mask ; is point off top side?
|
||
jz Cli_3 ; no, jump
|
||
; The endpoint is above the top of the clipping rectangle.
|
||
intersect clip_top,Stop_X,Stop_Y,Curr_Y,Curr_X
|
||
; AX contains new X already
|
||
mov BX,clip_top ; new Y
|
||
jmp Cli_join
|
||
Cli_3: test CL,right_mask ; is point off right side?
|
||
jz Cli_4 ; no, jump
|
||
; The endpoint is to the right of the clipping rectangle.
|
||
intersect clip_right,Stop_Y,Stop_X,Curr_X,Curr_Y
|
||
mov BX,AX ; new Y
|
||
mov AX,clip_right ; new X
|
||
jmp Cli_join
|
||
Cli_4: ; no need for more tests
|
||
; The endpoint is below the bottom of the clipping rectangle.
|
||
intersect clip_bottom,Stop_X,Stop_Y,Curr_Y,Curr_X
|
||
; AX contains new X already
|
||
mov BX,clip_bottom ; new Y
|
||
jmp Cli_join
|
||
|
||
Clip_line endp
|
||
|
||
page
|
||
;-----------------------------------------------------------------------------
|
||
; Clip_box in: none
|
||
; out: none
|
||
; destroyed: AX
|
||
;
|
||
; The box with corners (Curr_X, Curr_Y) and (Stop_X, Stop_Y) is clipped.
|
||
; (The corners should be (left,top) and (right,bottom) respectively.)
|
||
; The two points' coordinates are possibly modified during the process.
|
||
;-----------------------------------------------------------------------------
|
||
Clip_box proc
|
||
mov AX,clip_left
|
||
cmp Curr_X,AX
|
||
jge CB_1
|
||
mov Curr_X,AX
|
||
CB_1: mov AX,clip_top
|
||
cmp Curr_Y,AX
|
||
jge CB_2
|
||
mov Curr_Y,AX
|
||
CB_2: mov AX,clip_right
|
||
cmp Stop_X,AX
|
||
jle CB_3
|
||
mov Stop_X,AX
|
||
CB_3: mov AX,clip_bottom
|
||
cmp Stop_Y,AX
|
||
jle CB_4
|
||
mov Stop_Y,AX
|
||
CB_4: ret
|
||
Clip_box endp
|
||
|
||
page
|
||
;-----------------------------------------------------------------------------
|
||
|
||
comment ~
|
||
|
||
; NOTE: This routine is no longer called. Clipping is done instead. - rb
|
||
|
||
Fix_XY proc near ; Force x and y into their proper values
|
||
cmp PC_MAKE,TIPC
|
||
jne ibm_dsnt ; IBM doesn't do range checking, Y should I?
|
||
; On IBM, the ranges will vary with the mode
|
||
; On entry ax = `x', bx = `y'
|
||
; On exit ax = ax MOD 720, bx = bx MOD 300
|
||
; cx & dx = <changed>
|
||
; Get `x';fix to proper range (already in ax)
|
||
xor DX,DX ; Clear DX - unsigned dbl-word
|
||
div X_Resolution ; ax = INT(x / 720), dx = (x MOD 720)
|
||
mov CX,DX ; I want the MOD function....
|
||
;
|
||
mov AX,BX ; Get `y' and fix to proper range
|
||
xor DX,DX ; Clear DX - unsigned dbl-word
|
||
div Y_Resolution ; ax = INT(y / 300), dx = (y MOD 300)
|
||
; I want the MOD function....
|
||
mov BX,DX
|
||
mov AX,CX ; Put `x' back
|
||
ibm_dsnt: ret
|
||
Fix_XY endp
|
||
;-----------------------------------------------------------------------------
|
||
;-----------------------------------------------------------------------------
|
||
~ ;end comment
|
||
page
|
||
;-----------------------------------------------------------------------------
|
||
;-----------------------------------------------------------------------------
|
||
GM_Offset proc near
|
||
;
|
||
; Determine which word needs modifying and which bit to set.
|
||
; byte_offset = (Curr_Y * 736-bits/y_pixel * 1-byte/8-bits)
|
||
; + INT(Curr_X * 1-byte/8-x_pixels)
|
||
; bit-in-byte = Curr_X MOD 8 [0-msb, 8-lsb in byte]
|
||
;
|
||
; On entry ax = `x', bx = `y'
|
||
; On exit
|
||
; ah = bit-in-byte, bx = <changed>
|
||
; cx = <unchanged>, dx = <changed>
|
||
; di = byte-addr into graphics memory
|
||
xchg AX,BX ; now ax = `y' & bx = `x'
|
||
; neg AX ; Translate y=0 to bottom of screen
|
||
; add AX,Y_MAX-1 ; y_new = 299 - (y_old MOD 300)
|
||
; mul Bytes_per_Line ; Curr_Y * 736/8-bytes/y_pixel
|
||
shl AX,1 ; 2-clocks
|
||
shl AX,1 ; 2-clocks
|
||
mov DX,AX ; 2-clocks
|
||
shl AX,1 ; 2-clocks
|
||
add AX,DX ; 3-clocks
|
||
neg DX ; 3-clocks
|
||
shl AX,1 ; 2-clocks
|
||
shl AX,1 ; 2-clocks
|
||
shl AX,1 ; 2-clocks
|
||
add AX,DX ; 3-clocks
|
||
; TOTAL = 23-clocks
|
||
; MUL = (128-143)+EA
|
||
xchg AX,BX ; ........save partial sum
|
||
; and get `x' into accumulator
|
||
; xor DX,DX ; Clear DX - unsigned dbl-word
|
||
; div Bits_per_Byte ; ax = word offset from beginning of line
|
||
; dx = bit-in-byte (x MOD 8)
|
||
mov DX,7 ; mask all bits 'cept lower 3
|
||
; 4-clocks
|
||
and DX,AX ; 3-clocks
|
||
shr AX,1 ; 2-clocks
|
||
shr AX,1 ; 2-clocks
|
||
shr AX,1 ; 2-clocks
|
||
; TOTAL = 13-clocks
|
||
; DIV = (154-172)+EA
|
||
add AX,BX ; Ax = byte # offset into graphics bank
|
||
xor AL,1 ; fix byte offset address to jive with
|
||
; Intel's screwy byte ordering!!!
|
||
mov DI,AX ; move for addressing graphics memory
|
||
mov BX,DX ; Saves on number of memory accesses
|
||
mov AH,Bit_Table[bx] ; Ax = bit-pattern
|
||
mov AL,AH
|
||
not AL ; al = NOT ah - for turning bits off
|
||
ret
|
||
GM_Offset endp
|
||
;-----------------------------------------------------------------------------
|
||
;-----------------------------------------------------------------------------
|
||
;
|
||
public LCL_SETP
|
||
LCL_SETP proc near
|
||
cmp PC_MAKE,TIPC
|
||
je ti_setp
|
||
cmp VID_MODE,14
|
||
jl ibm_setp
|
||
cmp f_code,1
|
||
jne ibm_setp
|
||
or CL,080h ; set xor flag on
|
||
|
||
ibm_setp: mov DX,BX ; Move arguments around for IBM
|
||
xchg CX,AX
|
||
xor BH,BH ; video plane
|
||
mov AH,12 ; write dot
|
||
int IBM_CRT
|
||
ret
|
||
|
||
ti_setp label near
|
||
call GM_Offset ; Convert (x,y) to byte offset
|
||
;
|
||
; Determine which graphics memory banks get their bits twiddled.
|
||
;
|
||
|
||
Set_Byte: mov ES,Bank_A ; Get segment of 1st bank
|
||
call set_pixel
|
||
;
|
||
mov ES,Bank_B
|
||
call set_pixel ; Turn on the proper bit
|
||
;
|
||
mov ES,Bank_C
|
||
call set_pixel ; Turn on the proper bit
|
||
;
|
||
Quit_n_Quit label near ; Save the current X & Y and return
|
||
ret
|
||
LCL_SETP endp
|
||
|
||
set_pixel proc near
|
||
shr CL,1 ; Do we turn on/off bit in this bank?
|
||
jnc short this_bank ; If bit was on (one) then
|
||
|
||
cmp f_code,1 ; is the bit xored?
|
||
jne set_01
|
||
|
||
mov BL,ES:[DI] ; get current value
|
||
xor BL,AH ; xor with mask
|
||
mov ES:[DI],BL ; replace value
|
||
ret
|
||
|
||
set_01: or ES:[DI],AH
|
||
ret
|
||
|
||
this_bank label near
|
||
cmp f_code,1 ; xored?
|
||
je set_02
|
||
and ES:[DI],AL ; Turn off the proper bit
|
||
set_02: ret
|
||
set_pixel endp
|
||
|
||
;-----------------------------------------------------------------------------
|
||
;-----------------------------------------------------------------------------
|
||
page
|
||
;-----------------------------------------------------------------------------
|
||
;-----------------------------------------------------------------------------
|
||
;
|
||
; name BOX -- Draw a box in the graphics plane with the
|
||
; specified color.
|
||
;
|
||
; synopsis (box x-ul y-ul x-lr y-lr color)
|
||
;
|
||
; description Draw a box with graphics (not text characters). The
|
||
; upper left-hand corner is specified by (x-ul,y-ul)
|
||
; and the lower right-hand is specified by (x-lr,y-lr).
|
||
; Color indicates the pixel values that will make up the
|
||
; box. The interior will not be filled nor modified
|
||
; in any way. The box is clipped.
|
||
; Edges that are clipped are "shrunk inwards" to fit
|
||
; snug against the corresponding edges of the clipping
|
||
; rectangle. The result is another box and not just
|
||
; some line segments as you'd might expect.
|
||
;
|
||
; returns nothing
|
||
;
|
||
BOX proc near
|
||
mov Fill_Fig,FALSE ; This box ain't getting filled
|
||
BOX_2ND label near ; A secondary entry point for FILLED_BOX
|
||
push SI
|
||
mov AX,[BP].arg1 ; Get x upper-left
|
||
mov BX,[BP].arg2 ; Get y upper-left
|
||
; call Fix_XY ; Force x-ul and y-ul into correct ranges
|
||
mov Curr_X,AX
|
||
mov Curr_Y,BX
|
||
mov AX,[BP].arg3 ; Get x lower-right
|
||
mov BX,[BP].arg4 ; Get y lower-right
|
||
; call Fix_XY ; Force x-lr and y-lr into correct ranges
|
||
;
|
||
cmp AX,Curr_X
|
||
jg check_y ; Swap if x-lr < x-ul
|
||
xchg AX,Curr_X
|
||
check_y: cmp BX,Curr_Y
|
||
jg goodargs ; Swap if y-lr < y-ul (origin at top-left)
|
||
xchg BX,Curr_Y
|
||
;
|
||
goodargs: mov Stop_X,AX ; (var. Stop used during clipping only)
|
||
mov Stop_Y,BX
|
||
overlap box_1,box_done_1 ; if box totally inside CR, no need to clip
|
||
; if box totally outside, skip it
|
||
call Clip_box ; else clip box to the clipping rectangle
|
||
box_1: mov AX,Stop_X
|
||
mov BX,Stop_Y
|
||
;
|
||
sub BX,Curr_Y
|
||
inc BX ; BX = the height of the box (min=1-pixel)
|
||
mov Box_Hite,BX
|
||
mov BX,[BP].arg6 ; get function code
|
||
mov f_code,BL
|
||
mov BX,[BP].arg5 ; get the color
|
||
mov pix_c,BX
|
||
;
|
||
cmp PC_MAKE,TIPC ; All the "common" material taken care of
|
||
je BOX_TI
|
||
jmp BOX_IBM
|
||
;
|
||
box_done_1: jmp Box_done ; rel. branch not long enough
|
||
;
|
||
|
||
BOX_TI: mov BX,Curr_Y ; find upper right-hand corner address
|
||
mov y_val,BX
|
||
call GM_Offset
|
||
push DI ; save offset into graphics mem
|
||
push BX ; save bit-number
|
||
;
|
||
mov AX,Curr_X ; find upper left-hand corner address
|
||
mov BX,Curr_Y
|
||
call GM_Offset
|
||
mov Left_Offset,DI ; Offset into graphics plane of upper-left
|
||
xor DI,1 ; This craziness is due to *^&$%! Intel
|
||
;
|
||
mov AH,Start_Line[BX] ; Get left-end bit pattern
|
||
mov AL,AH
|
||
not AL ; Need (0ffh - AH) for Set_Byte()
|
||
mov DH,Bit_Table[BX] ; Get left-siding bit pattern
|
||
mov DL,DH
|
||
not DL ; Need (0ffh - DH) for Set_Byte()
|
||
mov Left_End,AX
|
||
mov Left_Side,DX
|
||
;
|
||
pop BX
|
||
mov AH,End_Line[BX] ; Get right-end bit pattern
|
||
mov AL,AH
|
||
not AL ; Need (0ffh - AH) for Set_Byte()
|
||
mov DH,Bit_Table[BX] ; Get right-siding bit pattern
|
||
mov DL,DH
|
||
not DL ; Need (0ffh - DH) for Set_Byte()
|
||
mov Right_End,AX
|
||
mov Right_Side,DX
|
||
;
|
||
pop CX
|
||
xor CL,1 ; This craziness due to #$%&! Intel
|
||
sub CX,DI
|
||
inc CL
|
||
mov Box_Width,CX ; CX = Number of bytes in box's width
|
||
cmp CL,1 ; are bits in the same byte? (narrow box)
|
||
jg wide_box ; jump if not
|
||
;
|
||
; We need to combine the "ends" and "sides"
|
||
; for a byte-wide box.
|
||
and AH,byte ptr Left_End+1 ; combine left-end and right-end
|
||
mov AL,AH
|
||
not AL
|
||
or DH,byte ptr Left_Side+1 ; combine left-side and right-side
|
||
mov DL,DH
|
||
not DL
|
||
mov Left_End,AX
|
||
mov Left_Side,DX
|
||
;
|
||
wide_box label near
|
||
mov DL,CL ; CL = width in bytes
|
||
mov DH,byte ptr [BP].arg5 ; get color of box
|
||
xor DI,1 ; This squirreliness is due to $%^&*! Intel
|
||
call Solid_Line ; Draw top of BOX
|
||
dec Box_Hite
|
||
Box_Loop: jz Box_Done
|
||
;
|
||
add Left_Offset,Bytes_per_Line ; goto next scan line
|
||
mov DI,Left_Offset
|
||
mov DL,byte ptr Box_Width ; just get the lower byte
|
||
cmp Box_Hite,1
|
||
je Bottom_Line
|
||
;
|
||
cmp Fill_Fig,TRUE ; Do we draw a filled or hollow box?
|
||
jne Do_Hollow
|
||
;
|
||
call Solid_Line ; Draw a solid horizontal line
|
||
jmp short BLoop_End
|
||
;
|
||
Do_Hollow: call Just_Ends ; Draw just the side points
|
||
BLoop_End: dec Box_Hite
|
||
jmp short Box_Loop
|
||
;
|
||
;
|
||
Bottom_Line: mov AX,stop_y
|
||
mov y_val,AX
|
||
call Solid_Line ; Draw the bottom of the box (if >1 high)
|
||
Box_Done: xor AX,AX ; Return a value of zero
|
||
pop SI
|
||
ret
|
||
;
|
||
;
|
||
Solid_Line label near
|
||
cmp f_code,1
|
||
jne S_Line_1
|
||
push DX
|
||
call ti_xxset
|
||
pop DX
|
||
ret
|
||
|
||
S_Line_1: mov AX,Left_End ; Get the bit pattern for left-most byte
|
||
mov CL,DH ; Get the color
|
||
call Set_Byte
|
||
xor DI,1 ; This craziness is due to %$&*@! INTEL!
|
||
dec DL
|
||
jz SLine_Done
|
||
S_Loop: cmp DL,1
|
||
je Last_Byte ; Jump if we need the right side
|
||
;
|
||
mov AX,0FF00h ; Get the solid (FFh) pattern
|
||
mov CL,DH
|
||
inc DI ; Point to next byte in graphics memory
|
||
xor DI,1 ; This craziness is due to %$&*@! INTEL!
|
||
call Set_byte
|
||
xor DI,1 ; This craziness is due to %$&*@! INTEL!
|
||
dec DL
|
||
jmp S_Loop
|
||
;
|
||
Last_Byte: mov AX,Right_End ; Get the bit pattern for right-most byte
|
||
inc DI
|
||
mov CL,DH ; Get color
|
||
xor DI,1 ; This craziness is due to %$&*@! INTEL!
|
||
call Set_Byte
|
||
SLine_Done: ret
|
||
;
|
||
Just_Ends label near
|
||
mov AX,Left_Side
|
||
mov CL,DH
|
||
call Set_Byte
|
||
xor DI,1 ; This craziness is due to %$&*@! INTEL!
|
||
dec DL
|
||
jz Hollow_End
|
||
add DI,Box_Width
|
||
dec DI ; Went one too far with addition
|
||
mov AX,Right_Side
|
||
mov CL,DH
|
||
xor DI,1 ; This craziness is due to %$&*@! INTEL!
|
||
call Set_Byte
|
||
Hollow_End: ret
|
||
;
|
||
;
|
||
; IBM (ugh!) version of draw box (sorry, but to maintain compatability
|
||
; among all the IBM video modes I've used the write-dot function (slow).
|
||
;
|
||
; modified - 10/10/86 for EGA
|
||
;
|
||
BOX_IBM label near
|
||
sub AX,Curr_X
|
||
inc AX ; Box_Width (number of pixels to draw line)
|
||
mov Box_Width,AX
|
||
call IBM_Solid ; Draw the top line of box
|
||
inc Curr_Y
|
||
dec Box_Hite
|
||
jz Box_Done
|
||
IBM_while: cmp Box_Hite,1
|
||
je IBM_botm ; Go draw bottom line
|
||
cmp Fill_Fig,TRUE ; Is box to be filled or not?
|
||
jne IBM_nofill
|
||
call IBM_Solid
|
||
jmp short IBM_fi
|
||
;
|
||
IBM_nofill: call IBM_epts ; Draw the side points for current scan line
|
||
IBM_fi: inc Curr_Y ; end of "if"
|
||
dec Box_Hite
|
||
jmp IBM_while
|
||
|
||
IBM_botm: call IBM_Solid ; Draw bottom line (needs to be solid)
|
||
jmp Box_Done
|
||
;
|
||
IBM_Solid label near ; Draw a solid horizontal line
|
||
|
||
mov DI,Box_Width ; sounds more like a room freshener :-)
|
||
mov DX,Curr_Y
|
||
mov CX,Curr_X
|
||
|
||
cmp vid_mode,14
|
||
jge ega_box
|
||
|
||
mov BL,byte ptr [BP].arg5 ; Get the color
|
||
I_Sloop: mov AH,0Ch ; write-dot function
|
||
mov AL,BL ; copy the color
|
||
int IBM_CRT ; WRITE-DOT(x,y,color)
|
||
inc CX
|
||
dec DI
|
||
jnz I_Sloop
|
||
ret
|
||
;
|
||
IBM_epts label near ; Draw the end points of a horizontal line
|
||
mov DX,Curr_Y
|
||
mov CX,Curr_X
|
||
mov BL,byte ptr [BP].arg5 ; Get the color
|
||
call epts
|
||
cmp Box_Width,1 ; Do we need to do the other end?
|
||
je I_eend
|
||
add CX,Box_Width
|
||
dec CX ; We added 1 too many
|
||
call epts
|
||
I_eend: ret
|
||
|
||
epts proc near
|
||
mov AH,0Ch ; write-dot function
|
||
mov AL,BL
|
||
cmp f_code,1
|
||
jne epts_01
|
||
or AL,080h ; set xor bit
|
||
epts_01: int IBM_CRT ; Write Left dot
|
||
ret
|
||
epts endp
|
||
|
||
;********************************************************************
|
||
;* *
|
||
;* EGA_BOX will draw a solid line on the EGA screen. This method *
|
||
;* is used in preference to write dot since write dot is so slow.*
|
||
;* *
|
||
;* DX = start row *
|
||
;* CX = start col *
|
||
;* DI = length *
|
||
;* *
|
||
;********************************************************************
|
||
|
||
ega_box: mov AX,CX ; put start col into AX
|
||
add AX,DI ; AX is not the ending column
|
||
dec AX ; added one too many
|
||
call xxset
|
||
ret
|
||
BOX endp
|
||
|
||
public xxset
|
||
XXSET PROC NEAR
|
||
|
||
PUSH ES
|
||
PUSH DX
|
||
PUSH DX
|
||
PUSH AX
|
||
|
||
MOV FUNC,0 ; DEFAULT TO DATA UNMODIFIED
|
||
CMP F_CODE,0 ; IS THIS An xor'ed box?
|
||
JE AND_TYPE
|
||
MOV FUNC,18H ; SET TO XOR
|
||
AND_TYPE:
|
||
MOV AX,CX ; PUT THE START COLUMN IN
|
||
MOV BX,DX ; PUT THE ROW IN
|
||
CALL GET_OFFSET ; CALCULATE START ADDR, OFFSET
|
||
CMP BX,8 ; ON A WORD BOUNDARY?
|
||
JL BYTE_01 ; YES, THEN CONTINBUE
|
||
INC AX ; BUMP THE WORD OFFSET
|
||
SUB BX,8 ; ADJUST FOR NEW BYTE ADDRESS
|
||
BYTE_01:
|
||
MOV ST_WORD,AX ; SAVE START ADDRESS AND
|
||
MOV ST_BIT,BX ; BIT OFFSET
|
||
|
||
POP AX ; RESET THE END COLUMN
|
||
POP BX ; POP DX INTO BX - ROW
|
||
CALL GET_OFFSET ; CALCULATE END ADDR, OFFSET
|
||
CMP BX,8 ; ON A WORD BOUNDARY?
|
||
JL BYTE_02 ; YES, THEN CONTINBUE
|
||
INC AX ; BUMP THE WORD OFFSET
|
||
SUB BX,8 ; ADJUST FOR NEW BYTE ADDRESS
|
||
BYTE_02:
|
||
MOV ED_WORD,AX ; SAVE START ADDRESS AND
|
||
MOV ED_BIT,BX ; BIT OFFSET
|
||
|
||
; Now to set up the addresses and masks and write to the planes
|
||
MOV DI,ST_WORD ; SET THE STARTING OFFSET
|
||
|
||
XOR_LOOP:
|
||
MOV AL,-1
|
||
CMP DI,ST_WORD ; STARTING OFFSET?
|
||
JNE END_OFF ; IF NOT, THEN CHECK FOR ENDING OFFSET
|
||
MOV CX,ST_BIT ; SUBTRACT THE STARTING BIT OFFSET
|
||
SHR AL,CL ; SET UP THE CORRECT MASK FOR START
|
||
END_OFF: ; End of offset processing
|
||
CMP DI,ED_WORD ; IS THIS THE LAST BYTE TO PROCESS?
|
||
JNE DO_XOR ; NO, THEN XOR THE DATA AND UPDATE
|
||
MOV AH,-1 ; INITIALIZE THE MASK
|
||
MOV CX,7
|
||
SUB CX,ED_BIT ; SUBTRACT THE # OF ENDING OFFSET
|
||
SHL AH,CL ; WANT TO SAVE ALL BUT BITS PAST END
|
||
AND AL,AH ; AND OFF ALL USELESS BITS
|
||
DO_XOR:
|
||
|
||
; Latch up the current mask
|
||
PUSH AX
|
||
MOV DX,3CEH ; LATCH PORT
|
||
MOV AL,8 ; BIT MASK = on
|
||
OUT DX,AL
|
||
INC DX
|
||
POP AX ; RESTORE THE CURRENT MASK
|
||
OUT DX,AL
|
||
|
||
CMP FUNC,18H
|
||
JNE WRT_ZEROS ; IF XOR, THE ONLY DO 1'S
|
||
|
||
; Set to XOR function
|
||
DEC DX
|
||
MOV AL,3 ; DATA ROTATE REGISTER
|
||
OUT DX,AL ; WRITE IT
|
||
MOV AL,FUNC ; SET THE XOR OPERATOR
|
||
INC DX ; to or everything on to the planes
|
||
OUT DX,AL
|
||
JMP WRT_ONES
|
||
|
||
WRT_ZEROS:
|
||
; Write the one to the planes that are set
|
||
|
||
MOV DX,3C4H ; SEQUENCER ADDRESS
|
||
MOV AL,2 ;
|
||
OUT DX,AL
|
||
|
||
MOV AX,PIX_C ; SET THE COLOR INTO THE AL
|
||
XOR AL,0FH ; SET THE ZERO PLANES TO ON
|
||
INC DX
|
||
OUT DX,AL ; ENABLE THIS PLANE
|
||
MOV ES,gra_ram ; GRAPHICS RAM ADDRESS
|
||
|
||
MOV AL,ES:[DI] ; LATCH UP THE EXISTING DATA
|
||
XOR AL,AL ; WRITE ZEROES
|
||
MOV ES:[DI],AL ; OR WORD IN GRAPHICS PLANE.
|
||
|
||
; Now write to the planes that are ONESes
|
||
|
||
WRT_ONES:
|
||
MOV DX,3C4H ; SEQUENCER ADDRESS
|
||
MOV AL,2 ;
|
||
OUT DX,AL
|
||
|
||
MOV AX,PIX_C ; SET THE COLOR INTO THE AL
|
||
INC DX
|
||
OUT DX,AL ; ENABLE THIS PLANE
|
||
MOV ES,GRA_RAM ; GRAPHICS RAM ADDRESS
|
||
|
||
MOV AL,ES:[DI] ; LATCH UP THE EXISTING DATA
|
||
MOV AL,0FFH ; WRITE ONES
|
||
MOV ES:[DI],AL ; OR WORD IN GRAPHICS PLANE.
|
||
|
||
; Now ready to update the pointers and continue
|
||
|
||
NEXT_BYTE:
|
||
|
||
CMP DI,ED_WORD ; PROCESSED LAST ONE?
|
||
JE XOR_EXIT
|
||
INC DI ; NEXT WORD IN THE GRAPHICS PLANES
|
||
JMP XOR_LOOP ; DO NEXT BYTE
|
||
|
||
XOR_EXIT:
|
||
|
||
MOV DX,3C4H ; SEQUENCER ADDRESS
|
||
MOV AL,2 ;
|
||
OUT DX,AL
|
||
|
||
MOV AL,0FFH ; ENABLE ALL BAMNK
|
||
INC DX
|
||
OUT DX,AL ; ENABLE THIS PLANE
|
||
|
||
MOV DX,3CEH ; SEQUENCER ADDRESS
|
||
MOV AL,3 ;
|
||
OUT DX,AL
|
||
|
||
MOV AL,0 ; NORMAL WRITES
|
||
INC DX
|
||
OUT DX,AL ; ENABLE THIS PLANE
|
||
|
||
DEC DX
|
||
MOV AL,8 ;
|
||
OUT DX,AL
|
||
|
||
MOV AL,0FFH ; ALL BITS
|
||
INC DX
|
||
OUT DX,AL ; ENABLE THIS PLANE
|
||
|
||
POP DX
|
||
POP ES
|
||
RET
|
||
;
|
||
XXSET ENDP
|
||
|
||
|
||
get_offset proc near
|
||
|
||
; AX has the pixel column number
|
||
; BX has the pixel row number
|
||
|
||
div b_p_wrds ; divide by bits per word
|
||
push AX ; save the bit offset
|
||
mov AX,BX ; get the pixel row
|
||
mul w_p_row ; row * 46 words per row
|
||
pop BX ; get words and bit within row
|
||
push BX ; save it again
|
||
xor BH,BH ; get rid of bit
|
||
add AX,BX ; bump to absolute offset
|
||
mul two ; byte offset!
|
||
pop BX
|
||
mov BL,BH ; shift bit count to bl
|
||
xor BH,BH
|
||
ret
|
||
; return - ax=word offset ; bx=bit offset
|
||
|
||
get_offset endp
|
||
|
||
;-----------------------------------------------------------------------------
|
||
;-----------------------------------------------------------------------------
|
||
page
|
||
|
||
;***************************************************************************
|
||
; XXSET - PUT A LINE ON THE SCREEN AT THE START, END LOC AND OF LENGTH L
|
||
; AX=START COL, BX=START ROW , CX=END COL
|
||
; COLOR = COLOR
|
||
;***************************************************************************
|
||
public ti_xxset
|
||
ti_xxset proc near
|
||
push ES
|
||
;
|
||
mov AX,curr_x
|
||
mov BX,y_val
|
||
mov CX,stop_x
|
||
;
|
||
push BX ; save the start row
|
||
call get_offset ; convert row/col to word/bit offset
|
||
|
||
mov st_word,AX ; save the start row offset
|
||
mov st_bit,BX ; save the start bit offset
|
||
pop BX ; restore the start row
|
||
mov AX,CX ; get the ending col
|
||
call get_offset ; convert to word/bit offset
|
||
|
||
mov ed_word,AX ; save the ending word offset
|
||
mov ed_bit,BX ; save the ending bit offset
|
||
; Determine the starting word mask
|
||
mov BX,st_word ; get the starting word offset
|
||
ti_xloop:
|
||
mov DX,-1
|
||
cmp BX,st_word
|
||
jne ti_endoff
|
||
mov CX,st_bit ; starting bit offset
|
||
shr DX,CL ; shift off one bits until mask gotten
|
||
ti_endoff:
|
||
cmp BX,ed_word ; last byte to process?
|
||
jne ti_xor ; no. then xor and update
|
||
push DX ; save mask
|
||
mov DX,-1 ; initialize mask
|
||
mov CX,0fh
|
||
sub CX,ed_bit ;subtract the # of ending offset
|
||
shl DX,CL ; want to save allbut bits past end
|
||
pop AX ; and off all useless bits
|
||
and DX,AX
|
||
|
||
ti_xor: mov CX,pix_c ; get the color
|
||
call ti_xor_word
|
||
cmp BX,ed_word
|
||
je ti_exit
|
||
|
||
add BX,2 ; bump the offset to next word
|
||
jmp ti_xloop ; do next word
|
||
ti_exit:
|
||
pop ES
|
||
inc y_val
|
||
ret
|
||
;
|
||
ti_xxset endp
|
||
|
||
;-----------------------------------------------------------------------------
|
||
;-----------------------------------------------------------------------------
|
||
page
|
||
|
||
;*****************************************************************************
|
||
; XOR_WORD - XOR THE MASK IN THE DX INTO THE 3 GRAPHICS PLANES AT OFFSET
|
||
; XOR THE DATA INTO THE THREE GRAPHICS PLANES
|
||
; BX = WORD OFFSET , DX=MASK , CX=COLOR
|
||
;****************************************************************************
|
||
|
||
ti_xor_word proc near
|
||
|
||
test CX,01h ; xor this plane only if bit set
|
||
jz xor_b ; no, then go to b plane
|
||
mov ES,bank_a ; get the seg addr of the a plane
|
||
call doit
|
||
;
|
||
xor_b:
|
||
test CX,02h ; xor this plane only if bit set
|
||
jz xor_c ; no, then go to c plane
|
||
mov ES,bank_b ; get the seg addr of the b plane
|
||
call doit
|
||
|
||
xor_c:
|
||
test CX,04h ; xor this plane only if bit set
|
||
jz xor_end ; no, then go bump the offset
|
||
mov ES,bank_c ; get the seg addr of the c plane
|
||
call doit
|
||
|
||
xor_end:
|
||
ret
|
||
ti_xor_word endp
|
||
|
||
doit proc near
|
||
mov AX,ES:[BX] ; get the word from a plane
|
||
xor AX,DX ; xor the word
|
||
mov ES:[BX],AX ; put it back
|
||
ret
|
||
doit endp
|
||
|
||
;-----------------------------------------------------------------------------
|
||
;-----------------------------------------------------------------------------
|
||
page
|
||
;-----------------------------------------------------------------------------
|
||
;-----------------------------------------------------------------------------
|
||
;
|
||
; name FILLED_BX -- Draw a solid box in the graphics plane with the
|
||
; specified color.
|
||
;
|
||
; synopsis (filled_box x-ul y-ul x-lr y-lr color)
|
||
;
|
||
; description Draw a filled box with graphics (not text characters).
|
||
; The upper left-hand corner is specified by (x-ul,y-ul)
|
||
; and the lower right-hand is specified by (x-lr,y-lr).
|
||
; Color indicates the pixel values that will make up the
|
||
; box. The interior will be filled with the same color
|
||
; as the box. The box is clipped.
|
||
;
|
||
; returns nothing
|
||
;
|
||
FILLD_BX proc near
|
||
mov Fill_Fig,TRUE
|
||
call BOX_2ND ; Call BOX at a second entry point
|
||
ret
|
||
FILLD_BX endp
|
||
;-----------------------------------------------------------------------------
|
||
;-----------------------------------------------------------------------------
|
||
page
|
||
;-----------------------------------------------------------------------------
|
||
; name SET_CLIP_RECT - Set the clipping rectangle.
|
||
;
|
||
; synopsis (set-clipping-rectangle! left top right bottom)
|
||
;
|
||
; description This routine sets the clipping rectangle for the screen.
|
||
; The coordinate values can be any signed integer. The
|
||
; intersection of the clipping rectangle and the screen is
|
||
; used as the final clipping rectangle. If this would be nil,
|
||
; the clipping rectangle is set to the full screen; we never
|
||
; let it become invisible.
|
||
;
|
||
; returns nothing
|
||
;
|
||
; in: no registers
|
||
; out: no registers
|
||
; destroyed: AX,BX,CX,DX
|
||
;-----------------------------------------------------------------------------
|
||
SET_CLIP_RECT proc near
|
||
cmp PC_MAKE,TIPC
|
||
je SCR_TI
|
||
call Reset_CR_IBM ; set CR to screen's full size
|
||
jmp short SCR_join
|
||
SCR_TI: call Reset_CR_TI ; set CR to screen's full size
|
||
SCR_join: mov AX,[BP].arg1
|
||
mov BX,[BP].arg2
|
||
mov CX,[BP].arg3
|
||
mov DX,[BP].arg4
|
||
; rearrange coordinates so first point is upper left hand corner
|
||
cmp CX,AX ; swap if x-lr < x-ul
|
||
jg SCR_1
|
||
xchg CX,AX
|
||
SCR_1: cmp DX,BX ; swap if y-lr < y-ul (origin at top left)
|
||
jg SCR_2
|
||
xchg DX,BX
|
||
; now we can continue
|
||
SCR_2: mov Curr_X,AX ; store for the overlap check
|
||
mov Curr_Y,BX
|
||
mov Stop_X,CX
|
||
mov Stop_Y,DX
|
||
overlap SCR_3,SCR_4 ; check how screen and CR overlap
|
||
call Clip_box ; they overlap, clip
|
||
SCR_3: mov AX,Curr_X ; move new coords to be final CR
|
||
mov clip_left,AX
|
||
mov BX,Curr_Y
|
||
mov clip_top,BX
|
||
mov AX,Stop_X
|
||
mov clip_right,AX
|
||
mov BX,Stop_Y
|
||
mov clip_bottom,BX
|
||
SCR_4: ret
|
||
SET_CLIP_RECT endp
|
||
|
||
page
|
||
;-----------------------------------------------------------------------------
|
||
; Reset the clipping rectangle to the full size of the screen for IBM modes.
|
||
; Destroys AX and BX.
|
||
;-----------------------------------------------------------------------------
|
||
Reset_CR_IBM proc near
|
||
mov AH,15 ; get the current video mode
|
||
int IBM_CRT
|
||
cmp al,16 ; cmp with max video mode (EGA 16)
|
||
jbe RCI_1
|
||
mov al,16 ; map out-of-range values to EGA 16
|
||
RCI_1: cbw
|
||
shl AX,1 ; multiply by 4
|
||
shl AX,1
|
||
mov BX,AX
|
||
mov clip_left,0 ; set the clipping rectangle accordingly
|
||
mov clip_top,0
|
||
mov AX,Res_Table_IBM[BX]
|
||
mov clip_right,AX
|
||
mov AX,Res_Table_IBM+2[BX]
|
||
mov clip_bottom,AX
|
||
ret
|
||
Reset_CR_IBM endp
|
||
|
||
;-----------------------------------------------------------------------------
|
||
; Reset the clipping rectangle to the full size of the screen for TIPC.
|
||
; No registers are affected.
|
||
;-----------------------------------------------------------------------------
|
||
Reset_CR_TI proc near
|
||
mov clip_left,0
|
||
mov clip_top,0
|
||
mov clip_right,X_max-1
|
||
mov clip_bottom,Y_max-1
|
||
ret
|
||
Reset_CR_TI endp
|
||
|
||
page
|
||
;-----------------------------------------------------------------------------
|
||
;-----------------------------------------------------------------------------
|
||
;
|
||
; name XPCINIT - Any special initialization required for a
|
||
; particular type PC (e.g. IBM)
|
||
;
|
||
; synopsis call far xpcinit (from PGROUP)
|
||
;
|
||
; description A C callable routine (well, almost) that should be used
|
||
; internally to PCS for any special initialization that may
|
||
; be needed for a particular PC.
|
||
;
|
||
; returns nothing ('cept personal satisfaction)
|
||
;
|
||
public XPCINIT
|
||
XPCINIT proc far
|
||
cmp PC_MAKE,TIPC
|
||
jne not_ti
|
||
|
||
IFDEF PROMEM ;;; Protected Mode
|
||
lea DI,Bank_A ; Segment Address of Bank A
|
||
mov SI,4
|
||
cld
|
||
INISEG: mov BX,[DI] ; Get real mode segment address
|
||
xor CX,CX
|
||
mov DX,0FFFFh ; Length of segment
|
||
mov AH,0C0H ; Create Real Data Window
|
||
int DOS_FUN ; (extended Dos function for protected mode)
|
||
stosw ; Save Segment Selector to memory address
|
||
dec SI
|
||
jnz iniseg
|
||
ENDIF
|
||
|
||
mov w_p_row,46
|
||
mov AX,offset XGROUP:endinit ; THIS IS REALLY UGLY!!!
|
||
push AX ; push return address (return from all_on)
|
||
push BP
|
||
push ES
|
||
push VID_MODE
|
||
jmp all_on ; Turn on TEXT, init & clear graphics
|
||
;
|
||
not_ti:
|
||
COMMENT %
|
||
IFDEF PROMEM ;;; Protected Mode
|
||
mov BX,GRA_RAM ; Segment Address of EGA GRAPHICS RAM
|
||
xor CX,CX
|
||
mov DX,0FFFFh ; Length of segment
|
||
mov AL,0C0H ; Create Real Data Window
|
||
int DOS_FUN ; Extended Dos function for protected mode
|
||
mov GRA_RAM,AX ; Save Segment Selector
|
||
ENDIF
|
||
%
|
||
cmp PC_MAKE,0FCh
|
||
jl not_ibm
|
||
mov AX,0500h ; Set active display page (for alpha modes)
|
||
int IBM_CRT ; should I check for graphics mode??? Nah!
|
||
|
||
mov AH,15 ; get current video mode
|
||
int IBM_CRT
|
||
xor AH,AH ; clear AH
|
||
mov VID_MODE,AX ; save videomode
|
||
|
||
mov w_p_row,40
|
||
|
||
cmp AX,16
|
||
jne short endinit
|
||
mov char_hgt,14
|
||
|
||
jmp short endinit
|
||
;
|
||
not_ibm label near ; Could there be a Zenith Z-100 out there?
|
||
; Not for now.
|
||
endinit: ret
|
||
XPCINIT endp
|
||
|
||
PROGX ends
|
||
end
|
||
|