📄 screen.asm
字号:
;* exit: n/a
labelFP <PUBLIC, MoveHardwareCursor>
jmp insj.lpfnMoveHwCursCsdInsj
;********** FQueryInft **********
;* entry: pinft, ifont
;* * get font info
;* exit: AX = 0 => no more fonts
labelFP <PUBLIC, FQueryInft>
jmp insj.lpfnFQueryInftCsdInsj
;********** GetCharMap **********
;* entry: pinft, ifont
;* * get font info
;* exit: AX = 0 => no more fonts
labelFP <PUBLIC, GetCharMap>
jmp insj.lpfnGetCharMapCsdInsj
ifdef WINDOW_OVERLAP
;********** FAllocOverlapTable **********
;* entry: pfnAlloc => allocation function (supplied by App)
;* pinst => current INST infor
;* * Allocate memory for the overlapping windows table
;* * Note!! pinst must have been set up already (FQueryInst)
;* exit: AX != 0 if successful
cPublic FAllocOverlapTable, <>, <SI>
parmDP pinst ;* INST info
parmD pfnAlloc2 ;* FAR PASCAL routine
cBegin FAllocOverlapTable
mov si,pinst
mov al,[si].axMacInst
mov ah,[si].ayMacInst
mul ah
mov bx,ax
mov ax,fmemFixed
Save <bx>
cCall pfnAlloc2, <bx, ax>
AssertEQ ax,0
or dx,dx
jz end_alloc_overlap ;* return AX == 0
mov psOverlap,dx
mov ax,sp ;* success
end_alloc_overlap:
cEnd FAllocOverlapTable
;********** FreeOverlapTable **********
;* entry: pfnFree => free function (supplied by App)
;* * free video driver buffers
;* exit: n/a
cPublic FreeOverlapTable, <>, <SI>
parmD pfnFree2 ;* FAR PASCAL routine
cBegin FreeOverlapTable
xor cx,cx
xchg cx,psOverlap
jcxz done_overlap_free
xor ax,ax
cCall pfnFree2, <cx, ax>
done_overlap_free:
cEnd FreeOverlapTable
endif ;*WINDOW_OVERLAP
;********** FAllocInstBuffers **********
;* entry: pinstAlloc => INST info to fill
;* pfnAlloc => allocation function (supplied by App)
;* fFonts => if secondary buffer wanted
;* * Allocate memory for video driver buffers
;* exit: AX != 0 if successful
cPublic FAllocInstBuffers, <>, <SI>
parmDP pinstAlloc
parmD pfnAlloc ;* FAR PASCAL routine
parmW fFonts
cBegin FAllocInstBuffers
StartPublic
mov si,pinstAlloc
IFNDEF SCREEN_FFONT
AssertEQ fFonts,0 ;* not allowed
endif ;!SCREEN_FFONT
;* * determine size of buffer (axMac * ayMac WORDS)
mov al,[si].axMacInst
mov ah,[si].ayMacInst
mul ah
mov bx,ax
xor ax,ax
mov [si].bits0Inst,ax ;* clear bits
;* * first check to see if primary buffer needs allocation
cmp [si].psPrimInst,ax ;* == 0 ?
jne done_prim_alloc
mov ax,fmemFixed
Save <bx>
cCall pfnAlloc, <bx, ax>
AssertEQ ax,0
or dx,dx
jz end_alloc ;* return AX == 0
mov [si].psPrimInst,dx
or [si].bits0Inst,MASK fAllocPrimInst
done_prim_alloc:
ifdef SCREEN_FFONT
;* * allocate secondary buffer if needed (bx = size of buffer)
mov cx,fFonts
jcxz no_sec_buffer
test [si].finstInst,finstFont
jz no_sec_buffer
mov ax,fmemFixed
cCall pfnAlloc, <bx, ax>
AssertEQ ax,0
or dx,dx
jz end_alloc ;* return AX == 0
mov [si].psSecInst,dx
no_sec_buffer:
endif ;SCREEN_FFONT
;* * allocate any needed driver specific memory
mov cx,[si].cwExtraInst
jcxz done_extra_alloc
mov ax,fmemFixed
cCall pfnAlloc, <cx, ax>
AssertEQ ax,0
or dx,dx
jz end_alloc ;* return AX == 0
mov [si].psExtraInst,dx
done_extra_alloc:
mov ax,sp ;* success
end_alloc:
StopPublic
cEnd FAllocInstBuffers
;********** FreeInstBuffers **********
;* entry: pinstFree => INST info to free
;* pfnFree => free function (supplied by App)
;* * free video driver buffers
;* exit: n/a
cPublic FreeInstBuffers, <>, <SI>
parmDP pinstFree
parmD pfnFree ;* FAR PASCAL routine
cBegin FreeInstBuffers
StartPublic
mov si,pinstFree
test [si].bits0Inst,MASK fAllocPrimInst
jz done_prim_free
xor ax,ax
cCall pfnFree, <[si].psPrimInst, ax>
and [si].bits0Inst,NOT (MASK fAllocPrimInst)
done_prim_free:
ifdef SCREEN_FFONT
xor cx,cx
xchg cx,[si].psSecInst
jcxz done_sec_free
xor ax,ax
cCall pfnFree, <cx, ax>
done_sec_free:
ELSE
AssertEQ [si].psSecInst,0
endif ;!SCREEN_FFONT
;* * free driver buffer
xor cx,cx
xchg cx,[si].psExtraInst
jcxz done_extra_free
xor ax,ax
cCall pfnFree, <cx, ax>
done_extra_free:
StopPublic
cEnd FreeInstBuffers
;*****************************************************************************
;********** FInitScreenInternal **********
;* entry: pinst => INST structure (NULL => re-init previous mode)
;* * Initialize the screen as needed
;* * NOTE : this routine can be called ONLY ONCE.
;* exit: AX != 0 => ok
;* * NOTE: failure may destroy old instCur
cPublic FInitScreenInternal,<ATOMIC>, <SI, DI>
parmW pinst
cBegin FInitScreenInternal
StartPublic
mov bx,dataOffset instCur
mov si,pinst
or si,si
jz use_current
;* * set new INST (copy into instCur)
push ds
pop es
mov di,bx
mov cx,cbInstMin / 2
rep movsw
use_current: ;* bx => instCur (instCur filled with *pinst)
mov ax,ds:[bx].finstInst
and ax,finstAvailable
jnz dont_end
end_init_jump:
jmp end_init ;* variant not available
dont_end:
mov ax,dataOffset inch
Save <bx>
cCall insj.lpfnFInitCsdInsj, <bx, ax> ;* (pinst, pinch)
or ax,ax
jz end_init_jump
;* * move info from INCH to other globals, bx => instCur
mov al,[bx].axMacInst
mov axMac,al
xor ah,ah
shl ax,1
mov axMacTimes2,ax
mov al,[bx].ayMacInst
mov ayMac,al
mov ax,[bx].finstInst
and al,finstMonochrome ;* finstMonochrome in lower byte
mov fMonochrome,al
IFNDEF CBOX
;* * copy information from INCH into boxes
lea bx,inch
push ds
pop es ;* all in default data segment
;* * copy single box
lea si,[bx]._chTopLeftCorner1Inch
lea di,boxSingle
mov cx,SIZE BOX / 2
rep movsw
;* * copy double box
lea si,[bx]._chTopLeftCorner2Inch
lea di,boxDouble
mov cx,SIZE BOX / 2
rep movsw
mov al,[bx]._chShadowInitInch
mov chShadow,al
ifdef WINDOW_OVERLAP
;* * base window is single box
lea si,[bx]._chTopLeftCorner1Inch
lea di,boxActiveWindowOut
mov cx,SIZE BOX / 2
rep movsw
mov al,[bx]._chCloseInch
mov boxActiveWindowOut.chTopLeftBox,al
mov al,[bx]._chZoomOutInch
mov boxActiveWindowOut.chTopRightBox,al
mov al,[bx]._chTopSide2Inch
mov boxActiveWindowOut.chTopBox,al
lea si,[bx]._chTopLeftCorner1Inch
lea di,boxInactiveWindowOut
mov cx,SIZE BOX / 2
rep movsw
mov al,[bx]._chCloseInch
mov boxInactiveWindowOut.chTopLeftBox,al
mov al,[bx]._chZoomOutInch
mov boxInactiveWindowOut.chTopRightBox,al
lea si,[bx]._chTopLeftCorner1Inch
lea di,boxActiveWindowIn
mov cx,SIZE BOX / 2
rep movsw
mov al,[bx]._chCloseInch
mov boxActiveWindowIn.chTopLeftBox,al
mov al,[bx]._chZoomInInch
mov boxActiveWindowIn.chTopRightBox,al
mov al,[bx]._chTopSide2Inch
mov boxActiveWindowIn.chTopBox,al
lea si,[bx]._chTopLeftCorner1Inch
lea di,boxInactiveWindowIn
mov cx,SIZE BOX / 2
rep movsw
mov al,[bx]._chCloseInch
mov boxInactiveWindowIn.chTopLeftBox,al
mov al,[bx]._chZoomInInch
mov boxInactiveWindowIn.chTopRightBox,al
endif ;WINDOW_OVERLAP
endif ; !CBOX
ifdef SCREEN_FFONT
;* * set the fFontAvailable flag
xor ax,ax ;* assume off
mov cx,instCur.finstInst
test cx,finstFont
jz set_ffont_available ;* not available in this mode
mov cx,instCur.psSecInst
jcxz set_ffont_available ;* no secondary buffer => forget it
inc ax ;* yes, we can use ffonts
set_ffont_available:
mov fFontAvailable,ax
endif ;SCREEN_FFONT
mov ax,sp ;* success
end_init: ;* ax = return code
StopPublic
cEnd FInitScreenInternal
;********** BltArc **********
;* entry : axSrc, aySrc : upper left of source
;* axDest, ayDest : upper left of destination
;* dax, day : shift amount
;* * Move a rectangle from one portion of the screen to another.
;* exit : n/a
cPrivate BltArc,<ATOMIC>,<SI,DI>
parmB axDest
parmB ayDest
parmB dax
parmB day
parmB axSrc
parmB aySrc
localW fMouseOn ;* FEnableMouse old state
localW offDestLim ;* last offset written
cBegin BltArc
StartPublic
xor ax,ax
cCall FEnableMouse,<ax> ;* turn mouse off
mov fMouseOn,ax
AssertUp
mov al,day
or al,al
jz blt_end1 ;* trivial case (day == 0)
CalcCoord axDest,ayDest
mov di,ax
mov offDrawFirst,ax ;* save for driver inform
;* * Do either a Prep, Do, Done sequence or a fast BltArcCsd call
test instCur.finstInst,finstFastScroll
jnz skip_prep
;* * Prepare screen driver for update
mov si,word ptr (dax) ;* low byte is all that's interesting
;* * si = dax, di = offset in Prim buffer
;* * ax = ayDest, cx = day
xor ax,ax
mov al,ayDest
xor cx,cx
mov cl,day
push di
loop_prep:
Save <ax,cx>
cCall insj.lpfnPrepUpdateCsdInsj, <ax, axDest, si, di, fRestoreDbcs>
add di,axMacTimes2 ;* point to next row
inc ax
loop loop_prep
pop di
skip_prep:
CalcCoord axSrc,aySrc
mov si,ax ; save pointer to source
mov dx,axMacTimes2 ;* row modulus
cmp ax,di
jge blt_hilo ; going from high memory to low
; go from low memory to high. Do backwards Blt Blt Row by row either
; fast or slow depending on the retrace parameter; ax has source, di
; destination of top left hand point
mov al,day
dec al
mul axMac
mov bl,dax
xor bh,bh
add ax,bx
shl ax,1
dec ax ;* back 1 byte (for movsb)
add di,ax ; move source to bottom right
add si,ax ; move dest to bottom, right
neg dx ;* negate row modulus
std ; bltting backwards
jmp short blt_go
blt_end1: ;* jump extender
jmp blt_end
blt_hilo:
; cld ;* D flag already cleared
blt_go:
;* * dx = row modulus (+ or - axMac * 2)
mov cl,dax ; setup number of columns
xor ch,ch
jcxz blt_end1 ;* trivial case (dax == 0)
shl cx,1 ;* ccol -> cb
mov bx,cx ;* CX = BX = cb
push ds
ifdef DEBUG
cmp instCur.psPrimInst,0 ;* no buffer! (FAllocInstBuffers)
jne @F
cCall CowAssertFailed
DB "no primary buffer for current mode$"
@@:
endif ;DEBUG
mov es,instCur.psPrimInst
push es
pop ds ;* DS & ES set to video segment
xor ax,ax
mov al,day
ifdef SCREEN_FFONT
Save <ax,bx,cx,dx,si,di> ;* needed for second call
cCall DoBltArc
pop ds
cmp fFontAvailable,0
jz no_blt_ffont
push ds
mov es,instCur.psSecInst
push es
pop ds ;* DS & ES set to video segment
endif ;SCREEN_FFONT
cCall DoBltArc
pop ds
no_blt_ffont:
cld ;* Clear D flag (convention)
;* Check for fast scrolling in graphics text modes
test instCur.finstInst,finstFastScroll
jz no_fast
cCall insj.lpfnBltArcCsdInsj, <axDest, ayDest, dax, day, axSrc, aySrc>
jmp skip_updatedone
no_fast:
;* * Inform screen driver of the destination area
mov si,word ptr (dax) ;* low byte is all that's interesting
mov di,offDrawFirst
;* * si = dax, di = offset in Prim buffer
loop_inform_blt:
cCall insj.lpfnDoUpdateCsdInsj, <ayDest, axDest, si, di, fRestoreDbcs>
add di,axMacTimes2 ;* point to next row
inc ayDest
dec day
jnz loop_inform_blt
;* * all done, refresh
cCall insj.lpfnDoneUpdateCsdInsj ;* ()
blt_end:
cld ;* Clear D flag (convention)
skip_updatedone:
cCall FEnableMouse,<fMouseOn> ;* restore mouse state
StopPublic
cEnd BltArc
;********** DoBltArc **********
;* entry : ax = day, bx = cx = cb, dx = row modulus, si = source,
;* di = dest, es and ds => video segment
;* * blt screen memory
;* * NOTE: direction flag either set or clear on entry.
;* exit : n/a
cProc DoBltArc,<NEAR,PUBLIC,ATOMIC>
cBegin DoBltArc
assumes ds,nothing
ifdef WINDOW_OVERLAP
push bp ;* current window do blt
mov bp,pwndCur
endif ;WINDOW_OVERLAP
blt_row:
push si
push di
blt_fast:
;* * We can BLT fast
ifdef WINDOW_OVERLAP
or bp,bp
jz blt_fast_allowed
blt_overlap:
push di
and di,not 1
push ds
mov ds,ss:psOverlap
cmp bp,[di]
pop ds
je move_two
;* * skip this movement
push ax
mov di,si ;* old position
lodsw ;* bump by 2 in right direction
mov ax,si
sub ax,di ;* ax = delta (+2 or -2)
pop di ;* old DI
add di,ax ;* DI points to new position
pop ax
jmp short move_overlap_next
move_two:
pop di
ifdef BUILTIN_SNOW
push ax
push dx
mov dx,3DAh ;* CGA video status port
StartDrawCrit
endif ;BUILTIN_SNOW
movsb
movsb
ifdef BUILTIN_SNOW
EndDrawCrit
pop dx
pop ax
endif ;BUILTIN_SNOW
move_overlap_next:
dec cx
loop blt_overlap
jmp short blt_next_row
blt_fast_allowed: ;* fall through to rep move
endif ;WINDOW_OVERLAP
ifdef BUILTIN_SNOW
push ax
push dx
mov dx,3DAh ;* CGA video status port
SnowL1:
StartDrawCrit
movsb
EndDrawCrit
loop SnowL1
pop dx
pop ax
ELSE ;NOT DEFINED BUILTIN_SNOW
rep movsb ;* move byte to keep backward case
endif ;BUILTIN_SNOW
;* simple.
blt_next_row:
pop di
pop si
mov cx,bx ;* restore cx as cb
add di,dx
add si,dx ; move to next/previous row
dec ax
jnz blt_row
ifdef WINDOW_OVERLAP
pop bp
endif ;WINDOW_OVERLAP
cEnd DoBltArc
sEnd SCREEN
;----------------------------------------------------------------------------
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -