.model medium, basic
.stack 20h
.386

EXTRN gsclipx1:WORD
EXTRN gsclipx2:WORD
EXTRN gsclipy1:WORD
EXTRN gsclipy2:WORD

.code

;sub GSfvtPut(x,y,varseg(screen),varptr(screen),varseg(Array),varptr(array))
;stack layout:
;bp+16  x
;bp+14  y
;bp+12  screenseg
;bp+10  screenofs
;bp+8   aryseg
;bp+6   aryofs
;bp+4   returnseg
;bp+2   returnofs
;bp+0   bp         (after pushing it on the first line)
;bp-2   toadd      (this is pushed several lines after the 'mov bp,sp')
;bp-4   ds

; es:di = screen
; ds:si = array

public GSfvtPut
GSfvtPut proc

;intro stuff, (memory management, getting variables set up, etc)

push bp
mov bp,sp

xor bx,bx         ;heh.... I could have done this a few lines up, but    
push bx           ;I had already written the stack layout before that... 

mov cx, gsclipx1
mov dx, gsclipy1
push cx
push dx
mov cx, gsclipx2
mov dx, gsclipy2
push cx
push dx

push ds
push es

mov es, [bp+12]   ;
mov di, [bp+10]   ;ds:si = screen

mov ds, [bp+8]    ;
mov si, [bp+6]    ;es:di = array

mov dx, [si]   ;dx = width*8
shr dx, 3
add si, 2         ;move di to the location of the height

mov bx, [si]   ;bx = height
add si, 2         ;di is now at the starting location of the image...

;;;;;;;;;         ;important stuff :)
mov cx, [bp+14]   ;cx = Y     
cmp cx, [bp-10]     ;if it is waaay too low, then exit
jg endofspr
cmp cx, [bp-6]
jl toohigh        ;if it is above the screen, then goto Toohigh

aftertoohigh:


;;;;;;; at this point: bx=height, dx = width, cx = Y location
;now check to see if it is partially off of the bottom of the screen

mov ax, cx        ;ax = Y
add ax, bx        ;ax = Y + height (the bottom pixel)
cmp ax, [bp-10] 
jg toolow         ;if it is too low, then goto toolow to be 'cropped'
aftertoolow:

sub ax,1
mov cx,ax
shl ax, 2         ; \
add ax, cx        ; /ax = bottompixel *320
shl ax, 6         ;/
add di, ax        ;offset the screen to the correct row

;;;;;;;; atp: bx = fully corrected height, dx=uncorrected width, cx=Y, ax=:oP
mov ax, [bp+16]   ;ax = X location
cmp ax, [bp-8]         ;waaay too far to the right? then exit
jg endofspr
cmp ax, [bp-4]  
jl tooleft        ;partially off of the screen to the left?
Aftertooleft: 
add di, ax        ;if it is fully on the screen, adjust the screen's offset   

;;;;;;;;atp: ax = X,bx=height,cx=Y,dx=width
;now, check to see if it is partally off of the right side of the screen

add dx, ax        ;running out of registers now :oP
cmp dx, [bp-8]        ;dx = width + X
jg tooright       ;greater than 319? goto tooright to be cropped
sub dx, ax        ;dx = width + X - X = width
aftertooright:
mov cx, dx        ;cx = width

jmp sprloop

toohigh:
neg cx            ;cx = -Y
add cx, [bp-6]
cmp cx, bx
jge endofspr    ;if it is waaay too high, end
sub bx, cx
mov cx, [bp-6]
jmp aftertoohigh  ;now cx = 0, 

toolow:
sub ax, [bp-10]        ;ax = Y2
dec ax
sub bx, ax        ;bx = height... this "crops" the height...
push ax
toolowloop:
add si, dx
dec ax
jnz toolowloop
pop ax
jmp aftertoolow

tooleft:
neg ax            ;ax = abs(X)
add ax, [bp-4] 
cmp ax, dx        ;if ax (=X) is too far to the left, end...
jge endofspr
add si, ax        ;ax(=-X) is < 0, di = the array's offset...
sub dx, ax        ;width = width + X (crops the width)
mov [bp-2], ax    ;[bp-2] is a weird little error-corrector that is used in 
                  ;the main loop to skip over the unneeded pixels
mov ax, [bp-4]  
jmp aftertooleft

tooright:
sub dx, [bp-8]    ;now dx = X + width - 319
sub dx, 1
add [bp-2],dx     ;add dx to the mysterious error-corrector :)
mov dx, [bp-8]  
add dx, 1         ;\
sub dx, ax        ;/now the sprite's width is just from X to 319...
jmp aftertooright

;;;;;;
;atp, ax is for pixels, bx = height, cx = width counter, dx = real width
;es:di = screen
;ds:si = array

sprloop:
mov ah, [si]      ;ah = current byte from the array
inc si                     ;move to the next pixel in the array

cmp ah, 0                  ;if it is 0, then move to the next byte...

je endofsprloop

mov es:[di], ah            ;puts the result into the screen

endofsprloop:
inc di   
dec cx
jnz sprloop
sub di, 320                ;if at the end of row, move down a row on the scrn
mov cx, dx                 ;cx = real width again...
mov ax, [bp-2]
sub di, cx                 ;move the screen offset to the starting X coord
add si, ax             ;move aryoffset up (in case it is off the edge of
dec bx                        ;the screen
jnz sprloop
           
endofspr:    ;either the thing is really far off the edge of the screen
pop es
pop ds       ;or it is finished... either way, restore ds&bp, & end
pop eax
pop ecx
pop bx
pop bp 
ret 12         ;restore the stack & end
GSfvtPut endp     ;the end :o)

end
