Greetings and welcome to the 1st issue of LOADER CLASS 101.  Your teacher
for the class is the "VGA KING" Sauron.  I am assuming that you have a
general knowledge of assembly for this. If not, pick up an assembly book to
help you learn the basics and then this will make more sense.  I am using
turbo assembler V2.0 for all these examples but Microsoft's Assmbler should
work just as well.  In this 1st issue, I am covering:

- Displaying a VGA 320x200x256c picture
- Pallete Scrolling
- Fading Techniques

Included with this .ZIP is a few utilities to help you.  They are:

INTRO  .EXE  - Re-orders the BMP so it is easier to use
CUT    .EXE  - This cuts the end off any file.
GIF2BMP.EXE  - Used by INTRO.EXE to convert a 320x200x256c gif to BMP.

The other files in this .ZIP are:

SAURON .NFO  - This file.
HUMBLE .ASM  - The source code for the example.
PICTURE.DAT  - The example picture converted with INTRO.EXE
PICTURE.GIF  - The example GIF
B      .BAT  - The file you run to compile the example (note, you must have
TASM and TLINK in your path)
256    .DAT  - 256 0's used in the stack.

Lets first concentrate on displaying a 320x200x256c picture.  The 1st thing
you must do is create/find a GIF.  Then use the program INTRO.EXE to convert
the GIF to a BMP in useable format. If you are having problems running this
program, make sure your COMSPEC is set pointing to your command.com.
For Example, something like this should be in your autoexec.bat file:
COMSPEC=C:\command.com
I have knowticed that this program doesn't work on GIFLITED GIF's.
Now, you should have a .DAT file that is 64768 bytes long.  The 1st 768
bytes are the pallete.  The next 64000 is the picture starting from the top
left to the bottom right.
Here's a Skeleton for displaying a picture along with comments:

DOSSEG                           ; so we can use the CUT procedure

picture segment byte public 'DATA'
pal      db     768 dup (0)      ; the pallete of this picture (256*3)
pic      db   64000 dup (0)      ; The actual picture.  (320*200)
picture ends

stacks  segment byte stack 'STACK'
thestak  db   256 dup (0)        ; the STACK used by the microprocessor
stacks  ends

code    segment byte public 'code'
assume  cs:code, ss:stacks

MAIN:   mov     ax,0013h           ; sets screen to 320x200x256c
int     10h                ; sets screen to 320x200x256c when ax =13h

mov     ax,picture         ;BEGIN setup pallete
mov     es,ax
mov     dx,offset pal
mov     ax,1012h
mov	bx,0
mov     cx,256
int     10h                ;END   setup pallete

mov     ax,picture         ;BEGIN copy picture to vga card.
mov     ds,ax
mov     ax,0a000h
mov     es,ax
mov     di,0
mov     si,offset pic
mov     cx,64000/2
rep     movsw              ;END   copy picture to vga card.

HERE:	mov	ah,1               ;poll keyboard for a key
int	16h                ;poll keyboard for a key when ah = 1
jz	HERE               ;if no key then Jump to HERE
mov	ah,0               ;clear keyboard buffer
int	16h                ;clear keyboard buffer when ah=0

mov     ax,0003            ; sets screen to TEXT 80x25
int     10h                ; sets screen to TEXT 80x25 when ax = 3
mov     ax,4c00h           ; program EXIT
int     21h                ; program EXIT when ax = 4c00h

code    ends
end     MAIN

You may cut this out and make a .ASM file out of it.

This program uses 3 segments (CODE,PICTURE,STACKS (in that order)).  Most of
this program should make sense to you but I will explain 2 sections a little
more.
1)  The Pallete Section.  This is a BIOS call which sets up the pallete.
To call this BIOS call, you must setup AX with 1012h and call INT 10h.
There are 256 colors and for each color there is 3 HUE's.  (R)ed,
(G)reen, and (B)lue.  That means 256*3=768 bytes of data must be set
for 256 colors.
Before calling this BIOS call, you must set up BX,CX,DX and ES.
ES - To be loaded with the SEGMENT which your pallete data is in.
Just move PICTURE into AX and then AX into ES.  You cannot do
this: MOV ES,picture.  So you must go about it this way.
BX - The 1st color to set (0-255). Since we are setting all 256 colors,
set this # to 0.
CX - The # of colors to set.
DX - The starting area for the pallete.
2)  The moving the picture to the vga card (0a000h).  There is 64k setup
at 0a000h for a 320x200 picture.  For speed, the command REP MOVSW is
being used.  This will move 2 bytes at a time from DS:SI to ES:DI.

Now to compile all this.  I have created a batch file called B.BAT which
will help speed things up ALOT.  Here is the batch file and an explanation
of what it does.

tasm sauron                                   ; runs tasm on sauron.asm
tlink sauron                                  ; runs tlink on sauron.obj

cut sauron.exe 65024                          ; cuts 65024 off the end of the
; sauron.exe  64768  (picture)
;            +  256  (stack)
;            =65024
copy /b sauron.exe+PICTURE.DAT+256.dat sauron.exe     ; puts it all together.
; /b is to make a BINARY copy.
sauron                                        ; runs SAURON.EXE

Pretty easy huh?  Now lets try some pallete cycling and fading techniques
without using BIOS calls.  If you want to know what color to start the
pallete cycling, use your favorite paint program (I use autodesk animator
pro) to find the starting pallete color # and the ending pallete #.

There are a few changes to the previous example to achieve this.  Here is
the finished program along with comments on the new code.

dosseg

data    segment byte public 'data'
credits       db      "LOADER CLASS 101",13,10
db      "Taught By - Sauron THG F/X Prez$"

palbegin      db      221                  ;
palbegincx    dw      221*3
palcx         dw      20*3

paltmp3       db      3 dup (0)
paltmp        db      256*3 dup (0)

paltmp2       db      256*3 dup (0)
fadepoint     db      64
fadepoint2    db      64
data    ends

picture segment byte public 'data'
pal           db        768 dup (0)
pic           db      64000 dup (0)
picture ends

stacks  segment byte stack 'stack'
thestak 	db      256 dup (0h)
stacks  ends

code    segment byte public 'code'
assume  cs:code, ds:data, ss:stacks
start:  jmp	main

PalleteRotate proc near
mov     ax,data
mov     es,ax
mov	ds,ax

PDN:    mov     cx,[palcx]
mov     di,offset paltmp3           ;to here
mov     si,offset paltmp            ;from here
rep     movsb
mov     cx,3
mov     si,offset paltmp3
rep     movsb

mov     dx,03dah
vr1:    in      al,dx
and     al,08
jz      vr1
mov     al,[palbegin]
mov     dx,03c8h
out     dx,al
inc     dx
mov     cx,[palcx]
mov     si,offset paltmp
pl13:   lodsb
out     dx,al
loop    pl13

ret
PalleteRotate endp

FADEOUT 	proc
mov     ax,data
mov     ds,ax
mov     es,ax

mov     ax,picture
mov     ds,ax
mov     cx,768/2
mov     si,offset pal
mov     di,offset paltmp
rep     movsw
mov     ax,data
mov     ds,ax
mov     es,ax
flp1:   mov     bx,768
flp2:   cmp     paltmp[bx],0
je      fl3
dec     paltmp[bx]
fl3:    dec     bx
jnz     flp2
mov     dx,offset paltmp
mov     ax,1012h
mov	bx,0
mov     cx,256
int     10h
dec     [fadepoint]
jnz     flp1

endfadeout:	ret
FADEOUT	endp

MAIN:   mov     ax,0013h
int     10h

mov     ax,picture      ;BEGIN setup pallete
mov     es,ax
mov	ds,ax
mov     dx,offset pal
mov     ax,1012h
mov	bx,0
mov     cx,256
int     10h             ;END   setup pallete

mov     ax,picture      ;BEGIN copy picture to vga card.
mov     ds,ax
mov     ax,0a000h
mov     es,ax
mov     di,0
mov     si,offset pic
mov     cx,64000/2
rep     movsw           ;END   copy picture to vga card.

mov     ax,data               ;copy pallete to temp for rotating pal
mov     ds,ax
mov     cx,[palcx]
mov     dx,[palbegincx]
mov     ax,picture
mov     ds,ax
mov     ax,data
mov     es,ax
mov     si,offset pal
add     si,dx
mov     di,offset paltmp
rep     movsb                 ;end copy pallete

HERE:   call    PalleteRotate

mov	ah,1
int	16h
jz	HERE
mov	ah,0
int	16h

call    fadeout

mov     ax,0003
int     10h
mov	ax,data
mov	ds,ax
mov     ah,9
mov     dx,offset credits
int     21h
mov     ax,4c00h
int     21h

code    ends
end     start

The 2 major new procedures are PALLETE CYCLING and FADEOUT.  Here they are
in detail.
1)  PALLETE CYCLING.  1st I have it copy just the section of the pallete
that we are going to rotate to a buffer. Now to the actual
palleterotate procedure.  Basically, the 1st section shifts the section
of the pallete DOWN by 1.  Then it takes the 3 bottom bytes and puts
them at the top.  This is to make sure you keep the pallete rotating
and not just shift them all off the bottom.

mov     ax,data
mov     ds,ax
mov     es,ax
mov     cx,[palcx]
mov     di,offset paltmp3           ;to here
mov     si,offset paltmp            ;from here
rep     movsb
mov     cx,3
mov     si,offset paltmp3
rep     movsb

The next section writes directly to the vga card.
Here is what this procedure does:

mov     dx,03dah                ; check for vertical retrace
vr1:    in      al,dx                   ;
and     al,08                   ;
jz      vr1                     ; end checking section

mov     al,[palbegin]
mov     dx,03c8h
out     dx,al
inc     dx
mov     cx,[palcx]
mov     si,offset paltmp
pl13:   lodsb
out     dx,al
loop    pl13

1st, we check for vertical retrace to be sure we don't get "SNOW" on
the screen.  For direct pallete cycling, you must have these registers
setup first:
This will select the starting color to start copying over bytes.
mov     al,[palbegin]       ; # to start cycling colors
mov     dx,03c8h            ; port address
out     dx,al

This will repeat CX # of times to copy all colors into the new pallete.
inc     dx                  ; dx is really now 03c9h
mov     cx,[palcx]          ; # of colors * 3 to set
mov     si,offset paltmp    ; starting offset for colors
pl13:   lodsb                       ; move into al, what is in DS:SI and
; increment SI
out     dx,al               ; output to port 03c9h byte in AL
loop    pl13                ; repeat till cx = 0 and DEC CX

I hope this will help you in programming the VGA card in assembly.  It is now
5:47am in the morning and I am TIRED so the end of this article might not
make too much sense.  From these examples, you can display multiple pictures,
fading in/out, and pallete cycling.  I will try to clear up any question in
the next issue of the Humble Review.  If you have a question, you can contact
me at The Warriors Guild BBS - (708)653-1839.

Next issue, I am going to cover scrollers.

If you use any of this code or this helps you understand VGA programming
please greet me somewhere in your loader.  You don't have to give me credit
for using my code as this is the basics of VGA programming.  HAPPY HACKING!