Revenir au plan du site

Scroller dans toutes les directions - Courage, fuyons!


Nous devons écrire des routines de scrolling suivant la logique des tableaux de transition de l'article précédent.

Contrairement au scrolling vertical sur écran de 64, il n'est pas possible de se passer d'un test de rebouclage...
                  ...à peu près partout où on touche l'adresse écran!

À chaque fois qu'on décale l'écran vers le haut ou le bas, il faut gérer ce rebouclage. La gestion sur les passages de ligne est la plus facile, on se contente de réajuster avec RES et SET.
NextLineHL ld a,h : add 8 : ld h,a : and #38 : ret nz ; tester le changement de bloc sur n'importe quelle page
ld a,64 : add l : ld l,a : ld a,#C0 : adc h : ld h,a : res 3,h : ret
PreviousLineHL ld a,h : sub 8 : ld h,a : and #38 : cp #38 : ret nz ; test du chgt de bloc (bis)
ld a,l : add #C0 : ld l,a : ld a,#3F : adc h : ld h,a : set 3,h : ret

Quand on décale l'écran vers la droite ou la gauche, il faut aussi gérer ce rebouclage. Et là c'est plus pénible (nous verrons une astuce lors des optimisations). En attendant ce snipet fonctionne partout et sur toutes les lignes.
ld a,h : and %11111000 : ld c,a : Mettre les 5 bits supérieurs de HL dans C
inc hl
ld a,h : and 7 : or c ; ne récupérer que la position dans le bloc et forcer le bloc

C'est pareil pour INC HL que DEC HL que ADD HL,BC

Note : Quand on sait que la ligne est paire ET qu'on veut incrémenter, le RES 3,H fonctionne
inc hl : res 3,h ; sur une ligne paire

Le mieux étant de pouvoir se passer de rebouclage car tester tout le temps finit par coûter du temps machine, il peut être utile de noter qu'utiliser des tiles multiples de la largeur écran (4 pour 64, c'est ok!), la gestion du rebouclage n'est utile que sur la dernière incrémentation. Toutes les autres colonnes n'en ont pas besoin.
Ceci étant dit, vous verrez en plusieurs endroits ces ajustements fastidieux dont il ne faut en oublier aucun. Et maintenant, place au code :)

Le scroll vers la gauche va exécuter la routine d'affichage dans la continuité de son code, car c'est quand on remonte les adresses qu'on dessine en dernier. On aura le même déroulement pour le scroll vers le haut.
ScrollGauche
ld a,(ix+multi.colonne) : or a : jr nz,.goForScroll
ld a,(ix+multi.mapOffset) : and 63 : ret z ; si on est sur la colonne zéro de la tile la plus à gauche... Bye!
.goForScroll
ld a,(ix+multi.HSSR) : bit 2,a : jr nz,.willDraw : add 4 : ld (ix+multi.HSSR),a : ret ; on ne change que le décalage et bye!
.willDraw
add 4 : and 15 : jr nz,.stillSSR
ld hl,(ix+multi.crtcHL) : dec hl : ld (ix+multi.crtcHL),hl ; each word
.stillSSR ld (ix+multi.HSSR),a
ld hl,(ix+multi.adresseDebut) :
ld a,h : and 7 : or l : jr nz,.skip : ld a,h : add 8 : ld h,a : .skip dec hl ; gérer le rebouclage à la décrémentation
ld (ix+multi.adresseDebut),hl
ld a,(ix+multi.colonne) : dec a : and 3 : ld (ix+multi.colonne),a : cp 3 : jr nz,.stillPosx : dec (ix+multi.mapOffset) : .stillPosx
ld hl,(ix+multi.mapOffset) : ld bc,64 : exx ; HL'=adresse de la tile BC'=saut de ligne dans la tileMap
ld de,(ix+multi.adresseDebut) ; DE=haut de la colonne à rafraichir
; accès direct à l'affichage d'une colonne

L'affichage des colonnes, dans la continuité de la routine de scroll à gauche, doit tenir compte de la ligne courante dûe aux scrolls verticaux (avez-vous lu les articles sur le clipping de sprites?)
afficheColonne
;------------------
ld a,(ix+multi.ligne) : or a : jr nz,.clipped
ld yh,16
.loopTiles
calculeAdresseTuileColonne 64
ld bc,#1004 : .loopColumn ld a,(hl) : ld (de),a : call NextLineDE
ld a,l : add c : ld l,a : djnz .loopColumn
dec yh : jr nz,.loopTiles
ret
;----------
.clipped
calculeAdresseTuileLigneColonne 64
ld a,64 : sub (ix+multi.ligne) : rrca : rrca : and 15 : ld b,a : ld c,4 ; la ligne contient un offset de ligne, on divise par 4 pour avoir le nombre de lignes
.loopColumnC1 ld a,(hl) : ld (de),a : call NextLineDE : ld a,l : add c : ld l,a : djnz .loopColumnC1
ld yh,15
call .loopTiles
; dernière tuile clippée
calculeAdresseTuileColonne 0
ld a,(ix+multi.ligne) : rrca : rrca : and 15 : ld b,a : ld c,4 ; la ligne contient un offset de ligne, on divise par 4 pour avoir le nombre de lignes
.loopColumnC3 ld a,(hl) : ld (de),a : call NextLineDE : ld a,l : add c : ld l,a : djnz .loopColumnC3
ret

Enfin, la routine de scroll à droite.
ScrollDroite
ld a,(ix+multi.mapOffset) : and 63 : cp 64-16 : ret z ; gérer le bord droit
ld a,(ix+multi.HSSR) : bit 2,a : jr z,.willDraw : sub 4 : ld (ix+multi.HSSR),a : ret
.willDraw
sub 4 : jr nc,.stillHSSR : jr z,.stillHSSR
ld hl,(ix+multi.crtcHL) : inc hl : ld (ix+multi.crtcHL),hl
ld a,12
.stillHSSR ld (ix+multi.HSSR),a

ld hl,(ix+multi.mapOffset) : ld bc,16 : add hl,bc : ld bc,64 : exx ; HL'=adresse de la tile BC'=saut de ligne dans la tileMap
ld hl,(ix+multi.adresseDebut) : ld bc,64 : ld a,h : and %11111000 : ld d,a : add hl,bc : ld a,h : and 7 : or d ; gère le rebouclage de bloc!
ex hl,de ; DE=haut de la colonne à rafraichir
call afficheColonne
ld a,(ix+multi.colonne) : inc a : and 3 : ld (ix+multi.colonne),a : jr nz,.stillPosx : inc (ix+multi.mapOffset) : .stillPosx
ld hl,(ix+multi.adresseDebut) : inc hl : ld a,h : and 7 : or l : jr nz,.skip : ld a,h : sub 8 : ld h,a : .skip : ld (ix+multi.adresseDebut),hl
ret

La gestion du scrolling vers le bas
;---------------------------------------------------------------------
ScrollBas
;---------------------------------------------------------------------
ld hl,(ix+multi.mapOffset) : ld a,hi(tileMap+48*64) : cp h : ret z ; trop bas, on ne fait rien!
; la tuile en bas sera 16 lignes de tuiles plus bas, soit 1024 octets de tileMap de largeur 64
ld bc,16*64 : add hl,bc : exx ; ajouter 16x64 à l'offset de tuile car on va afficher en bas de l'écran + sauvegarde dans HL'
ld de,(ix+multi.adresseDebut) ; écran carré, calculs simples, le bas revient en haut et vice versa :)
call afficheTuilesHorizontales
; mettre à jour les informations courantes
ld a,(ix+multi.ligne) : add 4 : cp 64 : jr nz,.pasDeChangementDeTuile ; ligne contient l'offset de début de la ligne suivante
ld hl,(ix+multi.mapOffset) : ld bc,64 : add hl,bc : ld (ix+multi.mapOffset),hl : xor a ; passer à la tuile dessous
.pasDeChangementDeTuile
ld (ix+multi.ligne),a ; valider la ligne de tuile
ld hl,(ix+multi.adresseDebut) : call NextLineHL : ld (ix+multi.adresseDebut),hl
ld a,(ix+multi.VSSR) : add #10 : and #70 : ld (ix+multi.VSSR),a : jr nz,.pasDeChangementDeBloc
ld hl,(ix+multi.crtcHL) : ld bc,32 : add hl,bc : ld (ix+multi.crtcHL),hl ; adresse CRTC augmente de 32 mots si le bloc change
.pasDeChangementDeBloc
ret

La gestion du scrolling vers le haut
ScrollHaut
;---------------------------------------------------------------------
ld hl,(ix+multi.mapOffset) : ld a,hi(tileMap) : cp h : jr nz,.okPourLeScroll ; si on est près du début on doit contrôler le "Y"
ld a,l : cp 63 : jr nc,.okPourLeScroll ; si on est sur la première ligne, on doit regarder la ligne de tuile!
ld a,(ix+multi.ligne) : or a : ret z ; tout en haut, aurevoir!
.okPourLeScroll ; on peut scroller!

; mettre à jour les informations courantes
ld a,(ix+multi.ligne) : sub 4 : jr nc,.pasDeChangementDeTuile ; ligne contient l'offset de début de la ligne suivante
ld hl,(ix+multi.mapOffset) : ld bc,-64 : add hl,bc : ld (ix+multi.mapOffset),hl : ld a,60 ; passer à la dernière ligne de la tuile dessous
.pasDeChangementDeTuile
ld (ix+multi.ligne),a ; valider la ligne de tuile
ld hl,(ix+multi.adresseDebut) : call PreviousLineHL : ld (ix+multi.adresseDebut),hl
ld a,(ix+multi.VSSR) : sub #10 : and #70 : ld (ix+multi.VSSR),a : cp #70 : jr nz,.pasDeChangementDeBloc
ld hl,(ix+multi.crtcHL) : ld bc,-32 : add hl,bc : ld (ix+multi.crtcHL),hl ; adresse CRTC baisse de 32 mots si le bloc change
.pasDeChangementDeBloc
; on affiche après en remontant
ld hl,(ix+multi.mapOffset) : exx
ld de,(ix+multi.adresseDebut)

L'affichage des lignes en tenant compte d'un éventuel décalage en colonne dû aux scrolls horizontaux.
afficheTuilesHorizontales
;---------------------------
ld a,(ix+multi.colonne) : or a : jr nz,.routineClippee
ld yh,16
.loop
calculeAdresseTuileLigne 1
ldi 3
ld a,d : and %11111000
ldi : ld c,a : ld a,d : and 7 : or c : ld d,a ; rebouclage de bloc...
dec yh : jr nz,.loop
ret
;-----------------
.routineClippee
;-----------------
ld yh,15 ; on aura 15 sprites entiers et 2 sprites partiels
calculeAdresseTuileLigneColonne 1
ld a,4 : sub (ix+multi.colonne) : ld c,a
ld b,0 : ldir : dec de : ld a,d : inc de : and %11111000 : ld c,a : ld a,d : and 7 : or c : ld d,a ; rebouclage de bloc...
.loop7
calculeAdresseTuileLigne 1
ldi 3
ld a,d : and %11111000
ldi : ld c,a : ld a,d : and 7 : or c : ld d,a ; rebouclage de bloc...
dec yh : jr nz,.loop7
calculeAdresseTuileLigne 0
ld c,(ix+multi.colonne)
ld b,0 : ldir : dec de : ld a,d : inc de : and %11111000 : ld c,a : ld a,d : and 7 : or c : ld d,a ; rebouclage de bloc...
ret

Tout le reste est déjà prêt, ne manque que le test des touches avec l'appel des fonctions et c'est parti :) (besoin des fichiers mapMulti.bin et mapMulti.tilemap)
BUILDSNA : BANKSET 0
SNASET CPC_TYPE,4 ; modèle 6128+ conseillé
ORG #100 : RUN #100
;*** RMR2 tags + macro ***
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

struct multi
mapOffset defw
HSSR defb ; 0-12
VSSR defb ; #00-#70
colonne defb ; 0-3 dans la tuile
ligne defb ; 0-60 par pas de 4 dans la tuile
adresseDebut defw
crtc12 defb ; cache des bits de bank
crtcHL defw ; adresse CRTC
endstruct
; définition des constantes pour le curseur
OCTET_CURSEUR_HAUT   equ matriceClavier+0 : BIT_CURSEUR_HAUT   equ 1
OCTET_CURSEUR_DROITE equ matriceClavier+0 : BIT_CURSEUR_DROITE equ 2
OCTET_CURSEUR_BAS    equ matriceClavier+0 : BIT_CURSEUR_BAS    equ 4
OCTET_CURSEUR_GAUCHE equ matriceClavier+1 : BIT_CURSEUR_GAUCHE equ 1

ld bc,#7F00+%10001100+%00 : out (c),c ; MODE 0
call UnlockAsic : RMR2 ASICON
ld hl,palettePlus : ld de,#6400 : ld bc,32 : ldir : ld hl,#000 : ld (#6420),hl ; +border noir

ld bc,#BC00+1 : out (c),c : ld bc,#BD00+32 : out (c),c ; Notre map fait 128 pixels de large, adaptez selon VOS besoins
ld bc,#BC00+2 : out (c),c : ld bc,#BD00+42 : out (c),c ; Centrer l'écran en X
ld bc,#BC00+6 : out (c),c : ld bc,#BD00+32 : out (c),c ; Hauteur de l'écran visible en lignes de caractères
ld bc,#BC00+7 : out (c),c : ld bc,#BD00+34 : out (c),c ; Centrer l'écran en Y
ld bc,#BC00+12 : out (c),c : ld bc,#BD30 : out (c),c ; adresse par défaut
ld bc,#BC00+13 : out (c),c : ld bc,#BD00 : out (c),c

ld ix,ecran1 : ld a,#C0 : call InitEcran
LaBoucle
call lectureMatriceClavier
call WaitVBL
ld ix,ecran1 ; notre structure écran par défaut pour aller scroller
call UpdateHardware

ld a,(OCTET_CURSEUR_BAS) : and BIT_CURSEUR_BAS : call z,ScrollBas
ld a,(OCTET_CURSEUR_HAUT) : and BIT_CURSEUR_HAUT : call z,ScrollHaut
ld a,(OCTET_CURSEUR_DROITE) : and BIT_CURSEUR_DROITE : call z,ScrollDroite
ld a,(OCTET_CURSEUR_GAUCHE) : and BIT_CURSEUR_GAUCHE : call z,ScrollGauche
jp LaBoucle

lectureMatriceClavier
ld hl,matriceClavier
ld bc,#f782
out (c),c
ld bc,#f40e
ld e,b
out (c),c
ld bc,#f6c0
ld d,b
out (c),c
out (c),0
ld bc,#f792
out (c),c
ld a,#40
ld c,d
.loop ld b,d
out (c),a ; sélectionner la ligne
ld b,e
ini ; lire et stocker dans notre tableau
inc a
inc c
jr nz,.loop
ld bc,#f782
out (c),c
ret

matriceClavier defs 10,#FF
;---------------------------------------------------------------------
MACRO calculeAdresseTuile increment
exx : ld a,(hl) ; index de la tile dans A
if {increment}==0 : elseif {increment}==1 : inc hl : else : add hl,bc : endif
exx ; index de la tile dans A / HL'=tileMap
ld hl,tuiles : ld b,a : ld c,0 : srl bc : srl bc : add hl,bc ; HL=adresse du début de la tuile
MEND
MACRO calculeAdresseTuileLigne increment
calculeAdresseTuile {increment}
ld a,(ix+multi.ligne) : add l : ld l,a ; HL=adresse du début de la tuile à la bonne ligne
MEND
MACRO calculeAdresseTuileColonne increment
calculeAdresseTuile {increment}
ld a,(ix+multi.colonne) : add l : ld l,a ; HL=adresse du début de la tuile à la bonne colonne
MEND
MACRO calculeAdresseTuileLigneColonne increment
calculeAdresseTuile {increment}
ld a,(ix+multi.ligne) : add (ix+multi.colonne) : add l : ld l,a ; HL=adresse du début de la tuile à la bonne ligne ET bonne colonne
MEND
;---------------------------------------------------------------------
ScrollGauche
;---------------------------------------------------------------------
ld a,(ix+multi.colonne) : or a : jr nz,.goForScroll
ld a,(ix+multi.mapOffset) : and 63 : ret z ; si on est sur la colonne zéro de la tile la plus à gauche... Bye!
.goForScroll
ld a,(ix+multi.HSSR) : bit 2,a : jr nz,.willDraw : add 4 : ld (ix+multi.HSSR),a : ret ; on ne change que le décalage et bye!
.willDraw
add 4 : and 15 : jr nz,.stillSSR
ld hl,(ix+multi.crtcHL) : dec hl : ld (ix+multi.crtcHL),hl ; each word
.stillSSR ld (ix+multi.HSSR),a
ld hl,(ix+multi.adresseDebut) :
ld a,h : and 7 : or l : jr nz,.skip : ld a,h : add 8 : ld h,a : .skip dec hl ; gérer le rebouclage à la décrémentation
ld (ix+multi.adresseDebut),hl
ld a,(ix+multi.colonne) : dec a : and 3 : ld (ix+multi.colonne),a : cp 3 : jr nz,.stillPosx : dec (ix+multi.mapOffset) : .stillPosx
ld hl,(ix+multi.mapOffset) : ld bc,64 : exx ; HL'=adresse de la tile BC'=saut de ligne dans la tileMap
ld de,(ix+multi.adresseDebut) ; DE=haut de la colonne à rafraichir
; accès direct à l'affichage d'une colonne
;------------------
afficheColonne
;------------------
ld a,(ix+multi.ligne) : or a : jr nz,.clipped
ld yh,16
.loopTiles
calculeAdresseTuileColonne 64
ld bc,#1004 : .loopColumn ld a,(hl) : ld (de),a : call NextLineDE
ld a,l : add c : ld l,a : djnz .loopColumn
dec yh : jr nz,.loopTiles
ret
;----------
.clipped
calculeAdresseTuileLigneColonne 64
ld a,64 : sub (ix+multi.ligne) : rrca : rrca : and 15 : ld b,a : ld c,4
.loopColumnC1 ld a,(hl) : ld (de),a : call NextLineDE : ld a,l : add c : ld l,a : djnz .loopColumnC1
ld yh,15
call .loopTiles
; dernière tuile clippée
calculeAdresseTuileColonne 0
ld a,(ix+multi.ligne) : rrca : rrca : and 15 : ld b,a : ld c,4
.loopColumnC3 ld a,(hl) : ld (de),a : call NextLineDE : ld a,l : add c : ld l,a : djnz .loopColumnC3
ret
;---------------------------------------------------------------------
ScrollDroite
;---------------------------------------------------------------------
ld a,(ix+multi.mapOffset) : and 63 : cp 64-16 : ret z ; gérer le bord droit
ld a,(ix+multi.HSSR) : bit 2,a : jr z,.willDraw : sub 4 : ld (ix+multi.HSSR),a : ret
.willDraw
sub 4 : jr nc,.stillHSSR : jr z,.stillHSSR
ld hl,(ix+multi.crtcHL) : inc hl : ld (ix+multi.crtcHL),hl
ld a,12
.stillHSSR ld (ix+multi.HSSR),a

ld hl,(ix+multi.mapOffset) : ld bc,16 : add hl,bc : ld bc,64 : exx ; HL'=adresse de la tile BC'=saut de ligne dans la tileMap
ld hl,(ix+multi.adresseDebut) : ld bc,64 : ld a,h : and %11111000 : ld d,a : add hl,bc : ld a,h : and 7 : or d ; gère le rebouclage de bloc!
ex hl,de ; DE=haut de la colonne à rafraichir
call afficheColonne
ld a,(ix+multi.colonne) : inc a : and 3 : ld (ix+multi.colonne),a : jr nz,.stillPosx : inc (ix+multi.mapOffset) : .stillPosx
ld hl,(ix+multi.adresseDebut) : inc hl : ld a,h : and 7 : or l : jr nz,.skip : ld a,h : sub 8 : ld h,a : .skip : ld (ix+multi.adresseDebut),hl
ret
;---------------------------------------------------------------------
ScrollBas
;---------------------------------------------------------------------
ld hl,(ix+multi.mapOffset) : ld a,hi(tileMap+48*64) : cp h : ret z ; trop bas, on ne fait rien!
; la tuile en bas sera 16 lignes de tuiles plus bas, soit 1024 octets de tileMap de largeur 64
ld bc,16*64 : add hl,bc : exx ; ajouter 16x64 à l'offset de tuile car on va afficher en bas de l'écran + sauvegarde dans HL'
ld de,(ix+multi.adresseDebut) ; écran carré, calculs simples, le bas revient en haut et vice versa :)
call afficheTuilesHorizontales
; mettre à jour les informations courantes
ld a,(ix+multi.ligne) : add 4 : cp 64 : jr nz,.pasDeChangementDeTuile ; ligne contient l'offset de début de la ligne suivante
ld hl,(ix+multi.mapOffset) : ld bc,64 : add hl,bc : ld (ix+multi.mapOffset),hl : xor a ; passer à la tuile dessous
.pasDeChangementDeTuile
ld (ix+multi.ligne),a ; valider la ligne de tuile
ld hl,(ix+multi.adresseDebut) : call NextLineHL : ld (ix+multi.adresseDebut),hl
ld a,(ix+multi.VSSR) : add #10 : and #70 : ld (ix+multi.VSSR),a : jr nz,.pasDeChangementDeBloc
ld hl,(ix+multi.crtcHL) : ld bc,32 : add hl,bc : ld (ix+multi.crtcHL),hl ; adresse CRTC augmente de 32 mots si le bloc change
.pasDeChangementDeBloc
ret
;---------------------------------------------------------------------
ScrollHaut
;---------------------------------------------------------------------
ld hl,(ix+multi.mapOffset) : ld a,hi(tileMap) : cp h : jr nz,.okPourLeScroll ; si on est près du début on doit contrôler le "Y"
ld a,l : cp 63 : jr nc,.okPourLeScroll ; si on est sur la première ligne, on doit regarder la ligne de tuile!
ld a,(ix+multi.ligne) : or a : ret z ; tout en haut, aurevoir!
.okPourLeScroll ; on peut scroller!

; mettre à jour les informations courantes
ld a,(ix+multi.ligne) : sub 4 : jr nc,.pasDeChangementDeTuile ; ligne contient l'offset de début de la ligne suivante
ld hl,(ix+multi.mapOffset) : ld bc,-64 : add hl,bc : ld (ix+multi.mapOffset),hl : ld a,60 ; passer à la dernière ligne de la tuile dessous
.pasDeChangementDeTuile
ld (ix+multi.ligne),a ; valider la ligne de tuile
ld hl,(ix+multi.adresseDebut) : call PreviousLineHL : ld (ix+multi.adresseDebut),hl
ld a,(ix+multi.VSSR) : sub #10 : and #70 : ld (ix+multi.VSSR),a : cp #70 : jr nz,.pasDeChangementDeBloc
ld hl,(ix+multi.crtcHL) : ld bc,-32 : add hl,bc : ld (ix+multi.crtcHL),hl ; adresse CRTC baisse de 32 mots si le bloc change
.pasDeChangementDeBloc
; on affiche après en remontant
ld hl,(ix+multi.mapOffset) : exx
ld de,(ix+multi.adresseDebut)
; on continue directement dans l'affichage des lignes
;---------------------------
afficheTuilesHorizontales
;---------------------------
ld a,(ix+multi.colonne) : or a : jr nz,.routineClippee
ld yh,16
.loop
calculeAdresseTuileLigne 1
ldi 3
ld a,d : and %11111000
ldi : ld c,a : ld a,d : and 7 : or c : ld d,a ; rebouclage de bloc...
dec yh : jr nz,.loop
ret
;-----------------
.routineClippee
;-----------------
ld yh,15 ; on aura 15 sprites entiers et 2 sprites partiels
calculeAdresseTuileLigneColonne 1
ld a,4 : sub (ix+multi.colonne) : ld c,a
ld b,0 : ldir : dec de : ld a,d : inc de : and %11111000 : ld c,a : ld a,d : and 7 : or c : ld d,a ; rebouclage de bloc...
.loop7
calculeAdresseTuileLigne 1
ldi 3
ld a,d : and %11111000
ldi : ld c,a : ld a,d : and 7 : or c : ld d,a ; rebouclage de bloc...
dec yh : jr nz,.loop7
calculeAdresseTuileLigne 0
ld c,(ix+multi.colonne)
ld b,0 : ldir : dec de : ld a,d : inc de : and %11111000 : ld c,a : ld a,d : and 7 : or c : ld d,a ; rebouclage de bloc...
ret
;---------------------------------------------------------------------
InitEcran
; IX = structure buffer
; A = poids fort de la page vidéo
ld hl,tileMap
ld (ix+multi.mapOffset),hl
ld hl,0
ld (ix+multi.HSSR),h
ld (ix+multi.VSSR),h
ld (ix+multi.colonne),h
ld (ix+multi.ligne),h
ld (ix+multi.crtcHL),hl
ld h,a : ld (ix+multi.adresseDebut),hl
rrca : rrca : ld (ix+multi.crtc12),a

; Afficher les tuiles sur tout l'écran

ld de,(ix+multi.adresseDebut)
ld ix,tileMap ; on n'utilise plus la structure à partir de là
ld yh,16 ; 16 tuiles en hauteur
afficheLigne
ld yl,16 ; nombre de tuiles en largeur
push de ; sauvegarder l'adresse de début de ligne de l'écran
afficheTuile
push de ; sauvegarder l'adresse du début de la tuile à l'écran
ld h,(ix+0) : inc ix : ld l,0 : srl hl : srl hl ; x 256 / 4 c'est la taille de nos tuiles (64 octets)
ld bc,tuiles : add hl,bc ; on a l'adresse de la tile
ld a,16
afficheLigneTuile
push de : ldi 4 : pop de
ld bc,#800 : ex hl,de : add hl,bc : jr nc,.novf : ld bc,64-#4000 : add hl,bc : .novf ex hl,de
dec a : jr nz,afficheLigneTuile
pop hl : ld bc,4 : add hl,bc : ex hl,de ; se placer juste à côté de la tuile précédente
dec yl : jr nz,afficheTuile
ld bc,48 : add ix,bc ; revenir à la ligne de tuile (64-16 dans notre cas)
pop hl : ld bc,128 : add hl,bc : ex hl,de ; se placer sous les tuiles à gauche
dec yh : jr nz,afficheLigne
ret
;---------------------------------------------------------------------
NextLineHL ld a,h : add 8 : ld h,a : and #38 : ret nz ; tester le changement de bloc sur n'importe quelle page
ld a,64 : add l : ld l,a : ld a,#C0 : adc h : ld h,a : res 3,h : ret
PreviousLineHL ld a,h : sub 8 : ld h,a : and #38 : cp #38 : ret nz ; test du chgt de bloc (bis)
ld a,l : add #C0 : ld l,a : ld a,#3F : adc h : ld h,a : set 3,h : ret
NextLineDE ld a,d : add 8 : ld d,a : and #38 : ret nz ; tester le changement de bloc sur n'importe quelle page
ld a,64 : add e : ld e,a : ld a,#C0 : adc d : ld d,a : res 3,d : ret
;---------------------------------------------------------------------
UpdateHardware
RMR2 ASICON
ld a,(ix+multi.HSSR) : or (ix+multi.VSSR) : or #80 : ld (#6804),a
ld hl,(ix+multi.crtcHL) : ld a,h : and 3 : ld h,a : ld a,(ix+multi.crtc12) : or h : ld bc,#BC00+12 : out (c),c : inc b : out (c),a
inc c : dec b : out (c),c : inc b : out (c),l
RMR2 ASICOFF
ret
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
ret

WaitVBL
ld b,#F5 : noVBL in a,(c) : rra : jr c,noVBL
VBL in a,(c) : rra : jr nc,VBL : ret

paletteplus: defw #323,#646,#5B3,#967,#A57,#B95,#6E4,#9B7,#C89,#ABA,#CE2,#DB8,#DB9,#EC6,#EC9,#EED
align 256 : tuiles incbin 'mapMulti.bin'
align 256 : tileMap include 'mapMulti.tilemap'
; et on se déclare deux structures pour un double buffer
struct multi ecran1
struct multi ecran2

Et voici notre scroll multi-directionnel


On se retrouve l'année prochaine pour le passage en double buffer? Des optimisations?