Category : Files from Magazines
Archive   : PJ-VGA.ZIP
Filename : SPLITSCN.ASM

 
Output of file : SPLITSCN.ASM contained in archive : PJ-VGA.ZIP
;
; *** Listing 1 ***
;
; Demonstrates the VGA/EGA split screen in action.
;
;*********************************************************************
IS_VGA equ 1 ;set to 0 to assemble for EGA
;
VGA_SEGMENT equ 0a000h
SCREEN_WIDTH equ 640
SCREEN_HEIGHT equ 350
CRTC_INDEX equ 3d4h ;CRT Controller Index register
OVERFLOW equ 7 ;index of Overflow reg in CRTC
MAXIMUM_SCAN_LINE equ 9 ;index of Maximum Scan Line register
; in CRTC
START_ADDRESS_HIGH equ 0ch ;index of Start Address High register
; in CRTC
START_ADDRESS_LOW equ 0dh ;index of Start Address Low register
; in CRTC
LINE_COMPARE equ 18h ;index of Line Compare reg (bits 7-0
; of split screen start scan line)
; in CRTC
INPUT_STATUS_0 equ 3dah ;Input Status 0 register
WORD_OUTS_OK equ 1 ;set to 0 to assemble for
; computers that can't handle
; word outs to indexed VGA registers
;*********************************************************************
; Macro to output a word value to a port.
;
OUT_WORD macro
if WORD_OUTS_OK
out dx,ax
else
out dx,al
inc dx
xchg ah,al
out dx,al
dec dx
xchg ah,al
endif
endm
;*********************************************************************
MyStack segment para stack 'STACK'
db 512 dup (0)
MyStack ends
;*********************************************************************
Data segment
SplitScreenLine dw ? ;line the split screen currently
; starts after
StartAddress dw ? ;display memory offset at which
; scanning for video data starts
; Message displayed in split screen.
SplitScreenMsg db 'Split screen text row #'
DigitInsert dw ?
db '...$'
Data ends
;*********************************************************************
Code segment
assume cs:Code, ds:Data
;*********************************************************************
Start proc near
mov ax,Data
mov ds,ax
;
; Select mode 10h, 640x350 16-color graphics mode.
;
mov ax,0010h ;AH=0 is select mode function
;AL=10h is mode to select,
; 640x350 16-color graphics mode
int 10h
;
; Put text into display memory starting at offset 0, with each row
; labelled as to number. This is the part of memory that will be
; displayed in the split screen portion of the display.
;
mov cx,25 ;# of lines of text we'll draw into
; the split screen part of memory
FillSplitScreenLoop:
mov ah,2 ;set cursor location function #
sub bh,bh ;set cursor in page 0
mov dh,25
sub dh,cl ;calculate row to draw in
sub dl,dl ;start in column 0
int 10h ;set the cursor location
mov al,25
sub al,cl ;calculate row to draw in again
sub ah,ah ;make the value a word for division
mov dh,10
div dh ;split the row # into two digits
add ax,'00' ;convert the digits to ASCII
mov [DigitInsert],ax ;put the digits into the text
; to be displayed
mov ah,9
mov dx,offset SplitScreenMsg
int 21h ;print the text
loop FillSplitScreenLoop
;
; Fill display memory starting at 8000h with a diagonally striped
; pattern.
;
mov ax,VGA_SEGMENT
mov es,ax
mov di,8000h
mov dx,SCREEN_HEIGHT ;fill all lines
mov ax,8888h ;starting fill pattern
cld
RowLoop:
mov cx,SCREEN_WIDTH/8/2 ;fill 1 scan line a word at a time
rep stosw ;fill the scan line
ror ax,1 ;shift pattern word
dec dx
jnz RowLoop
;
; Set the start address to 8000h and display that part of memory.
;
mov [StartAddress],8000h
call SetStartAddress
;
; Slide the split screen half way up the screen and then back down
; a quarter of the screen.
;
mov [SplitScreenLine],SCREEN_HEIGHT-1
;set the initial line just off
; the bottom of the screen
mov cx,SCREEN_HEIGHT/2
call SplitScreenUp
mov cx,SCREEN_HEIGHT/4
call SplitScreenDown
;
; Now move up another half a screen and then back down a quarter.
;
mov cx,SCREEN_HEIGHT/2
call SplitScreenUp
mov cx,SCREEN_HEIGHT/4
call SplitScreenDown
;
; Finally move up to the top of the screen.
;
mov cx,SCREEN_HEIGHT/2-2
call SplitScreenUp
;
; Wait for a key press (don't echo character).
;
mov ah,8 ;DOS console input without echo function
int 21h
;
; Turn the split screen off.
;
mov [SplitScreenLine],0ffffh
call SetSplitScreenScanLine
;
; Wait for a key press (don't echo character).
;
mov ah,8 ;DOS console input without echo function
int 21h
;
; Display the memory at 0 (the same memory the split screen displays).
;
mov [StartAddress],0
call SetStartAddress
;
; Flip between the split screen and the normal screen every 10th
; frame until a key is pressed.
;
FlipLoop:
xor [SplitScreenLine],0ffffh
call SetSplitScreenScanLine
mov cx,10
CountVerticalSyncsLoop:
call WaitForVerticalSyncEnd
loop CountVerticalSyncsLoop
mov ah,0bh ;DOS character available status
int 21h
and al,al ;character available?
jz FlipLoop ;no, toggle split screen on/off status
mov ah,1
int 21h ;clear the character
;
; Return to text mode and DOS.
;
mov ax,0003h ;AH=0 is select mode function
;AL=3 is mode to select, text mode
int 10h ;return to text mode
mov ah,4ch
int 21h ;return to DOS
Start endp
;*********************************************************************
; Waits for the leading edge of the vertical sync pulse.
;
; Input: none
;
; Output: none
;
; Registers altered: AL, DX
;
WaitForVerticalSyncStart proc near
mov dx,INPUT_STATUS_0
WaitNotVerticalSync:
in al,dx
test al,08h
jnz WaitNotVerticalSync
WaitVerticalSync:
in al,dx
test al,08h
jz WaitVerticalSync
ret
WaitForVerticalSyncStart endp
;*********************************************************************
; Waits for the trailing edge of the vertical sync pulse.
;
; Input: none
;
; Output: none
;
; Registers altered: AL, DX
;
WaitForVerticalSyncEnd proc near
mov dx,INPUT_STATUS_0
WaitVerticalSync2:
in al,dx
test al,08h
jz WaitVerticalSync2
WaitNotVerticalSync2:
in al,dx
test al,08h
jnz WaitNotVerticalSync2
ret
WaitForVerticalSyncEnd endp
;*********************************************************************
; Sets the start address to the value specifed by StartAddress.
; Wait for the trailing edge of vertical sync before setting so that
; one half of the address isn't loaded before the start of the frame
; and the other half after, resulting in flicker as one frame is
; displayed with mismatched halves. The new start address won't be
; loaded until the start of the next frame; that is, one full frame
; will be displayed before the new start address takes effect.
;
; Input: none
;
; Output: none
;
; Registers altered: AX, DX
;
SetStartAddress proc near
call WaitForVerticalSyncEnd
mov dx,CRTC_INDEX
mov al,START_ADDRESS_HIGH
mov ah,byte ptr [StartAddress+1]
cli ;make sure both registers get set at once
OUT_WORD
mov al,START_ADDRESS_LOW
mov ah,byte ptr [StartAddress]
OUT_WORD
sti
ret
SetStartAddress endp
;*********************************************************************
; Sets the scan line the split screen starts after to the scan line
; specified by SplitScreenLine.
;
; Input: none
;
; Output: none
;
; All registers preserved
;
SetSplitScreenScanLine proc near
push ax
push cx
push dx
;
; Wait for the leading edge of the vertical sync pulse. This ensures
; that we don't get mismatched portions of the split screen setting
; while setting the two or three split screen registers (register 18h
; set but register 7 not yet set when a match occurs, for example),
; which could produce brief flickering.
;
call WaitForVerticalSyncStart
;
; Set the split screen scan line.
;
mov dx,CRTC_INDEX
mov ah,byte ptr [SplitScreenLine]
mov al,LINE_COMPARE
cli ;make sure all the registers get set at once
OUT_WORD ;set bits 7-0 of the split screen scan line
mov ah,byte ptr [SplitScreenLine+1]
and ah,1
mov cl,4
shl ah,cl ;move bit 8 of the split split screen scan
; line into position for the Overflow reg
mov al,OVERFLOW
if IS_VGA
;
; The Split Screen, Overflow, and Line Compare registers all contain
; part of the split screen start scan line on the VGA. We'll take
; advantage of the readable registers of the VGA to leave other bits
; in the registers we access undisturbed.
;
out dx,al ;set CRTC Index reg to point to Overflow
inc dx ;point to CRTC Data reg
in al,dx ;get the current Overflow reg setting
and al,not 10h ;turn off split screen bit 8
or al,ah ;insert the new split screen bit 8
; (works in any mode)
out dx,al ;set the new split screen bit 8
dec dx ;point to CRTC Index reg
mov ah,byte ptr [SplitScreenLine+1]
and ah,2
mov cl,3
ror ah,cl ;move bit 9 of the split split screen scan
; line into position for the Maximum Scan
; Line register
mov al,MAXIMUM_SCAN_LINE
out dx,al ;set CRTC Index reg to point to Maximum
; Scan Line
inc dx ;point to CRTC Data reg
in al,dx ;get the current Maximum Scan Line setting
and al,not 40h ;turn off split screen bit 9
or al,ah ;insert the new split screen bit 9
; (works in any mode)
out dx,al ;set the new split screen bit 9
else
;
; Only the Split Screen and Overflow registers contain part of the
; Split Screen start scan line and need to be set on the EGA.
; EGA registers are not readable, so we have to set the non-split
; screen bits of the Overflow register to a preset value, in this
; case the value for 350-scan-line modes.
;
or ah,0fh ;insert the new split screen bit 8
; (only works in 350-scan-line EGA modes)
OUT_WORD ;set the new split screen bit 8
endif
sti
pop dx
pop cx
pop ax
ret
SetSplitScreenScanLine endp
;*********************************************************************
; Moves the split screen up the specified number of scan lines.
;
; Input: CX = # of scan lines to move the split screen up by
;
; Output: none
;
; Registers altered: CX
;
SplitScreenUp proc near
SplitScreenUpLoop:
dec [SplitScreenLine]
call SetSplitScreenScanLine
loop SplitScreenUpLoop
ret
SplitScreenUp endp
;*********************************************************************
; Moves the split screen down the specified number of scan lines.
;
; Input: CX = # of scan lines to move the split screen down by
;
; Output: none
;
; Registers altered: CX
;
SplitScreenDown proc near
SplitScreenDownLoop:
inc [SplitScreenLine]
call SetSplitScreenScanLine
loop SplitScreenDownLoop
ret
SplitScreenDown endp
;*********************************************************************
Code ends
end Start


  3 Responses to “Category : Files from Magazines
Archive   : PJ-VGA.ZIP
Filename : SPLITSCN.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/