Petit coup de nostalgie, j'ai eu envie de reprendre un peu l'asm z80 dans l'espoir peut être de terminer pour de bon un jeu cette fois (et confirmer que je n'ai pas rejoint la TIFT pour rien)...

Gurk est un RPG sortit à la base sur les nokia s30 (J2ME) puis porté sur android. J'y ai pas mal joué et je doit dire que c'est assez intuitif malgré sa sobriété (menu et combats très simplifiés), mais c'est en partit ça qui m'a convaincu que c'est un jeu plus ou moins "portable" facilement sur les TI z80.

Donc après quelques heures à galérer pour rassembler tout ce que j'avais besoin (tiles surtout, et notez la superbe façons dont spasm me permet les inclure), je me suis attaqué au tilemapper. En effet il n'y a pas à proprement parler de menu d'accueil, le jeu est reset sur la carte du monde à chaque lancement mais on peut charger une partie parmi les 3 emplacements disponibles pour sauver.

Devant l'énorme carte du monde (80*80 tiles si mes souvenirs sont bons) j'ai dû réfléchir au meilleur moyen de compression. Enfin ça c'était après avoir dû trouver un moyen rapide de convertir les cartes rippées du jeu en assembleur grâce à PureBasic.

J'ai donc opté pour un système se rapprochant du RLE, me permettant un gros gain de place et la possibilité de décompresser à la volé les tiles. Ceux-ci sont donc indexés par longueur d'enchaînement jusqu'à 255, ce qui m'a permis une compression de 60%. Bien-sûr cela sous entend une vitesse plus ou moins rapide de décompression selon la distance des tiles recherchés... Pour le moment je pense me tourner vers les interruptions pour maintenir un FPS constant selon cette distance.

Donc voilà mon tilemapper est prêt :

05-05-11.gif


map_display:
	bcall _grbufclr
	ld c,5

map_display_y:
	ld b,6

map_display_x:
	push bc
	call tile_display
	pop bc
	djnz map_display_x
	dec c
	ld b,c
	djnz map_display_y
	call ionFastCopy
	ret

tile_display:
	dec c
	push bc
	ld a,(map_x)
	add a,b
	ld h,0
	ld l,a
	ld a,(map_y)
	pop bc
	push bc
	add a,c
	push af
	ld a,(map_w)
	ld d,0
	ld e,a
	pop af
	call addhlde_a
	ld de,world_map
	call tile_decompress
	pop bc
	push bc
	xor a
	call adda16_b
	pop bc
	push af
	ld b,c
	xor a
	call adda16_b
	ld l,a
	pop af
	ld b,16
	ld c,2
	call ionLargeSprite
	ret

tile_decompress:
	ld a,(de)
	ld b,0
	ld c,a
	or a
	sbc hl,bc
	jr z,tile_decompress_ok
	jp m,tile_decompress_ok
	inc de
	inc de
	jr tile_decompress

tile_decompress_ok:
	inc de
	ld a,(de)
	ld hl,tiles
	ld de,32
	call addhlde_a
	push hl
	pop ix
	ret

adda16_b:
	add a,16
	djnz adda16_b
	sub 16
	ret

addhlde_a:
	or a \ ret z
	ld b,a

addhlde_a_loop:
	add hl,de
	djnz addhlde_a_loop
	ret

Y'a sûrement des optimisations donc je suis preneur de toute remarque !

Bon voilà le plus dur était d'avoir les bases maintenant c'est plus que du remplissage... A la limite ce qui m'emmerde un peu c'est de ne pas avoir les statistiques pour les monstres et donc de ne pas pouvoir calculer exactement les même dégâts que l'original mais bon ça je ferai au mieux...

En espérant avoir le temps et l'envie de le continuer ! smile

Plus d'info ici : http://deeph.servhome.org/?a=entrie&id=11
Je viens de voir les images du jeu et je crois que c'est un très bon choix pour porter, je jeterai un coup d'oeuil à ton code un peu plus tard, mais je ne compte pas avoir beaucoup à dire smile Si tu veux, je peux poster mon mapper qui fait plus ou moins exactement la même chose avec quelques modifications: je dessine une colonne et un rang de plus pour m'aider avec le "smoothscrolling". Mais essentialment c'est un mapper de tiles 16x16 alignées et assez simple.
;lleva:
;de = xcoord
;b = y coord
dibMapa:
	add hl,de
	ld e,b
	ld b,a
	add hl,de
	djnz $-1
	exx
		ld hl,saferam1	;donde guardar el mapa antes de dibujarlo a la pantalla, es decir, el gbuf
		ld de,13		;numero de columnas en gbuf menos uno (por el inc hl')
		ld bc,$0705		;dibujar 7 columnas y 5 filas de sprites (en la pantalla caben 6x4))
dibFila:
		push hl	;guardar gbuf
	exx
	push hl		;save map loc
	ld l,(hl)	;numero del sprite
	ld h,0
	ld bc,tileData
	add hl,hl	;x2
	add hl,hl	;x4
	add hl,hl	;x8
	add hl,hl	;x16
	add hl,hl	;x32
	add hl,bc	;primer byte en sprite
	ld b,16		;16 filas en sprite
dibSprite:
	ld a,(hl)	;pixeles del sprite a dibujar
	inc hl		;proximo conjunto de pixeles
	exx		;cambiar a los registros alternativos
		ld (hl),a
		inc hl	;proximo byte en gbuf
	exx
	ld a,(hl)
	inc hl		;2º conjunto (pixels son 16x16: 2 bytes de ancho)
	exx
		ld (hl),a
		add hl,de	;bajar a la proxima fila
	exx
	djnz dibSprite
	
	pop hl		;posicion en el mapa
	inc hl
	exx
		pop hl	;gbuf anterior
		inc hl
		inc hl	;saltar dos bytes porque los sprites son de 16x16
		djnz dibFila
	
	exx
	ld a,(mapWidth)
	sub 7			;ya hemos avanzado un cierto numero de tiles
	ld e,a
	ld d,0
	add hl,de
	exx
		ld e,14*15	;
		add hl,de
		ld e,13
		ld b,7
		dec c
		jr nz,drawRow
	ret
Pourquoi as-tu le pop/push bc ici ? Je ne pense pas que tu les utilises pour rien.
push bc
ld a,(map_x)
add a,b
ld h,0
ld l,a
ld a,(map_y)
pop bc
push bc
Enfaite je scroll par tiles pour rester proche de l'original, et puis c'est un peu plus simple pour les collisions.

Pour ce qui est des push/pop bc, le premier sert à sauvegarder c (=y) et le second b (=x). Je ne sais pas si c'est ce qu'il y a de plus optimisé mais c'est le plus simple je pense.
J'aime beaucoup les sprites, en particulier ce des montagnes !

Et je parlais de cette partie-ci:
	dec c			;bc = bc-1
	push bc			;bc = bc
	ld a,(map_x)	;bc = bc
	add a,b			;bc = bc
	ld h,0			;bc = bc
	ld l,a			;bc = bc
	ld a,(map_y)	;bc = bc
	pop bc			;bc ne s'est pas changé, il a la même valeur
	push bc 
Je n'ai pas eu le temps de regarder ton code soigneusement, mais je crois que tu affiches le map d'en bas à droite vers le haut à gauche ?
Oui c'est dans ce sens à cause des djnz.

Sinon voilà en gros l'explication :

map_display:
	bcall _grbufclr
	ld c,5			; nombre maximum de tiles verticaux +1

map_display_y:
	ld b,6			; nombre maximum de tiles horizontaux

map_display_x:
	push bc
	call tile_display
	pop bc
	djnz map_display_x	; on s'occupe d'abord des tiles horizontaux (de droite à gauche)
	dec c			; d'où le +1
	ld b,c
	djnz map_display_y	; et ensuite des tiles verticaux (de bas en haut)
	call ionFastCopy
	ret

Pour le reste, oui il y a un push/pop bc en trop, merci de me le faire remarquer !

	dec c
	ld a,(map_x)
	add a,b
	ld h,0
	ld l,a
	ld a,(map_y)
	push bc
Je crois aussi que tu n'as pas besoin du "or a" dans tile_decompress si tu ne l'utilise pas que pour le tilemapper parce que le djnz de addhlde_a remettra toujours le drapeau carry à 0.

Et si tu ne veux pas utiliser les registres cachés (ce n'est pas un app, non ?), tu pourrais utiliser du SMC:
	SMC		sans SMC
	____		______
	dec c		dec c
map_x = $+1
	ld a,0		ld a,(map_x)
	add a,b		add a,b 
	ld h,0		ld h,0 
	ld l,a		ld l,a 
map_y = $+1
	ld a,0		ld a,(map_y) 
	push bc		push bc 
	add a,c		add a,c 
			push af 
			ld a,(map_w) 
	ld d,h		ld d,0 
map_w = $+1
	ld e,0		ld e,a 
			pop af 
14 octets, 55 clocks	21 octets, 105 clocks
Je n'ai pas encore eu le temps de trop regarder et je n'ai jamais trop utilisé le SMC mais si ça marche merci ! smile

Et oui, ce n'est pas une application mais un programme Ion.

edit : je viens de tomber sur le site des développeurs : http://larvalabs.com/blog/larvalabs/our-first-mobile-game/ , où j’apprends notamment que les donjons sont aléatoires cheeky Je n'ai aucune idée de la façons dont concevoir des générateurs de cartes donc on verra bien...
Peux-tu pas les contacter ? Peut-être ils l'ont encore.. Je ne pense pas qu'ils te diraient que non.

Alors, qu'est-ce que tu comptes faire maintenant ?
Dès que j'ai 5min je commence le moteur de déplacements avec collisions puis ensuite je pense m'attaquer aux menu.
Bravo beau travail !!!
J'espère que tu le finiras. Je suis content de voir que l'asm z80 est un peu actif iciwink

Je me sens tout nul avec mon petit projet oilcap maintenant xD

Encore bravo continue wink
Merci smile

Oui je pense pouvoir pas mal l'avancer durant les vacances, le seul problème c'est que sans les sources il ne sera jamais à 100% identique à l'original. Je peux décompiler les sources Java mais c'est pas pratique et il me manquer les headers...

Le mieux ça reste de contacter les développeurs, donc dès que j'ai le temps je pense le faire !
Contra (./11) :
Bravo beau travail !!!
Je suis complètement d'accord smile
Je suis content de voir que l'asm z80 est un peu actif iciwink
Moi aussi ! Il n'y a pas beaucoup de monde qui est encore actif et je suis très content d'avoir trouvé ce site-ci grin

Et deeph, s'il n'est pas 100% égal à l'original ça n'a pas d'importance. De toute façon, il y a si peu de (bons) RPGs pour le 83/+.
Je suis en train d'essayer de faire comprendre à spasm que le smc n'est pas une redéfinition de label mais il ne veut rien savoir... Une idée ?

Je n'ai pas envie de repasser à tasm puisque ça me forcerait à convertir à la main mes tiles, et je le trouve moins pratique...
Est-ce que tu as d'abord effacer les vieux labels/variables ? Je suppose que quelque part dans ton code tu avais quelques labels qui s'appelaient map_x/y/w où tu gardais leurs valeurs. Si tu vas utiliser du SMC pour garder ces valeurs, tu n'as pas besoin des vieux labels.
Effectivement, merci smile
Deeph, tu as contacté les developpeurs??

Des nouveautés?
Moi aussi ! Il n'y a pas beaucoup de monde qui est encore actif et je suis très content d'avoir trouvé ce site-ci


Content que tu nous aies trouvés tongue
Non pas encore enfaite j’attends d'avoir quelque chose d'assez évolué pour justifier ma demande (les déplacements des perso surtout).

Là j'ai pas trop le temps d'avancer mais j'ai mis à jour les sources ici : http://deeph.servhome.org/?a=dossiers&d=ftp/TI%20z80/Gurk/ (y'a une version 83 maintenant).
Cool la version ti83 smile

J'ai l'impression que ça se met à ramer au bout d'un certain temps...?

gurk1.gif

Mais en tout cas ton jeu est superbe, trop beau bravo !!
Oui enfaite comme ça décompresse "à la volée" plus on demande des tiles "éloignés" plus ça prend du temps...

Pour le moment je ne sais pas trop comment palier à ça, peut être avec les interruptions...
Je n'ai pas d'idée, j'imagine qu'il est impossible de se passer de compression??

En tout cas la map est vraiment immense (ce qui est probablement la reponse a ma question)...
Oui la carte du monde fait 80*80 tiles et est 60% plus grosse si non compressée en RLE.

Enfin je vais sûrement faire en sorte que les tiles soient décompressés lors d'une interruption dans une matrice de 6*4 tiles qui sera ensuite affichée normalement par le mapper.
Je ne sais pas si la vitesse est très importante, mes si tu utilisais une routine de sprite AND tu pourrais en gagner un peu (car il ne faudrait pas effacer le gbuf). Tu pourrais aussi faire une simple routine pour le faire ( ld hl,gbuf \ ld (hl),0 \ ld de,gbuf+1 \ ld bc,767 \ ldir).

Maintenant je ne peux pas compiler ton jeu, mais j'ai jeté un coup d'oeuil au code et je crois que tu pourrais faire la multiplication d'autre façon plus rapide et qui tard toujour (plus ou moins) la même quantité de temps. Moi, je multiplie premièrement mapY*mapW et après j'ajoute mapX. Mon code est très pareil à ce d'un tutoriel de multiplication/division z80:
; En entrée :
;	H <=> Multiplicande
;	E <=> Multiplicateur
; En sortie :
;	HL <=> Produit de H par E
; Registres affectés
;	F, HL, DE, B
MATH_MUL_8x8 :
    LD L, 0
    LD D, L
    LD B, 8
_MATH_MUL_8x8_1
    ; Multiplication par 2 de HL (décalage d'1 bit vers le haut)
    ADD HL, HL
    JR  nc, _MATH_MUL_8x8_2
    ; Remplacement du bit de débordement par le multiplicateur
    ADD HL, DE	
_MATH_MUL_8x8_2
    DJNZ _MATH_MUL_8x8_1
    RET
Oui c'est vrai que pour les multiplications jusqu'à maintenant je ne me prenais pas trop la tête (j'additionnai autant de fois que nécessaire cheeky). Mais bon même si je gagne du temps sur ça du fait de la décompression j'aurais toujours des ralentissement selon les données recherchées... Les interruptions me semblent donc nécessaire.

Mais merci pour le lien ça a l'air intéressant top
Up

Des nouveautés??
Pas de trop, dernièrement j'ai pas eu trop le temps de coder et lorsque j'en ai eu je le consacrai à zContest.
Maintenant que zContest va bientôt se terminer, tu penses continuer avec Durk ?
J'ai absolument pas le temps de coder en ce moment mais aux prochaines vacances (vers mi-octobre) j'espère pouvoir reprendre tout ça...