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:
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