📄 llagrp.asm
字号:
TITLE LLAGRP - GW-BASIC Support for advanced graphics
;***
; LLAGRP - GW-BASIC Support for advanced graphics
;
; Copyright <C> 1986, Microsoft Corporation
;
;Purpose:
; This module contains support for graphics functions required only
; by programs using graphics drawing statements. Routines called
; directly or indirectly by statements not specifically graphic in
; nature (such as CLS) belong in LLCGRP for runtime granularity.
;
; Routines in this module are mode-independent in one or more of the
; following ways:
; 1) no device-dependent interaction,
; 2) table driven through mode-dependent data hooks, or
; 3) calls mode-dependent routines through function hooks.
;
; Mode-dependent graphics functions and initializers for hooks
; are segregated in separate modules for better granularity.
;
;******************************************************************************
INCLUDE switch.inc ;feature switches
INCLUDE rmacros.inc
USESEG _BSS
USESEG GR_TEXT
INCLUDE seg.inc
INCLUDE ibmunv.inc
sBegin _BSS
;
;#****************************************************************************
; External variables
;#****************************************************************************
;
externW b$PenC
externB b$MaskC
externB b$AttrC
externD b$AddrC
externW b$OffC
externW b$SegC
externB b$BytesPerRow
externB b$BitsPerPixel
externB b$Planes
externB b$PaintBorder
externB b$Tiling
externW b$Incr1
externW b$Incr2
externW b$IncrY
;
;#****************************************************************************
; External function vectors
;#****************************************************************************
;
externW b$SetAttr
externW b$MapXYC
externW b$PutAction
externW b$NReadL
externW b$NWriteL
externW b$SetPixFirstC
externW b$SetPixLastC
;
;#****************************************************************************
; Local variables
;#****************************************************************************
;
staticW BitCount,,1 ;count of pixel bits per line for Get/Put
staticW Shift,,1 ;lo byte = left shift count to align video
; byte with array byte for Get/Put
staticW Masks,,1 ;lo byte = mask to apply to last partial
; byte for Put
;hi byte = mask to apply to first partial
; byte for Put
labelD ArrayAddr,,1 ;address of Get/Put array
staticW ArrayOff,,1 ; offset of Get/Put array
staticW ArraySeg,,1 ; segment of Get/Put array
sEnd _BSS
assumes CS,GR_TEXT
sBegin GR_TEXT
;***
;B$PixSize - Get number of bits per pixel
;OEM-interface routine
;
;Purpose:
; Get the number of bits per pixel for the current graphics mode.
; This routine will never be called if the screen is not in a
; graphics mode.
;
; This routine is only called when determining whether a graphics
; PUT will fit on the screen. Note that on multiple plane
; systems, this routine should return the number of bits per pixel
; on a single plane, not the total number of bits on all the planes.
;
;Entry:
; none
;
;Exit:
; [AL] = bits / pixel
;
;Uses:
; Per Convention
;
;Preserves:
; BX, CX, DX
;
;Exceptions:
; none
;****
cProc B$PixSize,<PUBLIC,NEAR>
cBegin
mov al,b$BitsPerPixel
cEnd
;***
;B$PutGetInit - Initialize variables for B$NReadC and B$NWriteC
;OEM-interface routine
;
;Purpose:
; Called once for every PUT or GET statement to initialize
; variables used by B$NReadC and B$NWriteC.
;
; Following B$PutGetInit, PUT and GT enter a loop which
; calls B$NReadC or B$NWriteC once for each line of the
; rectangle being processed. If B$PutGetInit is being
; called by PUT, then it must retain which function ([AL])
; is being requested. Usually this entails setting up a
; PUT function dispatch vector. B$PutGetInit is also
; responsible for saving the array address and the line
; length for B$NReadC or B$NWriteC. Depending on how
; these routines are implemented, it may be desirable to
; calculate certain other values in B$PutGetInit for speed
; considerations.
;
; Upon entry into B$PutGetInit, the graphics cursor has
; been set to the upper left hand corner of the rectangle
; that is to be used.
;
;Entry:
; [AL] = PUT action [0..4] represent (OR,AND,PRESET,PSET,XOR)
; [ES:BX] = address of source/destination array
; [CX] = bits/pixel * pixels/horizontal line
; PSW.C = set indicates caller is PUT
; PSW.C = reset indicates caller is GET
;
;Exit:
; none
;
;Uses:
; Per Convention
;
;Exceptions:
; none
;****
cProc B$PutGetInit,<PUBLIC,NEAR>
cBegin
pushf
mov ArrayOff,bx ;set up array address
mov ArraySeg,es
mov BitCount,cx ;save bit count
mov bl,b$MaskC ;align mask to array byte to get shift count
xor dx,dx ;zero shift count
xor bh,bh ;mask for PUT
mov ch,cl ;get bit count
; (only concerned about mod 8 for bit index)
mov cl,b$BitsPerPixel ;shift count
PGILoop:
shl bl,cl ;test mask byte alignment
jc PGI2 ;go if it was
or bh,bl ;or pixel to first partial byte PUT mask
add ch,cl ;byte-align count for last partial byte PUT mask
add dl,cl ;bump shift count of bits
jmp short PGILoop
PGI2:
mov bl,0FFH ;set up mask for last partial byte
popf
jc PGIPut ;go for PUT init
mov cx,BitCount ;use bit cnt to determine final mask for GET
and cx,7 ;bit count in last byte
jz PGI4 ;go if full byte
shr bl,cl ;shift 0's in for mask
not bl ;invert for 1's
PGI4:
mov dh,bl ;last byte mask
mov Shift,dx ;save align shift count and last byte mask
jmp short PGExit ;exit if not PUT init
PGIPut:
not bh ;mask for 1st partial byte
mov cl,ch
and cx,7 ;bit count in last byte
jz PGI3 ;go if full byte
shr bl,cl ;shift 0's in for mask
not bl ;invert for 1's
PGI3:
mov Shift,dx ;save alignment shift count
mov Masks,bx ;save masks
call [b$PutAction] ;set up PUT action
PGExit:
cEnd
;***
;B$NReadC - Read multiple pixels from screen
;OEM-interface routine
;
;Purpose:
; Transfer bits from the screen to the array specified by
; the last B$PutGetInit. This routine is responsible for
; maintaining a pointer to the appropriate location in the
; destination array. The starting point on the screen for
; the transfer is the graphics cursor.
;
;Entry:
; B$PutGetInit must have been called.
;
;Exit:
; Array updated.
;
;Uses:
; per convention
;
;Exceptions:
; none
;****
cProc B$NReadC,<PUBLIC,NEAR>,<DI,SI,BP>
cBegin
cld
mov bl,b$Planes ;number of planes to read for each row
les di,ArrayAddr ;array offset and segment
push ds
lds si,b$AddrC ;screen address
ASSUME DS:NOTHING
xor bh,bh ;starting plane
NRdLoop:
.erre ID_SSEQDS ;assumes ss = ds
mov cx,ss:Shift ;cl=array align shift, ch=last byte mask
mov bp,ss:BitCount ;total bits to read
push bx ;save: plane info
push si ; screen address
.erre ID_SSEQDS ;assumes ss = ds
call ss:[b$NReadL] ;read a line from plane [bh]
pop si
pop bx
inc bh ;next plane
dec bl ;one more plane done
jnz NRdLoop ;go for next plane
pop ds
ASSUME DS:DGROUP
mov ArraySeg,es ;save updated array segment
mov ArrayOff,di ; and offset
cEnd
;***
;B$NWriteC - Write multiple pixels to the screen
;OEM-interface routine
;
;Purpose:
; Retrieve information from the array indicated by the last call
; to B$PutGetInit, perform the requested function on it, and store
; the resulting data on the screen. This routine is responsible
; for maintaining a pointer to the appropriate location in the
; source array, so that multiple calls to B$NWriteC will step
; though the entire array. The pixels will be written starting
; at the graphics cursor.
;
;Entry:
; B$PutGetInit must have been called
;
;Exit:
; Screen updated.
;
;Uses:
; per convention
;
;Exceptions:
; none
;****
cProc B$NWriteC,<PUBLIC,NEAR>,<DI,SI,BP>
cBegin
cld
mov bl,b$Planes ;number of planes to write for each row
les di,b$AddrC ;screen address
push ds
lds si,ArrayAddr ;array offset and segment
ASSUME DS:NOTHING
xor bh,bh ;starting plane
NWrLoop:
.erre ID_SSEQDS ;assumes ss = ds
mov cx,ss:Shift ;cx=array align shift
mov bp,ss:BitCount ;total bits to read
mov dx,ss:Masks ;dl=last byte mask, dh=first byte mask
push bx ;save: plane info
push di ; screen address
.erre ID_SSEQDS ;assumes ss = ds
call ss:[b$NWriteL] ;write a line to plane [bh]
pop di
pop bx
inc bh ;next plane
dec bl ;one more plane done
jnz NWrLoop ;go for next plane
.erre ID_SSEQDS ;assumes ss = ds
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -