Category : Forth Source Code
Archive   : SMILY46H.ZIP
Filename : VGA64LIN.SEQ

 
Output of file : VGA64LIN.SEQ contained in archive : SMILY46H.ZIP
\ vga640.seq contains code for lines in ega/vga mode $10 - Mike Sperl
\ 10/9/89 - requires some words that are in grafkrnl.seq
/*
ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ Direct screen writing by M. P. Sperl, M.D., 2/24/89 ³
³ Modified 10/9/89 - mps ³
³ These words write directly to the screen rather than ³
³ calling int 16 (BIOS), so they are faster. ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
*/

\ Thanks to Mike, we fixed a VEGA dot and line bug by adding
\ BYTES/ROW to words in GRAFKRNL.SEQ and VGA64LIN.SEQ. 21Nov89mds

assembler inlineon \ speeds up assembler words
ONLY FORTH ALSO GRAPHICS ALSO

headerless

VARIABLE X1
VARIABLE Y1
VARIABLE X2
VARIABLE Y2

create mask1[]
$ff c, $7f c, $3f c, $1f c, $0f c, 7 c, 3 c, 1 c,

create mask2[]
$80 c, $c0 c, $e0 c, $f0 c, $f8 c, $fc c, $fe c, $ff c,

CREATE LTBL 6 ALLOT
\ Array for variables, usage by line: (see below for usage by hline)
\ ltbl+0 = delta x, ltbl+2 = delta y, ltbl+4 = (halfx or halfy)

\ y changing faster than x
code steep640 \ on entry, ax = delta y, bx = delta x, cx=x1, dx=y1
mov bp, ax \ for counter
shr ax, # 1
mov ltbl 4 + ax \ halfy
xor bx, bx \ clear for cmp
push es \ save forth
mov ax, # $a000 \ ' vid.seg >body #)
mov es, ax \ direct to crt
begin
push bx push cx push dx
xchg cx, dx \ cx = row, dx = col (for rotate)
xor bx, bx \ starting offset = 0
push dx
\ mov ax, # 80 \ bytes/row
mov ax, bytes/row \ bytes/row \ 112089mds
cwd
mul cx \ = bytes to our row
add bx, ax \ = offset in buffer
pop dx
mov cx, dx \ cx = col (x)
shr dx, # 1 \ divide by 4
shr dx, # 1 \ (pixels/byte in med)
shr dx, # 1 \ div by 8 for high, ega, vga
add bx, dx \ = offset in segment
\ write direct to screen (write mode 2) for EGA/VGA
mov dx, # $3ce \ -> addr reg
mov ax, # $108 \ -> bit mask reg
not cl \ = 255 - cl(x), like 8 mod
and cl, # 7 \ = 0 to 7 (remainder)
rol ah, cl \ position to our bit
out dx, ax \ mask to data reg
mov al, color \ in ega color = 0 - 15
or es: 0 [bx], al \ write pixel
pop dx pop cx pop bx
add dx, si \ inc or dec y
add bx, ltbl \ = bx + delta x
cmp bx, ltbl 4 + \ bx > halfy ?
> if
sub bx, ltbl 2 + \ bx - delta y
add cx, di \ inc or dec x
then
dec bp \ count down
< until
pop es
mov dx, # $3ce \ address graphics contrl. regs.
mov ax, # 5 \ mode reg. index, write and read mode 0
out dx, ax
mov ax, # $ff08 \ default bit mask
out dx, ax
mov ax, # 3 \ default function select
out dx, ax
xor ax, ax \ zero set/reset
out dx, ax
inc ax \ zero enable set/reset
out dx, ax
mov dx, # $3c4 \ addr. reg.
mov ax, # $f02 \ data reg., enable all planes
pop bp pop si \ pushed by caller
next end-code

headers

\ on exit, cx=x1, dx=y1, bx=x2, ax=y2
code line640 ( x1 y1 x2 y2 -- ) \ writes to screen directly
mov dx, # $3ce \ address graphics contrl. regs.
mov ax, # $0f01 \ al = enable set/res. reg. index = 1
out dx, ax \ ah = all 8 bits on, written to $3cf
xor ax, ax \ al = set/reset reg. index = 0
mov ah, color \ send color to vga
out dx, ax
pop ax \ mov y2 ax \ save start, end points for
pop bx \ mov x2 bx \ nline and pline
pop dx \ mov y1 dx \ can remove these moves if
pop cx \ mov x1 cx \ program only calls line
push si ( used to hold direction)
push bp ( used as counter)
\ see if we'll inc or dec x, y (draws in any direction)
xor si, si \ 0 for horizontal line
mov di, si \ 0 for vertical lines
sub ax, dx \ ax <- y2-y1 (delta y)
> if inc si then \ si to increment y
< if dec si \ si to decrement y
neg ax \ abs(delta y)
then \ ax = delta y, dx = x2
mov ltbl 2 + ax \ delta y to 2 + ltbl
sub bx, cx \ x2 - x1 = delta x
> if inc di then \ di to increment x
< if dec di \ di to decrement x
neg bx \ abs(delta x)
then
mov ltbl bx \ 0 + ltbl = abs(delta x)
cmp bx, ax \ delta x - delta y
< if jmp ' steep640 \ y changes faster than x
then
\ x changing faster than y
mov bp, bx \ for counter
shr bx, # 1
mov ltbl 4 + bx \ halfx
xor bx, bx \ clear for cmp
push es \ save forth
mov ax, # $a000 \ ' vid.seg >body #)
mov es, ax \ direct to crt
begin
push bx push cx push dx
xchg cx, dx \ cx = row, dx = col (for rotate)
xor bx, bx \ starting offset = 0
push dx
\ mov ax, # 80 \ bytes/row
mov ax, bytes/row \ bytes/row \ 112089mds
cwd
mul cx \ = bytes to our row
add bx, ax \ = offset in buffer
pop dx
mov cx, dx \ cx = col (x)
shr dx, # 1 \ divide by 4
shr dx, # 1 \ (pixels/byte in med)
shr dx, # 1 \ div by 8 for high, ega, vga
add bx, dx \ = offset in segment
\ write direct to screen (write mode 2) for EGA/VGA
mov dx, # $3ce \ -> addr reg
mov ax, # $108 \ -> bit mask reg
not cl \ = 255 - cl(x), like 8 mod
and cl, # 7 \ = 0 to 7 (remainder)
rol ah, cl \ position to our bit
out dx, ax \ mask to data reg
mov al, color \ in ega color = 0 - 15
or es: 0 [bx], al \ write pixel
pop dx pop cx pop bx
add cx, di \ inc or dec x
add bx, ltbl 2 + \ = bx + delta y
cmp bx, ltbl 4 + \ bx > halfx ?
> if
sub bx, ltbl \ bx - delta x
add dx, si \ inc or dec y
then
dec bp \ count down
< until
pop es
mov dx, # $3ce \ address graphics contrl. regs.
mov ax, # 5 \ mode reg. index, write and read mode 0
out dx, ax
mov ax, # $ff08 \ default bit mask
out dx, ax
mov ax, # 3 \ default function select
out dx, ax
xor ax, ax \ zero set/reset
out dx, ax
inc ax \ zero enable set/reset
out dx, ax
mov dx, # $3c4 \ addr. reg.
mov ax, # $f02 \ data reg., enable all planes
pop bp pop si \ pushed by caller
next end-code

\ y changing faster than x
code xsteep640 \ on entry, ax = delta y, bx = delta x, cx=x1, dx=y1
mov bp, ax \ for counter
shr ax, # 1
mov ltbl 4 + ax \ halfy
xor bx, bx \ clear for cmp
push es \ save forth
mov ax, # $a000 \ ' vid.seg >body #)
mov es, ax \ direct to crt
begin
push bx push cx push dx
xchg cx, dx \ cx = row, dx = col (for rotate)
xor bx, bx \ starting offset = 0
push dx
\ mov ax, # 80 \ bytes/row
mov ax, bytes/row \ bytes/row \ 112089mds
cwd
mul cx \ = bytes to our row
add bx, ax \ = offset in buffer
pop dx \ dx=y
mov cx, dx \ cx = col (x)
shr dx, # 1 \ divide by 4
shr dx, # 1 \ (pixels/byte in med)
shr dx, # 1 \ div by 8 for high, ega, vga
add bx, dx \ = offset in segment
\ write direct to screen (write mode 0) for EGA/VGA
mov dx, # $3ce \ address graphics ctrl. regs.
not cl \ = 255 - cl
and cl, # 7 \ = 0 to 7
mov ax, # $108 \ bit mask reg. = 8
rol ah, cl \ position our bit
out dx, ax
mov ax, # $1803 \ send XOR to data rot. reg.
out dx, ax
mov ax, color \ in ega color = 0 - 15
xchg ah, al \ al = 0 = set/reset reg.
out dx, ax
mov ax, # $0f01 \ al = enable set/res. reg. index = 1
out dx, ax \ ah = all bit planes enabled
or es: 0 [bx], al \ write pixel
pop dx pop cx pop bx
add dx, si \ inc or dec y
add bx, ltbl \ = bx + delta x
cmp bx, ltbl 4 + \ bx > halfy ?
> if
sub bx, ltbl 2 + \ bx - delta y
add cx, di \ inc or dec x
then
dec bp \ count down
< until
pop es
mov dx, # $3ce \ address graphics contrl. regs.
mov ax, # 5 \ mode reg. index, write and read mode 0
out dx, ax
mov ax, # $ff08 \ default bit mask
out dx, ax
mov ax, # 3 \ default function select
out dx, ax
xor ax, ax \ zero set/reset
out dx, ax
inc ax \ zero enable set/reset
out dx, ax
mov dx, # $3c4 \ addr. reg.
mov ax, # $f02 \ data reg., enable all planes
pop bp pop si \ pushed by caller
next end-code

headers

\ on exit, cx=x1, dx=y1, bx=x2, ax=y2
code xline640 ( x1 y1 x2 y2 -- ) \ writes to screen directly
pop ax \ mov y2 ax \ save start, end points for
pop bx \ mov x2 bx \ nline and pline
pop dx \ mov y1 dx \ can remove these moves if
pop cx \ mov x1 cx \ program only calls line
push si ( used to hold direction)
push bp ( used as counter)
\ see if we'll inc or dec x, y (draws in any direction)
xor si, si \ 0 for horizontal line
mov di, si \ 0 for vertical lines
sub ax, dx \ ax <- y2-y1 (delta y)
> if inc si then \ si to increment y
< if dec si \ si to decrement y
neg ax \ abs(delta y)
then \ ax = delta y, dx = x2
mov ltbl 2 + ax \ delta y to 2 + ltbl
sub bx, cx \ x2 - x1 = delta x
> if inc di then \ di to increment x
< if dec di \ di to decrement x
neg bx \ abs(delta x)
then
mov ltbl bx \ 0 + ltbl = abs(delta x)
cmp bx, ax \ delta x - delta y
< if jmp ' xsteep640 \ y changes faster than x
then
\ x changing faster than y
mov bp, bx \ for counter
shr bx, # 1
mov ltbl 4 + bx \ halfx
xor bx, bx \ clear for cmp
push es \ save forth
mov ax, # $a000 \ ' vid.seg >body #)
mov es, ax \ direct to crt
begin
push bx push cx push dx

xchg cx, dx \ cx = row, dx = col (for rotate)
xor bx, bx \ starting offset = 0
push dx
\ mov ax, # 80 \ bytes/row
mov ax, bytes/row \ bytes/row \ 112089mds
cwd
mul cx \ = bytes to our row
add bx, ax \ = offset in buffer
pop dx
mov cx, dx \ cx = col (x)
shr dx, # 1 \ divide by 4
shr dx, # 1 \ (pixels/byte in med)
shr dx, # 1 \ div by 8 for high, ega, vga
add bx, dx \ = offset in segment
\ write direct to screen (write mode 0) for EGA/VGA
mov dx, # $3ce \ address graphics ctrl. regs.
not cl \ = 255 - cl
and cl, # 7 \ = 0 to 7
mov ax, # $108 \ bit mask reg. = 8
rol ah, cl \ position our bit
out dx, ax
mov ax, # $1803 \ send XOR to data rot. reg.
out dx, ax
mov ax, color \ in ega color = 0 - 15
xchg ah, al \ al = 0 = set/reset reg.
out dx, ax
mov ax, # $0f01 \ al = enable set/res. reg. index = 1
out dx, ax \ ah = all bit planes enabled
or es: 0 [bx], al \ write pixel
pop dx pop cx pop bx
add cx, di \ inc or dec x
add bx, ltbl 2 + \ = bx + delta y
cmp bx, ltbl 4 + \ bx > halfx ?
> if
sub bx, ltbl \ bx - delta x
add dx, si \ inc or dec y
then
dec bp \ count down
< until
pop es
mov dx, # $3ce \ address graphics contrl. regs.
mov ax, # 5 \ mode reg. index, write and read mode 0
out dx, ax
mov ax, # $ff08 \ default bit mask
out dx, ax
mov ax, # 3 \ default function select
out dx, ax
xor ax, ax \ zero set/reset
out dx, ax
inc ax \ zero enable set/reset
out dx, ax
mov dx, # $3c4 \ addr. reg.
mov ax, # $f02 \ data reg., enable all planes
pop bp pop si \ pushed by caller
next end-code

label fin0
mov dx, # $3ce \ addr reg
mov ax, # $ff08 \ enable set/reset reg., all planes
out dx, ax
mov ax, # $101 \ mask reg. index
out dx, ax
mov ax, # 3 \ default function select
out dx, ax
xor ax, ax \ zero set/reset
out dx, ax
inc ax \ zero enable set/reset
out dx, ax
mov dx, # $3c4 \ load map mask reg
mov ax, # $f02 \ mask reg. index, ah = all planes
out dx, ax
next c;

label ega.hlin2 \ EGA/VGA case for two byte line
mov bx, es \ save forth
mov ax, # $a000 \ ' vid.seg >body #)
mov es, ax \ direct to crt
mov dx, # $03ce
mov ah, ltbl 4 +
mov al, # 8
out dx, ax
or es: 0 [di], al
mov al, ltbl 5 +
inc dx
out dx, al
inc di
or es: 0 [di], al
mov es, bx
jmp fin0
c;

label ega.hlin1 \ line with all pels in one byte
mov bx, es \ save forth
mov ax, # $a000 \ ' vid.seg >body #)
mov es, ax \ direct to crt
mov ah, ltbl 4 +
mov al, ltbl 5 +
and ah, al
mov al, # 8
mov dx, # $03ce
out dx, ax
or es: 0 [di], al
mov es, bx
jmp fin0
c;

headers

\ Draw a horizontal line in modes CGA 640x200, EGA, VGA 640x480
\ write mode 0 direct to screen
\ 8 pixels simultaneously for speed
code hline640 ( x1 x2 y )
mov dx, # $3ce \ addr reg
mov ax, # $0f01 \ mask reg. index
out dx, ax
mov al, # 0 \ data reg.
mov ah, color
out dx, ax \ load set/reset reg. w/ color, write mode 0
pop dx
\ mov y1 dx \ for compatability with nline
\ mov y2 dx \ for compatability with nline
pop bx pop ax
cmp bx, ax
0< if xchg bx, ax then \ draw left to right
mov x2 bx
mov x1 ax
mov cx, # 3
shr ax, cl \ pels/8 = bytes
shr bx, cl
sub bx, ax
mov ltbl 2 + bx \ length in bytes
dec bx
mov ltbl bx \ no. of bytes between ends
mov bx, ax
mov di, # 0
\ mov ax, # 80 \ bytes/row
mov ax, bytes/row \ bytes/row \ 112089mds
mov cx, dx
cwd
mul cx
add ax, bx
add di, ax \ address in di
mov ax, x1
cwd
mov cx, # 8 \ x1 mod 8
div cx
mov bx, dx \ pels in 1st byte
mov al, mask1[] [bx] \ table look-up byte mask
mov ltbl 4 + al
mov ax, x2
cwd
div cx \ x2 mod 8
mov bx, dx \ pels in last byte
mov al, mask2[] [bx]
mov ltbl 5 + al
mov ax, ltbl 2 + \ number of bytes - 1
cmp ax, # 1
0< if jmp ega.hlin1 then
0= if jmp ega.hlin2 then
mov bx, es \ save forth
mov ax, # $a000 \ ' vid.seg >body #)
mov es, ax \ direct to crt
mov dx, # $03ce
mov ah, ltbl 4 + \ mask for 1st byte
mov al, # 8
out dx, ax
or es: 0 [di], al
mov al, # $ff \ mask for middle bytes
inc dx
out dx, al
mov cx, ltbl \ no. of bytes between
here
inc di
or es: 0 [di], al
loop
mov al, ltbl 5 + \ mask for last byte
out dx, al
inc di
or es: 0 [di], al
mov es, bx
jmp fin0
c;

headerless

label ega.xhlin2 \ EGA/VGA case for two byte line
mov bx, es \ save forth
mov ax, # $a000 \ ' vid.seg >body #)
mov es, ax \ direct to crt
mov dx, # $03ce
mov ah, ltbl 4 +
mov al, # 8
out dx, ax
or es: 0 [di], al
mov al, ltbl 5 +
inc dx
out dx, al
inc di
\ or es: 0 [di], al
xor es: 0 [di], al \ mds
mov es, bx
jmp fin0
c;

label ega.xhlin1 \ line with all pels in one byte
mov bx, es \ save forth
mov ax, # $a000 \ ' vid.seg >body #)
mov es, ax \ direct to crt
mov dx, # $03ce
mov ah, ltbl 4 +
mov al, ltbl 5 +
and ah, al
mov al, # 8
out dx, ax
\ or es: 0 [di], al
xor es: 0 [di], al \ mds
mov es, bx
jmp fin0
c;

headers

\ Draw a horizontal line in modes CGA 640x200, EGA, VGA 640x480
\ write mode 0 direct to screen
\ 8 pixels simultaneously for speed
code xhline640 ( x1 x2 y )
mov dx, # $3ce \ addr reg
mov ax, # $1803 \ send XOR to data rot. reg.
out dx, ax
mov al, # 0 \ data reg.
mov ah, color
out dx, ax \ load set/reset reg. w/ color, write mode 0
mov ax, # $0f01 \ al = enable set/res. reg. index = 1
out dx, ax \ ah = all bit planes enabled
pop dx
\ mov y1 dx \ for compatability with nline
\ mov y2 dx \ for compatability with nline
pop bx pop ax
cmp bx, ax
0< if xchg bx, ax then \ draw left to right
mov x2 bx
mov x1 ax
shr ax, 1
shr ax, 1
shr ax, 1
shr bx, 1
shr bx, 1
shr bx, 1
sub bx, ax
mov ltbl 2 + bx \ length in bytes
dec bx
mov ltbl bx \ no. of bytes between ends
mov bx, ax
\ mov ax, # 80 \ bytes/row
mov ax, bytes/row \ bytes/row \ 112089mds
mov cx, dx
cwd
mul cx
add ax, bx
mov di, ax \ address in di
mov ax, x1
cwd
mov cx, # 8 \ x1 mod 8
div cx
mov bx, dx \ pels in 1st byte
mov al, mask1[] [bx] \ table look-up byte mask
mov ltbl 4 + al
mov ax, x2
cwd
div cx \ x2 mod 8
mov bx, dx \ pels in last byte
mov al, mask2[] [bx]
mov ltbl 5 + al
mov ax, ltbl 2 + \ number of bytes - 1
cmp ax, # 1
0< if jmp ega.xhlin1 then
0= if jmp ega.xhlin2 then
mov bx, es \ save forth
mov ax, # $a000 \ ' vid.seg >body #)
mov es, ax \ direct to crt
mov dx, # $03ce
mov ah, ltbl 4 + \ mask for 1st byte
mov al, # 8
out dx, ax \ ah = all bit planes enabled
or es: 0 [di], al
\ xor es: 0 [di], al \ mds
mov ax, # $ff08 \ $ff=mask for middle bytes
out dx, AX \ was: out dx, AL
mov cx, ltbl \ no. of bytes between
here
inc di
\ or es: 0 [di], al
xor es: 0 [di], al \ mds
loop
inc di
mov al, # 8
mov ah, ltbl 5 + \ mask for last byte
out dx, ax
\ or es: 0 [di], al
xor es: 0 [di], al \ mds
mov es, bx
jmp fin0
c;

assembler inlineoff



  3 Responses to “Category : Forth Source Code
Archive   : SMILY46H.ZIP
Filename : VGA64LIN.SEQ

  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/