Bon j'ai avancé. Cette routine est partagée en deux parties qui assemblent des bouts de glb_d2 et glb_d3 pour obtenir les bons offset dans divers tableaux
Code:
[5] 5939 ldd glb_d2 * movea.w d2,d0 ; y_pos
; unlike original no interlace of background
; and foreground in tilemap * add.w d0,d0
[2] 5941 anda #$0F
[2] 5943 andb #$80 * andi.w #$F00,d0 ; rounded 2*y_pos
[5] 5948 std glb_d0
[5] 5953 ldd glb_d3 * movea.w d3,d1 ; x_pos
_lsrd
[2] 5955 lsra
[2] 5957 rorb
_lsrd * lsr.w #3,d1
[2] 5959 lsra
[2] 5961 rorb
[5] 5966 stb @d4_b * movea.w d1,d4
_lsrd
[2] 5968 lsra
[2] 5970 rorb
_lsrd
[2] 5972 lsra
[2] 5974 rorb
_lsrd
[2] 5976 lsra
[2] 5978 rorb
_lsrd ; shift only by 6 (64px not 128px) * lsr.w #4,d1 ; x_pos/128 = x_of_chunk
[2] 5980 lsra
[2] 5982 rorb
[2] 5984 anda #0
[2] 5986 andb #$7F * andi.w #$7F,d1
[6] 5992 addd glb_d0 * add.w d1,d0 ; d0 is relevant chunk ID now * moveq #-1,d1
[6] 5998 ldx glb_map_chunk_adr * clr.w d1 ; d1 is now $FFFF0000 = Chunk_Table
[8] 6006 leax d,x * lea (Level_Layout).w,a1
[4] 6010 lda ,x * move.b (a1,d0.w),d1 ; move 128*128 chunk ID to d1
TOTAL=76 cycles
et
Code:
[2] 6052 andb #0 ; shift right to get x128
_asrd ; instead of using a LUT * add.w d1,d1
[2] 6054 asra
[2] 6056 rorb
[8] 6064 leax d,x * move.w word_1E5D0(pc,d1.w),d1
[4] 6068 ldb glb_d2_b * movea.w d2,d0 ; y_pos
[2] 6070 andb #$70 * andi.w #$70,d0
[3] 6073 abx * add.w d0,d1
[2] 6075 ldb #0
@d4_b equ *-1
[2] 6077 andb #$E * andi.w #$E,d4 ; x_pos/8
[3] 6080 abx * add.w d4,d1
; x is loaded with address of block ID * movea.l d1,a1 ; address of block ID
TOTAL=28 cycles
A elles deux, cela coute 104 cycles. C'est peu, mais comme la routine est appelée super souvent, la routine Find_Tile se retrouve en 3e position (10% du temps passé dedans) juste après le remplissage des tuiles lors d'un profiling de 30s de la course de Sonic sur tous les tableaux vers la droite. (
https://www.cjoint.com/doc/22_11/LKgpwL ... .html#7DEB)
La routine en soi est déjà bien optimisée, mais c'est une traduction fidèle de ce que fait le code 68000. Là dedans deux choses me semblent optimisables: les décalages, certes peu couteux sur 6809, mais très nombreux, et les accès mémoire 16 bits qui sont vraiment lents. Tout va plus vite si on peut travailler au max de registre à registre sans passer par la mémoire (cf le glb_d0 qui sert de temporaire).
J'ai décidé de me focaliser sur les décalages. Le 1er décalage intéressant est à droite six fois sur 16bits, soit 24 cycles. C'est pas beaucoup mais cela coute 1/3 du temps de calcul, alors qu'on ne retient de ces 16 bits que 7 bits seulement. On pourrait convertir ce décalage à droite 6 fois en 2 décalages à gauche et retrouver ces mêmes bits non pas sur B, mais sur A. C'est ce que je fais dans cette réécriture du 1er calcul:
Code:
[6] 5940 ldx glb_map_chunk_adr
[5] 5945 ldd glb_d3
_lsld
[2] 5947 lslb
[2] 5949 rola
_lsld
[2] 5951 lslb
[2] 5953 rola
[2] 5955 anda #$7F
[5] 5960 leax a,x
[5] 5965 ldd glb_d2
[2] 5967 anda #$0F
[2] 5969 andb #$80
[8] 5977 lda d,x
TOTAL=43 cycles
On tombe à 43 cycles au lieu de 76. C'est vachement mieux. Le hic est qu'alors on a pas @d4_b qui est calculé pour la 2e partie. Il faut donc adapter le 2e calcul en conséquence en le recalculant depuis glb_d3. Mais là on peut retrouver la même valeur sans travailler sur 16bits, mais sur la partie basse de glb_d3 qui contient tout les bits recherchés. J'en profite pour l'ajouter directement à X sans le combiner à A pour rester au max sur des calculs 8 bits. Ca donne ceci:
Code:
[4] 6021 ldb glb_d2_b
[2] 6023 andb #$70
[3] 6026 abx
[4] 6030 ldb glb_d3+1
[2] 6032 lsrb
[2] 6034 andb #%00011100
_lsrd
[2] 6036 lsra
[2] 6038 rorb
[8] 6046 leax d,x
TOTAL=25 cycles
Et on gagne même 3 cycles par rapport au calcul de cette 2e partie par rapport à l'original. Au final ces deux calculs font en 68 cycles ce qu'on faisait en 104. Ca n'a l'air de rien, mais dans le profiling, cette méthode tombe alors à 7.67% du temps. Ca nous fait entre
2 et 3% de gain (
https://www.cjoint.com/doc/22_11/LKgpiw ... .html#7DEB)
J'ai mis le code source dans le ZIP ci-joint. Le hic, c'est que le calcul n'est plus fait dans l'ordre du 68000 et les commentaires associés ne sont pas bon. Aussi j'ai utilisé un "if 0" pour garder le code d'origine commenté pour référence.
Fichier(s) joint(s):
collision.zip [4.63 Kio]
Téléchargé 72 fois
Une dernière note: les hotspots #1 (25% du temps) et #2 (10% du temps) font partis de la routine d'affichage des tuiles. La partie à 25% correspond au cas ou STB écrit un 0 en $E7E6. L'autre correspond au cas où B écrit une vrai numéro de page et qu'on saute à la routine de sprite compilé (JSR ,x). Ca fait quand même pas mal de cas où on trouve un 0. Il faudrait que je vois s'ils sont consécutifs ou éparpillés au hasard. S'ils sont consécutifs, on pourrait imaginer détecter plusieurs tuiles consécutivement vides rapidement (en ajoutant ORB 1,U + ORB 5,U + ORB 9,U pur 4 tuiles consécutives) et sauter au dessus de plein de tuiles vides d'un coup. Ca pourrait faire gagner pas mal de temps sur la traversée de la carte.