home *** CD-ROM | disk | FTP | other *** search
- {
- ;
- ; Adapted from Programmer's Guide to PC & PS/2 Video Systems (1-55615-103-9)
- ;
- ; Routine written by Richard Wilton
- ;
- ;
- ; Name: ScreenOrigin
- ;
- ; Function: Set screen origin on EGA and VGA.
- ;
- ; Caller: Pascal:
- ;
- ; ScreenOrigin(x,y : integer);
- ;
- ; x,y (* pixel x,y coordinates *)
- ;
-
- ; Pascal calling convention
-
- ARGx EQU word ptr [bp+8] ; stack frame addressing
- ARGy EQU word ptr [bp+6]
-
- ;
- ; C calling convention
- ;
- ; ARGx EQU word ptr [bp+4]
- ; ARGy EQU word ptr [bp+6]
-
- CRT_MODE EQU 49h ; addresses in video BIOS data area
- ADDR_6845 EQU 63h
- POINTS EQU 85h
- BIOS_FLAGS EQU 89h
-
-
- DGROUP GROUP _DATA
-
-
- _TEXT SEGMENT byte public 'CODE'
- ASSUME cs:_TEXT,ds:DGROUP
-
- PUBLIC ScreenOrigin
- ScreenOrigin PROC far
-
- push bp ; preserve caller registers
- mov bp,sp
- push si
- push di
-
- mov ax,40h
- mov es,ax ; ES -> video BIOS data area
- mov cl,es:[CRT_MODE]
-
- mov ax,ARGx ; AX := pixel x-coordinate
- mov bx,ARGy ; BX := pixel y-coordinate
-
- cmp cl,7
- ja L01 ; jump if graphics mode
-
- je L02 ; jump if monochrome alpha
- test byte ptr es:[BIOS_FLAGS],1
- jnz L02 ; jump if VGA
- jmp short L03
-
- ; setup for graphics modes (8 pixels per byte)
-
- L01:
- mov cx,8 ; CL := 8 (displayed pixels per byte)
- ; CH := 0
- div cl ; AH := bit offset in byte
- ; AL := byte offset in pixel row
- mov cl,ah ; CL := bit offset (for Horiz Pel Pan)
- xor ah,ah
- xchg ax,bx ; AX := Y
- ; BX := byte offset in pixel row
-
- mul word ptr BytesPerRow
- ; AX := byte offset of start of row
- jmp short L05
-
- ; setup for VGA alphanumeric modes and EGA monochrome alphanumeric mode
- ; (9 pixels per byte)
-
- L02: ; routine for alpha modes
- mov cx,9 ; CL := 9 (displayed pixels per byte)
- ; CH := 0
- div cl ; AH := bit offset in byte
- ; AL := byte offset in pixel row
- dec ah ; AH := -1, 0-7
- jns L04 ; jump if bit offset 0-7
- mov ah,8 ; AH := 8
- jmp short L04
-
- ; setup for EGA color alphanumeric modes (8 pixels per byte)
-
- L03:
- mov cx,8 ; CL := 8 (displayed pixels per byte)
- ; CH := 0
- div cl ; AH := bit offset in byte
- ; AL := byte offset in pixel row
- L04:
- mov cl,ah ; CL := value for Horiz Pel Pan reg
- xor ah,ah
- xchg ax,bx ; AX := y
- ; BX := byte offset in row
- div byte ptr es:[POINTS] ; AL := character row
- ; AH := scan line in char matrix
- xchg ah,ch ; AX := character row
- ; CH := scan line (value for Preset
- ; Row Scan register)
- mul word ptr BytesPerRow ; AX := byte offset of char row
- shr ax,1 ; AX := word offset of character row
- L05:
- call SetOrigin
-
- pop di ; restore registers and exit
- pop si
- mov sp,bp
- pop bp
-
- ret 4
-
- ScreenOrigin ENDP
-
- SetOrigin PROC near ; Caller: AX = offset of character row
- ; BX = byte offset within row
- ; CH = Preset Row Scan value
- ; CL = Horizontal Pel Pan value
-
- add bx,ax ; BX := buffer offset
-
- mov dx,es:[ADDR_6845] ; CRTC I/O port (3B4h or 3D4h)
- add dl,6 ; video status port (3BAh or 3DAh)
-
- ; update Start Address High and Low registers
-
- L20:
- in al,dx ; wait for start of vertical retrace
- test al,8
- jz L20
-
- L21:
- in al,dx ; wait for end of vertical retrace
- test al,8
- jnz L21
-
- cli ; disable interrupts
- sub dl,6 ; DX := 3B4h or 3D4h
-
- mov ah,bh ; AH := value for Start Address High
- mov al,0Ch ; AL := Start Address High reg number
- out dx,ax ; update this register
-
- mov ah,bl ; AH := value for Start Address Low
- inc al ; AL := Start Address Low reg number
- out dx,ax ; update this register
- sti ; enable interrupts
-
- add dl,6 ; DX := video status port
- L22:
- in al,dx ; wait for start of vertical retrace
- test al,8
- jz L22
-
- cli ; disable interrupts
-
- sub dl,6 ; DX := 3B4h or 3D4h
- mov ah,ch ; AH := value for Preset Row Scan reg
- mov al,8 ; AL := Preset Row Scan reg number
- out dx,ax ; update this register
-
- mov dl,0C0h ; DX := 3C0h (Attribute Controller
- port)
- mov al,13h OR 20h ; AL bit 0-4 := Horiz Pel Pan reg
- number
- ; AL bit 5 := 1
- out dx,al ; write Attribute Controller Address
- reg
- ; (The Attribute Controller address
- ; flip-flop.)
- mov al,cl ; AL := value for Horiz Pel Pan reg
- out dx,al ; update this register
-
- sti ; enable interrupts
- ret
-
- SetOrigin ENDP
-
- _TEXT ENDS
-
-
- _DATA SEGMENT word public 'DATA'
-
- EXTRN BytesPerRow : word ; bytes per pixel row
-
- _DATA ENDS
-
- END
-
- }
- {$A+,B-,D+,E+,F+,G-,I+,L+,N-,O+,P+,Q+,R+,S+,T-,V+,X+,Y+}
- {$M 65520,0,655360}
-
- (****************************************************************************)
- { }
- { MODULE : SCROLL }
- { }
- { DESCRIPTION : Generic unit for perform smooth scrolling. }
- { }
- { AUTHOR : John M. Beck }
- { }
- { MODIFICATIONS: None }
- { }
- { HISTORY : 29-Dec-1993 Coded. }
- { }
- (****************************************************************************)
-
- unit scroll;
-
- interface
-
- const
- charwidth = 8;
- charheight = 14; { depends on adapter }
-
- var
- screenseg : word;
- bytesperrow : word;
-
- function getvideomode : byte;
-
- procedure smoothscroll;
-
- procedure gotoxy (x,y : byte);
- procedure wherexy(var x,y : byte);
-
- procedure cursoroff;
- procedure setcursor(top,bot : byte);
- procedure getcursor(var top,bot : byte);
-
- procedure clearline(line : word);
- procedure setvideomode(mode : byte);
- procedure panscreen(x0,y0,x1,y1 : integer);
-
- implementation
-
- {$L SCRORG.OBJ}
-
- {
- ;
- ; Name: ScreenOrigin
- ;
- ; Function: Set screen origin on EGA and VGA.
- ;
- ; Caller: Pascal:
- ;
- ; procedure ScreenOrigin(x,y : integer);
- ;
- ; x,y (* pixel x,y coordinates *)
- ;
- }
-
- procedure screenorigin(x,y : integer); external;
-
- function getvideomode : byte; assembler;
- asm
- mov ax,0F00h
- int 10h
- end;
-
- procedure cursoroff; assembler;
- asm
- mov cx,2000h
- mov ah,1
- int 10h
- end;
-
- procedure gotoxy(x,y : byte); assembler;
- asm
- mov ah,2
- xor bx,bx
- mov dl,x
- dec dl
- mov dh,y
- dec dh
- int 10h
- end;
-
- procedure wherexy(var x,y : byte); assembler;
- asm
- mov ax,0300h
- xor bx,bx
- int 10h
- xchg dx,ax
- les di,x
- stosb
- mov al,ah
- les di,y
- stosb
- end;
-
- procedure setvideomode(mode : byte); assembler;
- asm
- mov ah,00
- mov al,mode
- int 10h
- end;
-
- procedure setcursor(top,bot : byte); assembler;
- asm
- mov ax,0100h
- mov ch,top
- mov cl,bot
- int 10h
- end;
-
- procedure getcursor(var top,bot : byte); assembler;
- asm
- mov ax,0300h
- xor bx,bx
- int 10h
- xchg cx,ax
- les di,bot
- stosb
- mov al,ah
- les di,top
- stosb
- end;
-
- procedure clearline(line : word); assembler;
- asm
- mov ax,screenseg { ; AX := screen segment }
- mov es,ax { ; ES := AX }
-
- mov ax,bytesperrow { ; AX := # chars per row * 2 }
- push ax { ; preserve this value }
- mov cx,line { ; CX := Line }
- dec cx { ; CX-- (zero based) }
- mul cx { ; AX := bytesperrow * 25 }
- mov di,ax { ; ES:DI -> 25th line }
- pop cx { ; CX := bytesperrow }
- shr cx,1 { ; CX := CX / 2 (word moves) }
- mov ax,1824 { ; AH := 7 (white on black) }
- { ; AL := 32 (space) }
- rep stosw { ; clear line }
- end;
-
- procedure panscreen(x0,y0,x1,y1 : integer);
- {
- Routine originally in Microsoft C by Richard Wilton
- }
- var
- i,j : integer;
- xinc,
- yinc : integer;
- begin
- i := x0; j := y0;
-
- if (x0 < x1) then
- xinc := 1
- else
- xinc := -1;
-
- if (y0 < y1) then
- yinc := 1
- else
- yinc := -1;
-
- while (i <> x1) or (j <> y1) do
- begin
- if i <> x1 then inc(i,xinc);
- if j <> y1 then inc(j,yinc);
- screenorigin(i,j);
- end;
- end;
-
- procedure smoothscroll;
- {
- Smooth scrolls one line up and puts cursor on bottom line.
- }
- var
- top,bot : byte;
-
- begin
- clearline(26); { blank 26th line }
- panscreen(0,0,0,charheight); { smooth scroll one line down }
- screenorigin(0,0); { restore screen origin }
-
- asm
- push ds { ; preserve data segment }
-
- mov ax,screenseg { ; AX := 0B000h or 0B800 }
-
- mov ds,ax { ; DS := screen segment }
- mov si,160 { ; SI := offset of (0,1) }
- { ; DS:SI -> (0,1) of video buffer }
-
- mov es,ax { ; ES := screen segment }
- xor di,di { ; DI := offset of (0,0) }
-
- mov cx,1920 { ; CX := bytesperrow * 24 / 2 }
-
- rep movsw { ; move screen one line up }
-
- pop ds { ; restore data segment }
- end;
-
- getcursor(top,bot); { save cursor settings }
- clearline(25); { blank new bottom line }
- gotoxy(1,25); { goto last line }
- end;
-
- begin
- if getvideomode = 7 then
- screenseg := $B000
- else
- screenseg := $B800;
-
- bytesperrow := 80*2; { 80 bytes for text and attributes }
- end.
-
- {$A+,B-,D+,E+,F+,G-,I+,L+,N-,O+,P+,Q+,R+,S+,T-,V+,X+,Y+}
- {$M 65520,0,655360}
-
- (****************************************************************************)
- { }
- { PROGRAM : PANTEST }
- { }
- { DESCRIPTION : Tests the scroll unit. }
- { }
- { AUTHOR : John M. Beck }
- { }
- { MODIFICATIONS: None }
- { }
- { HISTORY : 29-Dec-1993 Coded. }
- { }
- (****************************************************************************)
-
- program pantest;
-
- uses crt, scroll;
-
- var
- count : byte;
-
- begin
- clrscr;
- gotoxy(1,1);
- textattr := (black shl 4) or lightgray;
- for count := 1 to 24 do writeln('Hello ',count);
-
- write('Press any key to smooth scroll up one line ... ');
- readkey;
-
- smoothscroll;
-
- write('Press any key to pan demonstration ... ');
- readkey;
-
- clrscr;
- gotoxy(65,25);
- textattr := (black shl 4) or lightgreen;
- write('... Groovy ...');
- panscreen(0,0,65 * charwidth,25 * charheight);
- panscreen(65 * charwidth,25 * charheight,0,0);
- gotoxy(1,25);
- textattr := (black shl 4) or lightblue;
- write('Any key to exit ... ');
- readkey;
- end.
-