Home > Back-end >  TASM sprite looks weird
TASM sprite looks weird

Time:06-04

I have recently begun coding in TASM and am currently working on sprites. In my program, I receive a sprite and print it on screen (Graphic mode).

The program works fine essentially but the numbers that are printed look weird. Pixels that are supposed to be right beneath each other appear somewhat distant.

This is how I call the function:

push 10 ; amount of lines
push 10 ; length of each line
push 4 ; color
push 100 ; y
push 160 ; x
push offset card2
call Sprite_Figure

And here is the function:

proc Sprite_Figure
push bp
mov bp, sp
push ax
push bx
push cx
push dx
push si
    
    mov si, [bp 4] ; sprite offset
    mov cx, [bp 14] ; number of lines   
    loop1:
        mov dx, [bp 12] ; size of one line
        loop2:
            push dx
            xor dx, dx
            cmp [byte ptr si], 0
            je continue
            
            print:
            mov bx, [bp 8] ; current row    
            
            mov ax, 320
            mul bx
            mov bx, ax ; calculation to get location of pixel on screen
            add bx, [bp 6] ; x
            
            mov ax, [bp 10] ; color
            mov [es:bx], al ; color location, es val is 0A000h
            
            continue:
            pop dx
            inc si ; next element in array  
            dec dx
            inc [bp 6] ; right by one
            
            cmp dx, 0
            jne loop2
        
        mov ax, 320
        sub ax, [bp 12] ; the size of one line
        add [bp 6], ax ; new line
        inc [bp 8] ; one line down  
        dec cx
        cmp cx, 0
        jne loop1
pop si
pop dx
pop cx
pop bx
pop ax
pop bp
ret 12
endp Sprite_Figure  

This is how the sprite looks on screen:
enter image description here

Does anyone have any ideas?

CodePudding user response:

The code is mixing 2 ways of moving down a line! This explains why the code descends at double rate on the screen, the value 320 gets added twice.

Basically you have a couple of ways to draw your character matrix:

  • A pair of nested loops where you vary the X and Y coordinates and calculate the address on screen each time.
  • A pair of nested loops where you calculate once the address of the upperleftcorner pixel on screen, and then change that address as needed.

The line

inc [bp 8]      ; one line down

suits the 1st method, whereas the lines

mov ax, 320
sub ax, [bp 12] ; the size of one line
add [bp 6], ax  ; new line

suit the 2nd method.

Method1

Because the inner loop has repeatedly incremented the X coordinate, for restoration purposes, you have to subtract the total number of increments:

    ...
    dec dx
    jnz loop2
    mov ax, [bp 12] ; Size of one line (number of increments)
    sub [bp 6], ax  ; X is now restored
    inc [bp 8]      ; Y  one line down  
    dec cx
    jnz loop1

Method2

The coordinates are used just the one time to obtain an address in BX. Only the address varies after that. A lot less instructions in the loops, means this is a much more efficient approach.

    mov ax, 320
    mul [word ptr bp 8] ; Y
    mov bx, ax
    add bx, [bp 6]      ; X

    mov si, [bp 4]      ; sprite offset
    mov cx, [bp 14]     ; number of lines   
    mov al, [bp 10]     ; color

loop1:
    mov dx, [bp 12]     ; size of one line

loop2:
    cmp [byte ptr si], 0
    je continue
    mov [es:bx], al     ; ES val is 0A000h
continue:
    inc si              ; next byte in character pattern
    inc bx              ; X  right by one on screen
    dec dx
    jnz loop2

    sub bx, [bp 12]     ; Address of left side
    add bx, 320         ; Address of new line
    dec cx
    jnz loop1
  • Related