Search code examples
assemblyx86-16dostasm

i don't know why the score system doesn't work


I am using dosbox with tasm.

This is the main part of the code written in assembler.

IDEAL
MODEL small  
STACK 100h
P186 

include 'GL1.asm'  

DATASEG

ballX DW 160
ballY DW 100
ballColor DB 4
BALL_SIZE  EQU  20
ballDeltaX DW ?
ballDeltaY DW ?
scorr db 0

randChangeCounter DW ?

CODESEG

start:
mov ax, @data
mov ds, ax
mov ax, 13h
int 10h
mov al,[ballColor]
call glBall 
mov CX,60
mov [ballDeltaX],-2
mov [ballDeltaY],-1
mov cx,300 
call SetCursor
Gameloop:
mov BH ,00h
call TickDelay

call mouse 

call Score

cmp [scorr] , 20
je exit
call randChange


call changeOnborder
call renderBall

call mouse 
call Score
cmp [scorr] , 20
je exit


jmp  Gameloop
exit:

mov ah, 0
mov al, 2
int 10h

mov ax, 4c00h
int 21h

proc renderBall
PUSHA

xor al,al  ; balck 
call glBall 

mov cx,[ballDeltaX]
add [ballX],cx
mov cx,[ballDeltaY]
add [ballY],cx

mov al,[ballColor]
call glBall 
POPA    
ret
endp renderBall

proc waitKey
PUSHA
mov ah,00h
int 16h 
POPA
ret
endp waitKey    

proc glBall 
PUSHA 
mov cx,[ballX]
mov dx,[ballY]
mov ah,BALL_SIZE
mov bl,BALL_SIZE

call glBox  
POPA
ret 
endp glBall

proc glBox 
PUSHA 
@@ONE_LINE  :
call glVLine  
inc dx
dec bl
jnz @@ONE_LINE
POPA
ret 
endp

proc glVLine 
PUSHA 
mov bl,ah 
mov bh,0
mov ah,0ch
@@ONE_PIXEL :
int 10h
inc cx
dec bl
jnz @@ONE_PIXEL
POPA
ret 
endp

proc randChange
push ax
inc [randChangeCounter]
cmp [randChangeCounter],20
jne @@skip
    mov [randChangeCounter],0

    mov ax,13 ; +-6
    call rand_max
    sub ax,6 
    mov [ballDeltaX],ax

    mov ax,13 ; +-4
    call rand_max
    sub ax,6 
    mov [ballDeltaY],ax

    mov ax,6 
    call rand_max
    add ax,2 
    mov [ballColor],al

@@skip:
pop ax
ret
endp randChange
proc SetCursor

mov ax, 0h
int 33h
mov ax, 1h
int 33h
mov ax, 3h
int 33h
ret
endp SetCursor
proc mouse
mov ax, 3h
int 33h
ret
endp mouse
proc Score

mov   ax,3h
int 33h
cmp  bl,1
je   Check_X1_Cords
ret
Check_X1_Cords:
cmp cx, [ballX]
jg Check_X2_Cords
ret
Check_X2_Cords:
cmp cx,[ballX+20]
jl Check_Y1_Cords
ret
Check_Y1_Cords:
cmp dx, [ballY]
jg ScoreLabel
ret
Check_Y2_Cords:
cmp dx, [ballY+20]
jl ScoreLabel
ret
ScoreLabel:
inc [scorr]
ret 
endp Score

proc changeOnborder
push ax

mov ax,[ballX]
add ax,[ballDeltaX] 
cmp ax,320-BALL_SIZE  
jg X_FIX
cmp ax,0
jge X_OK
X_FIX:  
mov [ballColor],1
neg [ballDeltaX] 
X_OK:

mov ax,[ballY]
add ax,[ballDeltaY] 
cmp ax,200- BALL_SIZE
jg Y_FIX
cmp ax,0
jge Y_OK
Y_FIX:  
mov [ballColor],1
neg [ballDeltaY] 
Y_OK:

pop ax
ret
endp changeOnborder

END start

and this is GL1.asm

 RANDPRIME    equ    401

 segment    biosdata    at 40h
 org    6ch
timer      dw    ?    ; clock ticks
ends

DATASEG
lastrand   dw    0


FastCounter  DW 0 ; 
SlowCounter  DW 0 ; 

CODESEG

;
; timeticks - get time ticks from bios data segment.
;
; Register Arguments:
;    None.
;
; Returns: 
;    ax - current ticks
;

proc    timeticks
push   es

mov    ax, biosdata
mov    es, ax
assume es:biosdata
mov    ax, [timer]
assume es:nothing
pop    es
ret
endp

;
; random - pseudo generate random number
;
; Register Arguments:
;    None.
;
; Returns:
;    ax - random number.
;
codeseg
proc    random
push   dx
push   bx
mov    bx, [lastrand]
mov    ax, bx
mov    dx, RANDPRIME
mul    dx
mov    dx, ax
call   timeticks
xor    ax, dx
xchg   dh, dl
xor    ax, dx
xchg   bh, bl
xor    ax, bx
mov    [lastrand], ax
pop    bx
pop    dx
ret
endp

proc    rand_max
push   dx
push   bx
mov bx,ax ; store max
call random ; -> ax
xor dx,dx
div bx
mov ax,dx   ; the reminder [0..max]

pop    bx
pop    dx
ret
endp rand_max
 ;===================== Delay ===================== 
Proc delay

push ax
push cx
push dx
push es

mov dx,0 
mov cx , 55
div cx  

mov cx, ax  
cmp cx,0
je Finish
DelayLoop:

call timeticks
mov dx,ax   
Tick:  
call timeticks
cmp dx,ax   
je Tick

loop DelayLoop
Finish: 

pop es 
pop dx
pop cx
pop ax
ret 
endp Delay  

proc  TickDelay
pusha

mov cx, 4 
each_sync:
  call wait_for_vsync
loop each_sync

popa
ret 
endp TickDelay

proc wait_for_vsync
pusha

mov dx, 03dah
@@previous_not_ended:
in   al, dx
test al, 08h
jnz  @@previous_not_ended

@@next_not_started:
in   al, dx
test al, 08h
jz  @@next_not_started

@@exit:
popa
ret
endp

I don't know what to do I think the problem is in GL1 but im not sure.

Any help according to the problem or style of code would be really appreaciated.

Thanks a lot in advance.


Solution

  • Just a quick browse revealed the following:

    Your timeticks procedure does not read the BIOS timer at all!
    You've set up everything for the ES segment register, but the mov ax, [timer] instruction entirely depends on the DS segment register only.

    This destroys both your rand_max and delay procedures.
    No wonder then that it doesn't work!

    Put in another way, the following becomes an infinite loop (because timeticks most probably always returns the same value!):

        call  timeticks
        mov   dx, ax   
    Tick:  
        call  timeticks
        cmp   dx, ax   
        je    Tick