Category : Pascal Source Code
Archive   : FASTWR.ZIP
Filename : FASTWR.ASM

 
Output of file : FASTWR.ASM contained in archive : FASTWR.ZIP

; FASTWR.ASM
; Fast screen writing routines
; By Brian Foley
; Last update: 11/08/87


;****************************************************** Equates

Mono = 0
CGA = 1
EGA = 2
MCGA = 3
VGA = 4

;****************************************************** Data

DATA SEGMENT BYTE PUBLIC

EXTRN BaseOfScreen : WORD ;Pascal variables
EXTRN WaitForRetrace : BYTE

CurrentMode DB ? ;local variables
Display DB ?

DATA ENDS

;****************************************************** Code

CODE SEGMENT BYTE PUBLIC

ASSUME CS:CODE,DS:DATA

PUBLIC FastWrite, FastWriteNA, ChangeAttribute, MoveFromScreen
PUBLIC MoveToScreen, CurrentDisplay, CurrentVideoMode

;****************************************************** CalcOffset

;Calculates offset in video memory corresponding to Row,Column
;On entry, CH has Row, BX has Column (both 1-based)
;On exit, ES:DI points to proper address in video memory, AX = 0

CalcOffset PROC NEAR

XOR AX,AX ;AX = 0
MOV CL,AL ;CL = 0
MOV BH,AL ;BH = 0
DEC CH ;Row (in CH) to 0..24 range
SHR CX,1 ;CX = Row * 128
MOV DI,CX ;Store in DI
SHR DI,1 ;DI = Row * 64
SHR DI,1 ;DI = Row * 32
ADD DI,CX ;DI = (Row * 160)
DEC BX ;Col (in BX) to 0..79 range
SHL BX,1 ;Account for attribute bytes
ADD DI,BX ;DI = (Row * 160) + (Col * 2)
MOV ES,BaseOfScreen ;ES:DI points to BaseOfScreen:Row,Col
RET ;Return

CalcOffset ENDP

;****************************************************** FastWrite

;procedure FastWrite(St : String; Row, Col, Attr : Byte);
;Write St at Row,Col in Attr (video attribute) without snow

;equates for parameters:
FWAttr EQU BYTE PTR [BP+6]
FWCol EQU BYTE PTR [BP+8]
FWRow EQU BYTE PTR [BP+10]
FWSt EQU DWORD PTR [BP+12]

FastWrite PROC FAR

PUSH BP ;Save BP
MOV BP,SP ;Set up stack frame
PUSH DS ;Save DS
MOV CH,FWRow ;CH = Row
MOV BL,FWCol ;BL = Column
CALL CalcOffset ;Call routine to calculate offset
MOV CL,WaitForRetrace ;Grab this before changing DS
LDS SI,FWSt ;DS:SI points to St[0]
CLD ;Set direction to forward
LODSB ;AX = Length(St); DS:SI -> St[1]
XCHG AX,CX ;CX = Length; AL = WaitForRetrace
JCXZ FWExit ;If string empty, exit
MOV AH,FWAttr ;AH = Attribute
RCR AL,1 ;If WaitForRetrace is False...
JNC FWMono ; use "FWMono" routine
MOV DX,03DAh ;Point DX to CGA status port
FWGetNext:
LODSB ;Load next character into AL
; AH already has Attr
MOV BX,AX ;Store video word in BX
CLI ;No interrupts now
FWWaitNoH:
IN AL,DX ;Get 6845 status
TEST AL,8 ;Vertical retrace in progress?
JNZ FWStore ;If so, go
RCR AL,1 ;Else, wait for end of
JC FWWaitNoH ; horizontal retrace
FWWaitH:
IN AL,DX ;Get 6845 status again
RCR AL,1 ;Wait for horizontal
JNC FWWaitH ; retrace
FWStore:
MOV AX,BX ;Move word back to AX...
STOSW ; and then to screen
STI ;Allow interrupts!
LOOP FWGetNext ;Get next character
JMP FWExit ;Done
FWMono:
LODSB ;Load next character into AL
; AH already has Attr
STOSW ;Move video word into place
LOOP FWMono ;Get next character
FWExit:
POP DS ;Restore DS
MOV SP,BP ;Restore SP
POP BP ;Restore BP
RET 10 ;Remove parameters and return

FastWrite ENDP

;****************************************************** FastWriteNA

;procedure FastWriteNA(St : String; Row, Col : Byte);
;Write St at Row,Col without snow, and don't change video attributes

;equates for parameters:
FNCol EQU BYTE PTR [BP+6]
FNRow EQU BYTE PTR [BP+8]
FNSt EQU DWORD PTR [BP+10]

FastWriteNA PROC FAR

PUSH BP ;Save BP
MOV BP,SP ;Set up stack frame
PUSH DS ;Save DS
MOV CH,FNRow ;CH = Row
MOV BL,FNCol ;BL = Column
CALL CalcOffset ;Call routine to calculate offset
MOV CL,WaitForRetrace ;Grab this before changing DS
LDS SI,FNSt ;DS:SI points to St[0]
CLD ;Set direction to forward
LODSB ;AX = Length(St); DS:SI -> St[1]
XCHG AX,CX ;CX = Length; AL = Wait
JCXZ FNExit ;If string empty, exit
RCR AL,1 ;If WaitForRetrace is False...
JNC FNNoWait ; use FNNoWait routine
MOV DX,03DAh ;Point DX to CGA status port
FNGetNext:
LODSB ;Load next character into AL
MOV AH,AL ;Store char in AH
CLI ;No interrupts now
FNWaitNoH:
IN AL,DX ;Get 6845 status
TEST AL,8 ;Check for vertical retrace
JNZ FNStore ; In progress? go
RCR AL,1 ;Else, wait for end of
JC FNWaitNoH ; horizontal retrace
FNWaitH:
IN AL,DX ;Get 6845 status again
RCR AL,1 ;Wait for horizontal
JNC FNWaitH ; retrace
FNStore:
MOV AL,AH ;Move char back to AL...
STOSB ; and then to screen
STI ;Allow interrupts
INC DI ;Skip attribute bytes
LOOP FNGetNext ;Get next character
JMP FNExit ;Done
FNNoWait:
MOVSB ;Move character to screen
INC DI ;Skip attribute bytes
LOOP FNNoWait ;Get next character
FNExit:
POP DS ;Restore DS
MOV SP,BP ;Restore SP
POP BP ;Restore BP
RET 8 ;Remove parameters and return

FastWriteNA ENDP

;****************************************************** ChangeAttribute

;procedure ChangeAttribute(Number : Word; Row, Col, Attr : Byte);
;Change Number video attributes to Attr starting at Row,Col

;equates for parameters:
CAAttr EQU BYTE PTR [BP+6]
CACol EQU BYTE PTR [BP+8]
CARow EQU BYTE PTR [BP+10]
CANumber EQU WORD PTR [BP+12]

ChangeAttribute PROC FAR

PUSH BP ;Save BP
MOV BP,SP ;Set up stack frame
MOV CH,CARow ;CH = Row
MOV BL,CACol ;BL = Column
CALL CalcOffset ;Call routine to calculate offset
INC DI ;Skip character
CLD ;Set direction to forward
MOV CX,CANumber ;CX = Number to change
JCXZ CAExit ;If zero, exit
MOV AL,CAAttr ;AL = Attribute
CMP WaitForRetrace,1 ;Get wait state
JNE CANoWait ;If WaitForRetrace is False
; use CANoWait routine
MOV AH,AL ;Store attribute in AH
MOV DX,03DAh ;Point DX to CGA status port
CAGetNext:
CLI ;No interrupts now
CAWaitNoH:
IN AL,DX ;Get 6845 status
TEST AL,8 ;Check for vert. retrace
JNZ CAGo ;In progress? Go
RCR AL,1 ;Wait for end of horizontal
JC CAWaitNoH ; retrace
CAWaitH:
IN AL,DX ;Get 6845 status again
RCR AL,1 ;Wait for horizontal
JNC CAWaitH ; retrace
CAGo:
MOV AL,AH ;Move Attr back to AL...
STOSB ; and then to screen
STI ;Allow interrupts
INC DI ;Skip characters
LOOP CAGetNext ;Look for next opportunity
JMP CAExit ;Done
CANoWait:
STOSB ;Change the attribute
INC DI ;Skip characters
LOOP CANoWait ;Get next character
CAExit: ;Next instruction
MOV SP,BP ;Restore SP
POP BP ;Restore BP
RET 8 ;Remove parameters and return

ChangeAttribute ENDP

;****************************************************** MoveFromScreen

;procedure MoveFromScreen(var Source, Dest; Length : Word);
;Move Length words from Source (video memory) to Dest without snow

;equates for parameters:
MFLength EQU WORD PTR [BP+6]
MFDest EQU DWORD PTR [BP+8]
MFSource EQU DWORD PTR [BP+12]

MoveFromScreen PROC FAR

PUSH BP ;Save BP
MOV BP,SP ;Set up stack frame
MOV BX,DS ;Save DS in BX
MOV AL,WaitForRetrace ;Grab before changing DS
LES DI,MFDest ;ES:DI points to Dest
LDS SI,MFSource ;DS:SI points to Source
MOV CX,MFLength ;CX = Length
CLD ;Set direction to forward
RCR AL,1 ;Check WaitForRetrace
JNC MFNoWait ;False? Use MFNoWait routine
MOV DX,03DAh ;Point DX to CGA status port
MFNext:
CLI ;No interrupts now
MFWaitNoH:
IN AL,DX ;Get 6845 status
TEST AL,8 ;Check for vertical retrace
JNZ MFGo ;In progress? go
RCR AL,1 ;Wait for end of horizontal
JC MFWaitNoH ; retrace
MFWaitH:
IN AL,DX ;Get 6845 status again
RCR AL,1 ;Wait for horizontal
JNC MFWaitH ; retrace
MFGo:
LODSW ;Load next video word into AX
STI ;Allow interrupts
STOSW ;Store video word in Dest
LOOP MFNext ;Get next video word
JMP MFExit ;All Done
MFNoWait:
REP MOVSW ;That's it!
MFExit:
MOV DS,BX ;Restore DS
MOV SP,BP ;Restore SP
POP BP ;Restore BP
RET 10 ;Remove parameters and return

MoveFromScreen ENDP

;****************************************************** MoveToScreen

;procedure MoveToScreen(var Source, Dest; Length : Word);
;Move Length words from Source to Dest (video memory) without snow

;equates for parameters:
MTLength EQU WORD PTR [BP+6]
MTDest EQU DWORD PTR [BP+8]
MTSource EQU DWORD PTR [BP+12]

MoveToScreen PROC FAR

PUSH BP ;Save BP
MOV BP,SP ;Set up stack frame
PUSH DS ;Save DS
MOV AL,WaitForRetrace ;Grab before changing DS
LES DI,MTDest ;ES:DI points to Dest
LDS SI,MTSource ;DS:SI points to Source
MOV CX,MTLength ;CX = Length
CLD ;Set direction to forward
RCR AL,1 ;Check WaitForRetrace
JNC MTNoWait ;False? Use MTNoWait routine
MOV DX,03DAh ;Point DX to CGA status port
MTGetNext:
LODSW ;Load next video word into AX
MOV BX,AX ;Store video word in BX
CLI ;No interrupts now
MTWaitNoH:
IN AL,DX ;Get 6845 status
TEST AL,8 ;Check for vertical retrace
JNZ MTGo ;In progress? Go
RCR AL,1 ;Wait for end of horizontal
JC MTWaitNoH ; retrace
MTWaitH:
IN AL,DX ;Get 6845 status again
RCR AL,1 ;Wait for horizontal
JNC MTWaitH ; retrace
MTGo:
MOV AX,BX ;Move word back to AX...
STOSW ; and then to screen
STI ;Allow interrupts
LOOP MTGetNext ;Get next video word
JMP MTExit ;All done
MTNoWait:
REP MOVSW ;That's all!
MTExit:
POP DS ;Restore DS
MOV SP,BP ;Restore SP
POP BP ;Restore BP
RET 10 ;Remove parameters and return


MoveToScreen ENDP

;****************************************************** CurrentModePrim

;Returns current video mode in AL

CurrentModePrim PROC NEAR

MOV AH,0Fh ;Get video mode function
INT 10h ;Call BIOS
MOV CurrentMode,AL ;Save it
RET ;Return

CurrentModePrim ENDP

;****************************************************** CurrentDisplay

;function CurrentDisplay : DisplayType;
;Returns type of the currently active display.

JunkValue = 0FFFFh

CurrentDisplay PROC FAR

;get the current video mode
CALL CurrentModePrim ;Call primitive routine

;test for VGA
MOV Display,VGA ;Assume VGA
MOV CX,JunkValue ;Load CX with junk value
MOV AX,1C00h ;Save/Restore video state
INT 10h
CMP AL,1Ch ;AL = $1C signals valid call
JE CDexit ;Adapter type known

;test for MCGA
MOV Display,MCGA ;Assume MCGA
MOV BL,32h ;Choose Enable
MOV AX,1200h ;Enable/Disable video addressing
INT 10h
CMP AL,12h ;AL = $12 signals valid call
JE CDexit ;Adapter type known

;test for EGA
MOV Display,EGA ;Assume EGA
MOV BX,0FF10h ;Return EGA information
MOV CX,JunkValue ;Load CX with junk value
MOV AX,1200h ;Alternate function select
INT 10h
XOR AL,AL ;AL = 0
CMP CX,JunkValue ;CX unchanged?
JE CDplain ;If so, not an EGA
CMP BH,1 ;BH should be 0 or 1
JA CDplain ;Mono or CGA if it isn't

;See if EGA is the active display
CMP BH,1 ;mono display?
JE CDegaMono ;If so, use mono check
CMP CurrentMode,7 ;In mono mode?
JE CDplain ;If so, we're not on the EGA
JMP SHORT CDexit ;else, it's an EGA

CDegaMono:
CMP CurrentMode,7 ;Current mode = 7?
JNE CDplain ;Exit if not

CDexit:
MOV AL,Display ;set return value
RET ;Return

CDplain:
MOV Display,CGA ;Assume CGA
CMP CurrentMode,7 ;Mono mode
JNE CDexit ;Done if not
MOV Display,Mono ;Else, Mono
JMP SHORT CDexit ;Done

CurrentDisplay ENDP

;****************************************************** CurrentVideoMode

;function CurrentVideoMode : Byte;
;Returns current video mode in AL

CurrentVideoMode PROC FAR

CALL CurrentModePrim ;Call primitive routine
RET ;Return

CurrentVideoMode ENDP

CODE ENDS

END


  3 Responses to “Category : Pascal Source Code
Archive   : FASTWR.ZIP
Filename : FASTWR.ASM

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/