Transformation de sprites hard à la volée à partir de données uniquesContrairement aux bornes d'arcade et consoles, les sprites hard de l'ASIC ne s'affiche que dans un seul sens. Il n'est pas possible de les tourner ou de les inverser sur un axe. À minima deux solutions sont possibles : - stocker tous les sprites nécéssaires - créer des routines d'affichage qui s'occupent des transformations La rotation de 180° est la plus triviale, on décode dans l'ordre et on écrit dans l'ordre inverse complet. Il faut donc commencer à écrire dans le dernier octet du sprite, au poids faible 255. decrunchSpriteRotation180 ; HL = source alignée sur 128 octets ; DE = destination dans l'ASIC ld b,hi(tableDecale4) ld e,255 .loop repeat 8 ld a,(hl) : inc l : ld (de),a : dec e ld c,a : ld a,(bc) : ld (de),a : if x==7 : ret z : endif : dec e rend jr .loop retPour une inversion en miroir, soit on inverse la lecture de la source, soit on inverse l'écriture dans la destination, sur chaque ligne. En modifiantla routine de décrunch présentée dans la page sur la [ compression delta ], on aurait un code comme ceci : decrunchSpriteMiroirHorizontal ; HL = source alignée sur 128 octets ; DE = destination dans l'ASIC ld b,hi(tableDecale4) ld e,15 ; on part de la FIN de la ligne destination .loop repeat 8,x ld a,(hl) : inc l : ld (de),a : dec e ld c,a : ld a,(bc) : ld (de),a if x<7 : dec e : else ; on décrémente SAUF sur le dernier pixel écrit ld a,e : add 31 : ld e,a ; on revient au point de départ, +16 pour être à la fin de la ligne suivante :) endif rend ; la dernière comparaison change, on ne teste plus le retour à zéro mais le dépassement de 255 jr nc,.loop retLe pendant du miroir horizontal est le miroir vertical decrunchSpriteMiroirVertical ; HL = source alignée sur 128 octets ; DE = destination dans l'ASIC ld b,hi(tableDecale4) ld e,240 ; on part du début de la dernière ligne destination .loop repeat 8,x ld a,(hl) : inc l : ld (de),a : inc e ld c,a : ld a,(bc) : ld (de),a if x<7 : inc e : else ; on incrémente SAUF sur le dernier pixel écrit ld a,e : sub 31 : ld e,a ; on revient au point de départ, -16 pour être au début de la ligne précédente :) endif rend ; on teste le débordement inférieur à zéro jr nc,.loop retLes deux dernières rotations sont les plus coûteuses ( presque 2400 nops contre moins de 1650 pour les autres ) Voici la rotation 90° horaire. decrunchSpriteRotation90 ; HL = source alignée sur 128 octets ; DE = destination dans l'ASIC ld b,hi(tableDecale4) ld e,15 ; on part de la FIN de la ligne destination .loop repeat 8,x ld a,(hl) : ld c,a : inc l : ld (de),a : ld a,e : add 16 : ld e,a ; pixel du dessous ld a,(bc) : ld (de),a if x<7 : ld a,e : add 16 : ld e,a : else ; on passe au pixel du dessous sauf le dernier de la colonne ld a,e : sub 1+240 : ld e,a ; on revient au point de départ, -1 pour être sur le pixel de la colonne précédente endif rend ; la dernière comparaison change, on teste le débordement inférieur à zéro jr nc,.loop retEt la rotation à 270° pour terminer. decrunchSpriteRotation270 ; HL = source alignée sur 128 octets ; DE = destination dans l'ASIC ld b,hi(tableDecale4) ld e,240 ; on part du coin en bas à gauche .loop repeat 8,x ld a,(hl) : ld c,a : inc l : ld (de),a : ld a,e : sub 16 : ld e,a ; pixel du dessous ld a,(bc) : ld (de),a if x<7 : ld a,e : sub 16 : ld e,a : else ; on passe au pixel du dessus sauf le dernier de la colonne ld a,e : add 1+240 : ld e,a ; on revient au point de départ, +1 pour être sur le pixel de la colonne suivante endif rend ; on teste le débordement à 255 jr nc,.loop retAllez, on met tout ça en pratique avec l'éternel programme de test :) Il vous faudra télécharger le [ mini sprite ] pour l'assembler startingindex 0 buildsna SNASET CPC_TYPE,4 ; 6128+ bankset 0 org #38 ei : ret org #100 run #100;*** RMR2 tags *** ASICOFF equ 0 : ROM0000 equ 0 : ROM4000 equ %01000 : ROM8000 equ %10000 : ASICON equ %11000 ROM0 equ 0 : ROM1 equ 1 : ROM2 equ 2 : ROM3 equ 3 : ROM4 equ 4 : ROM5 equ 5 : ROM6 equ 6 : ROM7 equ 7 macro RMR2 tags : ld a,{tags}+%10100000 : ld b,#7F : out (c),a : mend ld sp,#100 ; la pile avant le code ld bc,#7F80+%1100 : out (c),c ; MODE 0 UnlockAsic ld bc,#BCFF out (c),c out (c),0 ld hl,%1001000011101010 .loop out (c),c ld a,h:rlca:ld h,l:ld l,a srl c:res 3,c and #88 or c ld c,a cp #4D jr nz,.loop ld a,#CD out (c),a : out (c),a RMR2 ASICON ld hl,#FFF : ld (#6422),hl ei ; activer 6 sprites en ratio mode 1 zoomé ld a,%1110 ld hl,#6004 : ld b,6 : ld de,8 .setHsp ld (hl),a : add hl,de : djnz .setHsp ; il faut positionner nos sprites à minima à l'initialisation ld hl,0 : ld bc,80 ld (#6000+8*0),hl : add hl,bc ld (#6000+8*1),hl : add hl,bc ld (#6000+8*2),hl : add hl,bc ld (#6000+8*3),hl : add hl,bc ld (#6000+8*4),hl : add hl,bc ld (#6000+8*5),hl ld hl,fragola : ld de,#4000 : call decrunchSprite ld hl,fragola : ld d,#41 : call decrunchSpriteMiroirHorizontal ld hl,fragola : ld d,#42 : call decrunchSpriteMiroirVertical ld hl,fragola : ld d,#43 : call decrunchSpriteRotation90 ld hl,fragola : ld d,#44 : call decrunchSpriteRotation180 ld hl,fragola : ld d,#45 : call decrunchSpriteRotation270 jr $ align 128 : fragola incbin 'lemon.bin' decrunchSpriteRotation180 ; HL = source alignée sur 128 octets ; DE = destination dans l'ASIC ld b,hi(tableDecale4) ld e,255 .loop repeat 8,x ld a,(hl) : inc l : ld (de),a : dec e ld c,a : ld a,(bc) : ld (de),a : if x==7 : ret z : endif : dec e rend jr .loop decrunchSpriteMiroirHorizontal ; HL = source alignée sur 128 octets ; DE = destination dans l'ASIC ld b,hi(tableDecale4) ld e,15 ; on part de la FIN de la ligne destination .loop repeat 8,x ld a,(hl) : inc l : ld (de),a : dec e ld c,a : ld a,(bc) : ld (de),a if x<7 : dec e : else ; on décrémente SAUF sur le dernier pixel écrit ld a,e : add 31 : ld e,a ; on revient au point de départ, +16 pour être à la fin de la ligne suivante :) endif rend ; la dernière comparaison change, on ne teste plus le retour à zéro mais le dépassement de 255 jr nc,.loop ret decrunchSpriteMiroirVertical ; HL = source alignée sur 128 octets ; DE = destination dans l'ASIC ld b,hi(tableDecale4) ld e,240 ; on part du début de la dernière ligne destination .loop repeat 8,x ld a,(hl) : inc l : ld (de),a : inc e ld c,a : ld a,(bc) : ld (de),a if x<7 : inc e : else ; on incrémente SAUF sur le dernier pixel écrit ld a,e : sub 31 : ld e,a ; on revient au point de départ, -16 pour être au début de la ligne précédente :) endif rend ; on teste le débordement inférieur à zéro jr nc,.loop ret decrunchSpriteRotation90 ; HL = source alignée sur 128 octets ; DE = destination dans l'ASIC ld b,hi(tableDecale4) ld e,15 ; on part de la FIN de la ligne destination .loop repeat 8,x ld a,(hl) : ld c,a : inc l : ld (de),a : ld a,e : add 16 : ld e,a ; pixel du dessous ld a,(bc) : ld (de),a if x<7 : ld a,e : add 16 : ld e,a : else ; on passe au pixel du dessous sauf le dernier de la colonne ld a,e : sub 1+240 : ld e,a ; on revient au point de départ, -1 pour être sur le pixel de la colonne précédente endif rend ; la dernière comparaison change, on teste le débordement inférieur à zéro jr nc,.loop ret decrunchSpriteRotation270 ; HL = source alignée sur 128 octets ; DE = destination dans l'ASIC ld b,hi(tableDecale4) ld e,240 ; on part du coin en bas à gauche .loop repeat 8,x ld a,(hl) : ld c,a : inc l : ld (de),a : ld a,e : sub 16 : ld e,a ; pixel du dessous ld a,(bc) : ld (de),a if x<7 : ld a,e : sub 16 : ld e,a : else ; on passe au pixel du dessus sauf le dernier de la colonne ld a,e : add 1+240 : ld e,a ; on revient au point de départ, +1 pour être sur le pixel de la colonne suivante endif rend ; on teste le débordement à 255 jr nc,.loop ret startingindex 0 align 256 tableDecale4 repeat 256,x defb x>>4 rend decrunchSprite ; HL = source alignée sur 128 octets ; DE = destination dans l'ASIC ld b,hi(tableDecale4) .loop repeat 8 ld a,(hl) : inc l : ld (de),a : inc e ld c,a : ld a,(bc) : ld (de),a : inc e rend jr nz,.loop ret Vous devriez voir apparaitre dans l'ordre, le sprite d'origine, les miroirs et enfin les 3 rotations 
Roudoudou CPCrulez[Content Management System] v8.732-desktop Page créée en 656 millisecondes et consultée 5 foisL'Amstrad CPC est une machine 8 bits à base d'un Z80 à 4MHz. Le premier de la gamme fut le CPC 464 en 1984, équipé d'un lecteur de cassettes intégré il se plaçait en concurrent du Commodore C64 beaucoup plus compliqué à utiliser et plus cher. Ce fut un réel succès et sorti cette même années le CPC 664 équipé d'un lecteur de disquettes trois pouces intégré. Sa vie fut de courte durée puisqu'en 1985 il fut remplacé par le CPC 6128 qui était plus compact, plus soigné et surtout qui avait 128Ko de RAM au lieu de 64Ko. |
|