0

I am making a Pong game in assembly and for the ball mechanic I am drawing a blank ball in the place where the last ball location was but when I added it to my game loop the ball started flashing and it looks buggy, Here is the code I use for the ball, any way to make the deleting process better so it won’t flash (including different methods from the one I am using)?

IDEAL
MODEL small
jumps
STACK 100h
p186
DATASEG
;-------------------------
temp_x dw 0
temp_y dw 0
color dw 4
lengthOfDrawings dw 9
pic_off dw 0
x_ball dw 150
y_ball dw 50
h_ball dw 9
w_ball dw 9
ballSpeed dw 03AFFh
y_direction_ball dw 'd'
x_direction_ball dw 'r'
temp_var dw 0
ball db 00h, 00h, 08h, 08h, 08h, 08h, 08h, 00h, 00h
     db 00h, 08h, 08h, 07h, 07h, 07h, 08h, 08h, 00h
     db 08h, 08h, 07h, 07h, 07h, 07h, 07h, 08h, 08h
     db 08h, 07h, 07h, 07h, 07h, 07h, 07h, 07h, 08h
     db 08h, 07h, 07h, 07h, 07h, 07h, 07h, 07h, 08h
     db 08h, 07h, 07h, 07h, 07h, 07h, 07h, 07h, 08h
     db 08h, 08h, 07h, 07h, 07h, 07h, 07h, 08h, 08h
     db 00h, 08h, 08h, 07h, 07h, 07h, 08h, 08h, 00h
     db 00h, 00h, 08h, 08h, 08h, 08h, 08h, 00h, 00h
     
;----------------------
CODESEG

proc draw_pixel
    pusha
    xor bh, bh
    mov cx, [temp_x]
    mov dx, [temp_y]
    mov ax, [color]
    mov ah, 0ch
    int 10h
    popa
    ret
endp draw_pixel

proc draw_line_ball
    pusha
    mov cx, [lengthOfDrawings]
    mov ax, [x_ball]
    mov [temp_x], ax
drawpr:
    call draw_pixel
    inc [temp_x]
    loop drawpr
    popa
    ret
endp draw_line_ball

proc draw_ball
    pusha
    mov cx, [x_ball]
    mov dx,[y_ball]
    mov ax, 0ch
    int 10H ; AL = COLOR
    cmp al, 4
    je endDrawBall
    cmp al, 9
    je endDrawBall
    ; DI  שמירה כתובת התחלתית של מערך דמות 
    mov di,[pic_off]
    mov dx, [y_ball]
    
print_line:
    mov cx, [x_ball] ; x pos
    mov si, [w_ball] ; ball width

print_columns: 
    mov al, [di] copy color to AL
    inc di  ; next item in array
    
    ; painting a pixel
    ;  cx = x coordinate , dx = y coordinate, al- color
    mov bh,0
    mov ah,0ch
    int 10h 
    
    inc cx ; inc x
    dec si ; decrease col counter
    cmp si, 0
    jne print_columns
    
    inc dx ;inc Y
    dec [h_ball] ; decreasing row counter
    cmp [h_ball], 0
    jne print_line
endDrawBall:
    popa
    ret
endp draw_ball

proc draw_blank_ball
    pusha
    mov cx, 9
    mov ax, [y_ball]
    mov [temp_y], ax
    mov [color], 0
rectanl:
    call draw_line_ball
    inc [temp_y]
    loop rectanl
    mov [color], 4
    popa
    ret
endp draw_blank_ball

proc delay
    pusha
    mov cx, 00h ;Higher part of the number
    mov dx, [ballSpeed] ;Lower part of the number
    mov al, 0
    mov ah, 86h
    int 15h
    popa
    ret
endp delay

start:

mov ax, @data
mov ds, ax

;---------------------------
    ;Changing to graphic mode
    mov ax, 13h
    int 10h
    
gameLoop:
    add [x_ball], 2h
    inc [y_ball]
    mov [pic_off], offset ball
    mov [h_ball], 9
    mov [w_ball], 9
    call draw_ball
    call delay
    call draw_blank_ball
    jmp gameLoop

    
endGame:
    ;Returns to text mode
    mov ax, 2h
    int 10h
;---------------------------


exit:
mov ax, 4c00h
int 21h
END start
Demo
  • 15
  • 5
  • Only delete the parts that will not show up on the next frame. – fuz Feb 15 '22 at 16:59
  • @fuz, but all of the parts won’t show next frame since I am increasing the X location and the Y location so the new ball is in a different position than the one I need to delete – Demo Feb 15 '22 at 18:12
  • Are you running this under DOSBox, or some other emulator, in case that matters? Is it doing cycle-accurate emulation of an old slow 8088? If so, then doing a `pusha` / `popa` for every pixel probably doesn't help! Although `int 10h` itself is probably not fast, compared to storing directly to VGA memory. – Peter Cordes Feb 15 '22 at 19:10
  • @PeterCordes I am using DOSBox, the int 10h part I am required to do for the game (as a requirement) do I can’t change that. Now, for the pusha & popa I have no requirement but it could ruin other parts of my code by overriding some of the registers so how can I remove them safely? – Demo Feb 15 '22 at 19:53
  • 1
    Use comments to keep track of which registers are clobbered by which function, or just inline `draw_pixel` instead of store/reload to global vars; many of the register args don't change. (David Wohlferd's answer shows this) Or use a standard calling convention, like letting AX, CX, and DX be clobbered by functions, and only save/restore other registers when necessary. ([What are callee and caller saved registers?](https://stackoverflow.com/a/56178078)) – Peter Cordes Feb 15 '22 at 22:07
  • You might also experiment with `int 10h AH=06h`. I believe that if you set al to zero, it clears the area specified in cx/dx. – David Wohlferd Feb 21 '22 at 02:28
  • I've run into this sort of thing before, it might just be a result of the order in which you erase the ball vs. draw it again. If you only redraw the ball when it actually changes location you shouldn't get any flicker – puppydrum64 Nov 28 '22 at 17:13
  • If you directly draw to video memory (if I recall correctly, VGA video memory is at a segment register value of `0xA000`) you can XOR the ball with the screen memory to draw it. This has a nice benefit where if you draw the ball over top itself it gets erased instead, at the cost of taking slightly longer than simply storing the ball sprite. I used to have some code I wrote for a blitter routine, I can't find it right now but if I do you can use it. – puppydrum64 Nov 28 '22 at 17:18

1 Answers1

1

pusha is going to be a pretty expensive operation. Only pushing/popping the registers you modify might be a savings.

That said, how about something like this? It gets rid of the call to draw_pixel (thus a pusha/popa), plus the constant repopulating of the registers.

proc draw_line_ball
    pusha
    mov si, [lengthOfDrawings]

    xor bh, bh
    mov cx, [x_ball]
    mov dx, [temp_y]
    mov ax, [color]
    mov ah, 0ch

drawpr:

    int 10h

    inc cx
    dec si
    jnz drawpr

    popa
    ret
endp draw_line_ball

(Obviously) I have not tried this, but there may be some useful ideas there.

David Wohlferd
  • 7,110
  • 2
  • 29
  • 56