1

J'ai une routine qui se charge de vérifier les événements liés à certains tiles une fois que le joueur est dessus mais je n'arrive pas à sauter à la routine de l’événement en question alors que ça devrait marcher... sad

Le code :

check_event:	; a:numéro du tile
	ld hl,event_tiles
	ld b,(event_tiles_end - event_tiles)/3	; b = 2 ici

check_event_loop:
	cp (hl)	; on compare au numéro du tile de la table
	inc hl	; on incrémente pour qu'hl prenne la valeur de l'adresse de la routine
	jp z,jp_hl	; parce que jp z,(hl) n'existe pas
	inc hl
	inc hl	; si c'est pas le bon tile on incrémente pour tester le suivant (l'adresse prend 2 octets)
	djnz check_event_loop
	ret

jp_hl:
	jp (hl)	; normalement ça saute bien à la _valeur_ d'hl (adresse de la routine) et non pas à son adresse (qui est celle de l'adresse des tiles), non ?

event_tiles:
	.db 3	; tile n°3 = porte
	.dw event_door	; adresse de la routine de gestion des téléportations
	.db 18 ; etc...
	.dw event_hole

event_tiles_end:


Vous voyez où est le problème ?

2

jp (hl) saute à l'adresse mise dans hl, il n'y a pas de déréférencement.

Je me demande si le inc hl ne change pas ton registre f juste avant le jp z, jp_hl
De plus tu devrais sauver hl car j'imagine qu'il est modifié dans ta sous routines non?
Enfin voila tout ce que mon instinct me dit à propos de ton code tongue

J'ai eu un problème similaire il y a quelques temps si ça peut aider:
http://www.cemetech.net/forum/viewtopic.php?t=7159&start=0

3

Pas besoin de sauver hl : c'est un saut pas un appel (pas de retour dans la boucle).

Du coup je ne vois pas trop comment facilement récupérer la valeur d'hl pour l'y faire ensuite pointer...

4

Bon je crois avoir résolu le problème avec l'excellente fonction ex (sp),hl :
check_event_tile:
	ld hl,event_tiles
	ld b,(event_tiles_end - event_tiles)/3

check_event_tile_loop:
	cp (hl)
	jp z,event
	inc hl
	inc hl
	inc hl
	djnz check_event_tile_loop
	ret

event:
	inc hl
	ld (sp_save),sp
	ld sp,hl
	ex (sp),hl
sp_save = $+1
	ld sp,0
	jp (hl)

Je pensais qu'inc hl ne modifiait pas les flags mais enfaite c'est seulement inc (registre 16bits) (cf http://quasar.cpcscene.com/doku.php?id=iassem:z80init#la_mise_a_jour_des_flags).

Ça a l'air de marcher mais c'est un peu tortueux, si quelqu'un à mieux...

5

Pourquoi ne pas simplement pusher hl sur la pile ?
check_event_tile: 
	ld hl,event_tiles 
	ld b,(event_tiles_end - event_tiles)/3 

check_event_tile_loop: 
	cp (hl)
;###############
	push hl
	ret z
	pop hl
;###############
	inc hl 
	inc hl 
	inc hl 
	djnz check_event_tile_loop 
	ret 

6

Oui mais il faut faire un inc hl avant de faire le saut, or ça change le zero flag.

Y'a sûrement moyen de faire avec mais je ne vois pas trop la différence avec jp (hl)...

7

Comment as-tu organisé les tuiles ? Je crois qu'il serait mieux d'organiser tes tuiles pour que chaque tuile "interactive" soit l'une après l'autre (ensemble). Sinon:
check_event_tile:  
	ld hl,event_tiles  
	ld b,(event_tiles_end - event_tiles)/3  
 
check_event_tile_loop:  
	cp (hl) 
;############### 
	jr nz,$+5
		inc hl
		push hl
		ret
;############### 
	inc hl  
	inc hl  
	inc hl  
	djnz check_event_tile_loop  
	ret 

8

Ça ferait gagner du temps pour la comparaison mais dans tous les cas il faut que j'arrive à sauter à l'adresse de la routine...

Pour le moment je n'ai pas encore définit quels seront les tiles interactifs donc je compare tout, mais quand ce sera fait je les réunirais très certainement.

Sinon ça ne devrait pas plutôt être jr nz,$+3 plutôt (enfin même avec je ne sais pas pourquoi mais ça ne marche pas...) ?

9

jr nz,$+5 ;2 octets
inc hl ;1 octet
push hl ;1 octet
ret ;1 octet

Ahh mais je sais pourquoi ça ne marche pas, il faut d'abord ajouter ces 4 octets/instructions:
ld a,(hl)
inc hl
ld h,(hl)
ld l,a

On va à l'addresse dans hl, pas à l'addresse contenue dans l'address dans hl :P Désolé !

10

Ça marche (avec jp (hl) à la fin aussi) par contre je ne pensais pas qu'il fallait inclure la taille du jr dans l'adresse du saut...?

edit : ça marche avec :
check_event_tile_loop:
	cp (hl)
	jr nz,$+8
	inc hl
	ld a,(hl)
	inc hl
	ld h,(hl)
	ld l,a
	jp (hl)
	inc hl
	inc hl
	inc hl
	djnz check_event_tile_loop
	ret

Merci !!! boing

11

Oui, l'assembleur utilise l'octet (l'addresse) actuel de l'instruction. Mais si tu regardes le code hexa c'est comme tu pensais, une valeur de zéro sauterait à l'octet suivant. Je crois que l'assembleur n'augmente pas le "PC" (je ne sais pas comment il s'appelle) jusqu'à la fin d'une instruction.