title graphics : all sort of graphic procedures

extrn scan_code: byte, key_flag: byte, timer_flag: byte

public init_vga, plot_pixel_xy_dbuffer, show_double_buffer, rtn_to_text_mode
public set_palette_register, get_palette_register, pcx_load
public update_color_register, keyboard_int, timer_tick, setup_int
public draw_sprite, pcx_grap_bitmap, get_sprite_background, draw_background

.model compact

include macros.asm


.code

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

init_vga proc near

; purpose : initialize the graphic card to vga mode.
; input   : none. 
; output  : none. 
; method  : put 13h(vga mode) into ax and interrupt video 10h.


push ax

mov ax, @data   ; initialize data segment
mov ds, ax

mov ah, 0       ; initialize the
mov al, 013h    ; graphic card to
int 10h         ; vga mode.

pop ax

ret

init_vga endp


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


plot_pixel_xy_dbuffer proc near

; purpose : draw a dot onto the double_buffer use x and y coordination.
; input   : stack on entry : return address (top), color, y, x, double buffer
;           address.
; output  : none.
; method  : times y by 320, then add x. Take the value and put into
;           memory offset. then put the color into double buffer.


push bp                         ; initialize...
mov bp, sp                      ; put sp value to bp and save bp on the stack.

push ax                         ; save registers
push bx         
push cx
push dx
push si

mov ax, @data                   ; initialize data segment
mov ds, ax

mov bx, word ptr[bp+6]          ; put y into bx;
mov ax, word ptr[bp+6]          ; put another copy of y into ax;
mov cl, 8        
shl bx, cl                      ; shift bx 8 bits left
mov cl, 6       
shl ax, cl                      ; shift ax 6 bits left
add ax, bx                      ; sum ax and bx into ax, than means
                                ; y*256 + y*64 = y*320
add ax, word ptr [bp+8]         ; add x to ax which contains y * 320
mov bx, word ptr [bp+10]        ; move double buffer address into bx
mov cx, word ptr [bp+4]         ; move the color value into cx
mov si, ax                      ; move the offset address to si
                                ; so it can do indirect address
mov word ptr [bx+si], cx        ; finally, we put the color into
                                ; double buffer in x and y coordination.

pop si                          ; restore registers
pop dx
pop cx
pop bx
pop ax

pop bp                          ; restore bp

ret 8                           ; return and pop the 4 parameter into space.

plot_pixel_xy_dbuffer endp


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

show_double_buffer proc near

; purpose : put double_buffer stuff onto the screen
; input   : stack entry: return address (top), buffer address
; output  : none
; method  : use a loop to put the contents in double_buffer to screen_buffer


push bp                 ; initialize...
mov bp, sp              ; put sp value to bp and save bp on the stack.

push ds                 ; save registers
push es
push cx
push ax
push si
push di

mov ax, @data   ; initialize data segment
mov ds, ax

cld

mov ax, 0a000h          ; load screen_buffer segment
mov es, ax
mov di, 0

mov ax, @data
mov ds, ax
mov ax, word ptr [bp+4] ; load double_buffer segment
mov si, ax
mov cx, 32000d          ; we want to mov 320*200 bytes or 320*200/2 words
rep movsw               ; do the movement.


pop di                  ; restore registers
pop si
pop ax
pop cx
pop es
pop dx


pop bp                  ; restore bp

ret 2

show_double_buffer endp


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


rtn_to_text_mode proc near
; purpose : put the screen back to text mode
; input   : none
; output  : none
; method  : put 3 into ax and interrupt video 10h


push ax         ; save register.

mov ax, @data   ; initialize data segment
mov ds, ax

mov ah, 0       ; initialize the              
mov al, 03h     ; graphic card to
int 10h         ; text mode.

pop ax          ; return register.

ret

rtn_to_text_mode endp


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


set_palette_register proc
;purpose : to set the one of palette_register color.
;input   : stack entry : return address (top), index, blue, green, red.
;output  : none.
;method  : use the i/o port to set the palette register instead of calling
;          interrupt. It is much faster.

; palette mask           3c6h
; read palette register  3c7h
; write palette register 3c8h
; palette data           3c9h


push bp                         ; initialize...
mov bp, sp                      ; put sp value to bp and save bp
                                ; on the stack.

push ax                         ; save registers
push dx

mov ax, @data   ; initialize data segment
mov ds, ax


mov dx, 3c6h
mov al, 0ffh
out dx, al                      ; tell the palette_mask a palette register
                                ; will be updated.
mov dx, 3c8h
mov al, byte ptr [bp+4]
out dx, al                      ; put the index into the writing palette
                                ; register
mov dx, 3c9h
mov al, byte ptr [bp+10]
out dx, al                      ; put the red into the data palette
                                ; register
mov al, byte ptr [bp+8]
out dx, al                      ; put the green into the data palette
                                ; register
mov al, byte ptr [bp+6]
out dx, al                      ; put the blue into the data palette
                                ; register

pop dx                          ; restore registers.
pop ax

pop bp                          ; restore bp

ret 8                           ; return and pop the 4 parameter into space.

set_palette_register endp


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


get_palette_register proc
;purpose : to read the one of palette_register color.
;input   : stack entry : return address (top), index, blue, green, red.
;output  : stack contains value in the sequence of index (top), blue,
;          green, red.
;method  : use the i/o port to read the palette register instead of calling
;          interrupt. It is much faster.

; palette mask           3c6h
; read palette register  3c7h
; write palette register 3c8h
; palette data           3c9h

push bp                         ; initialize...
mov bp, sp                      ; put sp value to bp and save bp
                                ; on the stack.

push ax                         ; save registers
push dx

mov ax, @data   ; initialize data segment
mov ds, ax


mov dx, 3c6h
mov al, 0ffh
out dx, al                      ; tell the palette_mask a palette register
                                ; will be updated.
mov dx, 3c7h
mov al, byte ptr [bp+4]
out dx, al                      ; put the index into the writing palette
                                ; register
mov dx, 3c9h
mov al, byte ptr [bp+10]
in  al, dx                      ; put the red into the data palette
                                ; register
mov dx, 3c9h
mov al, byte ptr [bp+8]
in  al, dx                      ; put the green into the data palette
                                ; register
mov dx, 3c9h
mov al, byte ptr [bp+6]
in  al, dx                      ; put the blue into the data palette
                                ; register

pop dx                          ; restore registers.
pop ax

pop bp                          ; restore bp

ret                             ; return to calling program.


get_palette_register endp


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
pcx_load proc
; purpose : to read and uncompress data in pcx file.
; input   : stack entry: return address (top), filename's address, handle,
;           file_buffer's address, data's address, counter, main_counter
; output  : none ( the return parameters on the stack are all pointers. So we
;           don't need to return them. )
; method  : First it open the file and move the read/ write pointers 128 bytes
;           from the beginning.
;           Second it read and uncompress the image.
;           Third it update the color palette in pcx file to the palette
;           register.


push bp                         ; initialize...
mov bp, sp                      ; put sp value to bp and save bp
                                ; on the stack.

push ax                         ; save registers.
push bx
push cx
push ds
push es
push dx


mov ax, @data                   ; initialize ds
mov ds, ax

xor al, al
mov ah, 3dh                     ; open an existing file function number
mov dx, word ptr [bp+4]         ; dx have the file address
mov cl, 0                       ; read_only attribute
int 21h                         ; open the file
mov word ptr [bp+6], ax         ; save handle or error code.

mov ah, 42h                     ; moves read pointer function
mov bx, word ptr [bp+6]         ; get handle
xor cx, cx
mov dx, 128d                    ; 128 bytes to move
mov al, 0                       ; move relative to beginning of file
int 21h                         ; move file pointer


pcx_load_big_while :

mov ax, @data                   ; initialize ds
mov ds, ax
xor al, al
mov ah, 3fh                     ; read file function
mov bx, word ptr [bp+6]         ; get handle
mov cx, 1h                      ; read first byte
mov dx, word ptr [bp+10]        ; load the data address
int 21h                         ; read file into buffer

mov bx, word ptr [bp+10]
cmp byte ptr [bx], 192d         ; compare data to 192
jb next                         ; jump if less than 192
;cmp byte ptr [bx], 255d         ; compare data to 255
;ja next                         ; jump if greater than 255

sub byte ptr [bx], 192d         ; subtract 192 from data
mov al, byte ptr [bx]           ; put data-192 into counter
mov byte ptr [bp+12], al            

xor al, al                      ; clean al
mov ah, 3fh                     ; read file function
mov bx, word ptr [bp+6]         ; get handle
mov cx, 1h                      ; read first byte
mov dx, word ptr [bp+10]        ; load the data address
int 21h                         ; read file into buffer


pcx_load_while :

mov bx, word ptr [bp+10]        ; put data in al so it can be accessed.
mov al, byte ptr [bx]
mov bx, word ptr [bp+8]         ; put al(data) into file buffer.
mov byte ptr [bx], al

inc word ptr [bp+8]             ; increase file buffer pointer
inc word ptr [bp+14]            ; increase main counter
dec byte ptr [bp+12]            ; decrease counter by one

cmp byte ptr [bp+12], 0d        ; until counter reach 0
ja pcx_load_while

jmp pcx_load_end
next :                          ; move data into file buffer
mov bx, word ptr [bp+10]        ; move data into al   
mov al, byte ptr [bx]
mov bx, word ptr [bp+8]         ; move file buffer pointer into bx.
mov byte ptr [bx], al           ; put data into file buffer
inc  word ptr [bp+8]            ; move pointer
inc  word ptr [bp+14]           ; increase main counter

pcx_load_end :
cmp word ptr [bp+14], 64000d    ; if main counter haven't reach 320*200 then
jb pcx_load_big_while           ; go back to top and loop again.


mov ah, 3eh                     ; close the file function number
mov bx, word ptr [bp+6]         ; get handle
int 21h                         ; close the file




jmp normal
pcx_load_error :
disp_str 'error!!! '          ; used to display a message and wait for a
mov al, 0h                      ; keypress.
mov ah, 01h
int 21h

normal :

pop dx                          ; restore registers.
pop es
pop ds
pop cx
pop bx
pop ax

pop bp                          ; restore bp

ret 12                          ; return to calling program and kick 14 bytes
                                ; in stack to space.

pcx_load endp



;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


update_color_register proc
;purpose : 
;input   : return address (top), filename's address, handle, 1 byte color
;          variable's address, counter, 
;output  : 
;method  : 

push bp                         ; initialize...
mov bp, sp                      ; put sp value to bp and save bp
                                ; on the stack.

push ax                         ; save registers
push bx
push cx
push dx


mov ax, @data                   ; initialize ds
mov ds, ax

xor al, al
mov ah, 3dh                     ; open an existing file function number
mov dx, word ptr [bp+4]         ; dx have the file address
mov cl, 0                       ; read_only attribute
int 21h                         ; open the file
mov word ptr [bp+6], ax         ; save handle or error code.


mov ah, 42h                     ; moves read pointer function
mov bx, word ptr [bp+6]         ; get handle
mov cx, 1111111111111111b
mov dx, 1111110100000000b       ; 768 bytes to move
mov al, 2d                      ; move relative to the end of file
int 21h                         ; move file pointer


mov word ptr [bp+10], 0d        ; initialize counter

register_part_while :

xor al, al                      ; clean al
mov ah, 3fh                     ; read file function
mov bx, word ptr [bp+6]         ; get handle
mov cx, 1h                      ; read first three byte
mov dx, word ptr [bp+8]         ; load the data address
int 21h                         ; read file into buffer


xor ah, ah                      ; clean ah
mov bx, word ptr [bp+8]         ; get actual pointer
mov al, byte ptr [bx]           ; get red
shr al, 1
shr al, 1
push ax

xor al, al                      ; clean al
mov ah, 3fh                     ; read file function
mov bx, word ptr [bp+6]         ; get handle
mov cx, 1h                      ; read first three byte
mov dx, word ptr [bp+8]         ; load the data address
int 21h                         ; read file into buffer


xor ah, ah                      ; clean ah
mov bx, word ptr [bp+8]         ; get actual pointer
mov al, byte ptr [bx]           ; get green
shr al, 1
shr al, 1
push ax

xor al, al                      ; clean al
mov ah, 3fh                     ; read file function
mov bx, word ptr [bp+6]         ; get handle
mov cx, 1h                      ; read first three byte
mov dx, word ptr [bp+8]         ; load the data address
int 21h                         ; read file into buffer


xor ah, ah                      ; clean ah
mov bx, word ptr [bp+8]         ; get actual pointer
mov al, byte ptr [bx]           ; get blue
shr al, 1
shr al, 1
push ax

mov ax, word ptr [bp+10]        ; get index
push ax
call set_palette_register

inc word ptr [bp+10]            ; increase counter
cmp word ptr [bp+10], 256d
jl register_part_while

jmp update_normal
update_error :
disp_str 'error!!! '          ; used to display a message and wait for a
mov al, 0h                      ; keypress.
mov ah, 01h
int 21h

update_normal :


pop dx                          ; restore registers.
pop cx
pop bx
pop ax

pop bp                          ; restore bp

ret 8                           ; return and pop the 4 parameter into space.

update_color_register endp


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

Keyboard_Int Proc
; keyboard interrupt routine
;save registers

push ds
push ax

mov ax, seg scan_code           ; set up ds
mov ds, ax

in al, 60h                      ; read scan code
push ax                         ; save it
in al, 61h                      ; control port value
mov ah, al                      ; save in ah
or al, 80h                      ; set bit for keyboard
out 61h, al                     ; write back
xchg ah, al                     ; get back control value
out 61h, al                     ; resent control port
pop ax
mov ah, al                      ; save scan code in ah
test al, 80h                    ; test for break code
jne key_0                       ; yes, clear flags, goto key_0

mov scan_code, al               ; save in variable
mov key_flag, 1                 ; set key flag
key_0 : mov al, 20h             ; reset interrupt
out 20h, al

pop ax                          ; restore registers
pop ds

iret
keyboard_int endp               ; end keyboard routine





;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

timer_tick proc

push ds                         ; save registers
push ax

mov ax, seg timer_flag          ; get segment of flag
mov ds, ax                      ; put in ds
mov timer_flag, 1               ; set flag

pop ax                          ; restore ds
pop ds

iret

timer_tick endp                 ; end timer routine


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


setup_int proc

; input: al= interrupt type
; di = address of buffer for old vector
; si = address of buffer containing new vector
; save old interrupt vector

push es
push bx
push ax
push di
push si
push dx
push ds


mov ah, 35h                     ; get vector
int 21h                         ; es:bx = vector
mov [di], bx                    ; save offset
mov [di+2], es                  ; save segment

                                ; set new vector
mov dx, [si]                    ; has offset
push ds                         ; save it
mov ds, [si+2]                  ; ds has segment number
mov ah, 25h                     ; set vector
int 21h
pop ds                          ; restore

pop ds
pop dx
pop si
pop di
pop ax
pop bx
pop es
ret
setup_int endp


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


pcx_grap_bitmap proc

; purpose: grabs a bitmap from a .pcx frame buffer
; input  : stack entry : return address (top), file buffer address,
;          grab_x, grab_y, sprite address, x_off, y_off, counter, counter2
; output : none ( the return parameters on the stack are all pointers. So we
;          don't need to return them. )
;          
; method : ?

push bp                         ; initialize...
mov bp, sp                      ; put sp value to bp and save bp
                                ; on the stack.

push ax                         ; save registers
push bx
push cx
push si
push ds
push es
push dx

mov ax, @data   ; initialize data segment
mov ds, ax

mov ax, word ptr [bp+6]                 ; grab grab_x value
mov cx, 25d
mul cx                                  ; multiply by 25
inc ax                                  ; add 1
mov word ptr [bp+12], ax                ; save to x_off

mov ax, word ptr [bp+8]                 ; grab grab_y value
mov cx, 25d
mul cx                                  ; multiply by 25
inc ax                                  ; add 1
mov word ptr [bp+14], ax                ; save to y_off

mov cx, 320d
mul cx                                  ; y_off multiply by 320
mov word ptr [bp+14], ax                ; save to y_off
                   
mov word ptr [bp+16], 0                 ; initialize counter
mov word ptr [bp+18], 0                 ; initialize counter2


grab_outer_loop :

grab_inner_loop :


mov bx, word ptr [bp+12]                ; put y_off + x_off + counter2
add bx, word ptr [bp+14]                ; into bx
add bx, word ptr [bp+18]

mov si, word ptr [bp+4]                 ; move the appropriate pixel
mov dl, byte ptr [si+bx]                ; to dl
xor dh, dh
push dx

mov ax, word ptr [bp+16]                ; get counter
mov cx, 24d
mul cx                                  ; multiply by 24
add ax, word ptr [bp+18]                ; then add counter2
mov bx, ax                              ; copy value to bx
mov si, word ptr [bp+10]                ; store sprite address in si

pop dx
mov byte ptr es:[si+bx], dl             ; put dl into sprite address

inc word ptr [bp+18]                    ; increment counter
cmp word ptr [bp+18], 24d               ; compare counter with 24
jl grab_inner_loop                      ; jump back if less

add word ptr [bp+14], 320d              ; add 320 to y_off
mov word ptr [bp+18], 0                 ; initialize counter

inc word ptr [bp+16]                    ; increment counter2
cmp word ptr [bp+16], 24d               ; compare counter2 with 24
jl grab_outer_loop                      ; jump back if less


pop dx                          ; restore registers.
pop es
pop ds
pop si
pop cx
pop bx
pop ax

pop bp                          ; restore bp

ret 16                          ; return and pop the 9 parameter into space.


pcx_grap_bitmap endp


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


draw_sprite proc

; purpose : a drawing of a sprite
; input   : stack entry : return address (top), x, y, sprite address, counter,
;           counter2, double buffer, offset, work_offset
; output  : none
; method  : ?

push bp                         ; initialize...
mov bp, sp                      ; put sp value to bp and save bp
                                ; on the stack.

push ax                         ; save registers
push bx
push cx
push si
push ds
push es
push dx


mov ax, @data   ; initialize data segment
mov ds, ax

mov word ptr [bp+10], 0                 ; initialize counter
mov word ptr [bp+12], 0                 ; initialize counter2

mov word ptr[bp+18], 0                  ; initialize work_offset

mov bx, word ptr[bp+6]          ; put y into bx;
mov ax, word ptr[bp+6]          ; put another copy of y into ax;
mov cl, 8        
shl bx, cl                      ; shift bx 8 bits left
mov cl, 6       
shl ax, cl                      ; shift ax 6 bits left
add ax, bx                      ; sum ax and bx into ax, than means
                                ; y*256 + y*64 = y*320
add ax, word ptr [bp+4]         ; add x to ax which contains y * 320

mov word ptr [bp+16], ax        ; save to offset.

draw_out_loop:

draw_inner_loop:

mov bx, word ptr[bp+12]         ; mov x into bx
add bx, word ptr[bp+18]         ; work_offset + x
mov si, word ptr[bp+8]          ; mov sprite into si
mov dl, byte ptr es:[si+bx]     ; get the color of that pixel.
cmp dl, 0
jz draw_zero
mov bx, word ptr [bp+12]        ; put x into bx
add bx, word ptr [bp+16]        ; add offset
mov si, word ptr [bp+14]        ; load double buffer
mov byte ptr[si+bx], dl         ; put color of that pixel into double_buffer

draw_zero :
inc word ptr [bp+12]            ; increase x
cmp word ptr [bp+12], 24d       ; compare with 24
jl draw_inner_loop              ; jump if smaller

add word ptr [bp+16], 320d      ; add 320 to offset
add word ptr [bp+18], 24d       ; add 24 to work_offset
mov word ptr [bp+12], 0d        ; initialize x

inc word ptr[bp+10]             ; increase y
cmp word ptr [bp+10], 24d       ; compare with 24
jl draw_out_loop                ; jump if smaller



pop dx                          ; restore registers.
pop es
pop ds
pop si
pop cx
pop bx
pop ax

pop bp                          ; restore bp

ret 16                          ; return and pop the 9 parameter into space.


draw_sprite endp

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


get_sprite_background proc

; purpose : get sprite background.
; input   : stack entry : return address (top), x, y, sprite address, counter,
;           counter2, double buffer, offset, work_offset
; output  : none
; method  : ?

push bp                         ; initialize...
mov bp, sp                      ; put sp value to bp and save bp
                                ; on the stack.

push ax                         ; save registers
push bx
push cx
push si
push ds
push es
push dx


mov ax, @data   ; initialize data segment
mov ds, ax

mov word ptr [bp+10], 0                 ; initialize counter
mov word ptr [bp+12], 0                 ; initialize counter2

mov word ptr[bp+18], 0                  ; initialize work_offset

mov bx, word ptr[bp+6]          ; put y into bx;
mov ax, word ptr[bp+6]          ; put another copy of y into ax;
mov cl, 8        
shl bx, cl                      ; shift bx 8 bits left
mov cl, 6       
shl ax, cl                      ; shift ax 6 bits left
add ax, bx                      ; sum ax and bx into ax, than means
                                ; y*256 + y*64 = y*320
add ax, word ptr [bp+4]         ; add x to ax which contains y * 320

mov word ptr [bp+16], ax        ; save to offset.

get_out_loop:

get_inner_loop:

mov bx, word ptr [bp+12]        ; put x into bx
add bx, word ptr [bp+16]        ; add offset
mov si, word ptr [bp+14]        ; load double buffer
mov dl, byte ptr[si+bx]         ; get color of that pixel from double_buffer


mov bx, word ptr[bp+12]         ; mov x into bx
add bx, word ptr[bp+18]         ; work_offset + x
mov si, word ptr[bp+8]          ; mov sprite into si
mov byte ptr es:[si+bx], dl     ; get the color of that pixel.


inc word ptr [bp+12]            ; increase x
cmp word ptr [bp+12], 24d       ; compare with 24
jl get_inner_loop              ; jump if smaller

add word ptr [bp+16], 320d      ; add 320 to offset
add word ptr [bp+18], 24d       ; add 24 to work_offset
mov word ptr [bp+12], 0d        ; initialize x

inc word ptr[bp+10]             ; increase y
cmp word ptr [bp+10], 24d       ; compare with 24
jl get_out_loop                ; jump if smaller



pop dx                          ; restore registers.
pop es
pop ds
pop si
pop cx
pop bx
pop ax

pop bp                          ; restore bp

ret 16                          ; return and pop the 9 parameter into space.


get_sprite_background endp


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


draw_background proc

; purpose : a drawing of a sprite
; input   : stack entry : return address (top), x, y, sprite address, counter,
;           counter2, double buffer, offset, work_offset
; output  : none
; method  : ?

push bp                         ; initialize...
mov bp, sp                      ; put sp value to bp and save bp
                                ; on the stack.

push ax                         ; save registers
push bx
push cx
push si
push ds
push es
push dx


mov ax, @data   ; initialize data segment
mov ds, ax

mov word ptr [bp+10], 0                 ; initialize counter
mov word ptr [bp+12], 0                 ; initialize counter2

mov word ptr[bp+18], 0                  ; initialize work_offset

mov bx, word ptr[bp+6]          ; put y into bx;
mov ax, word ptr[bp+6]          ; put another copy of y into ax;
mov cl, 8        
shl bx, cl                      ; shift bx 8 bits left
mov cl, 6       
shl ax, cl                      ; shift ax 6 bits left
add ax, bx                      ; sum ax and bx into ax, than means
                                ; y*256 + y*64 = y*320
add ax, word ptr [bp+4]         ; add x to ax which contains y * 320

mov word ptr [bp+16], ax        ; save to offset.

drawb_out_loop:

drawb_inner_loop:

mov bx, word ptr[bp+12]         ; mov x into bx
add bx, word ptr[bp+18]         ; work_offset + x
mov si, word ptr[bp+8]          ; mov sprite into si
mov dl, byte ptr es:[si+bx]     ; get the color of that pixel.
mov bx, word ptr [bp+12]        ; put x into bx
add bx, word ptr [bp+16]        ; add offset
mov si, word ptr [bp+14]        ; load double buffer
mov byte ptr[si+bx], dl         ; put color of that pixel into double_buffer

inc word ptr [bp+12]            ; increase x
cmp word ptr [bp+12], 24d       ; compare with 24
jl drawb_inner_loop              ; jump if smaller

add word ptr [bp+16], 320d      ; add 320 to offset
add word ptr [bp+18], 24d       ; add 24 to work_offset
mov word ptr [bp+12], 0d        ; initialize x

inc word ptr[bp+10]             ; increase y
cmp word ptr [bp+10], 24d       ; compare with 24
jl drawb_out_loop                ; jump if smaller



pop dx                          ; restore registers.
pop es
pop ds
pop si
pop cx
pop bx
pop ax

pop bp                          ; restore bp

ret 16                          ; return and pop the 9 parameter into space.


draw_background endp


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


end
