Revenir au plan du site

Un premier scrolling hard horizontal


Vous rappelez-vous des Rubidouilles dans le magazine Amstrad 100%? Moi oui! D'autant plus qu'à l'époque, je n'avais pas d'assembleur, en conséquence de quoi je devais me farcir les opcodes à la mimine, sauts relatifs compris. Mais il est une routine de Rubi que j'avais pris soigneusement le temps de poker, d'abord sur papier. C'est celle du scrolling hard pages [66] et [67] du numéro 25
C'est un équivalent de cette routine que nous allons travailler aujourd'hui. Nous enlèverons le test de touche espace (rien à faire), ainsi que la préparation des sprites, peu pertinente dans notre cas car nous avons des [outils] à notre disposition.

Mais d'abord, quelques explications...

Les registres 12 et 13 du CRTC


Les registres 12 et 13 du CRTC fonctionnent de concert et servent à définir à quel endroit le CRTC va démarrer la lecture des données d'un nouvel écran, et aussi de savoir si il peut déborder de sa page mémoire de 16k. Voici la description de ces deux registres, telle qu'on peut la trouver un peu partout.

Registre 12 Registre 13
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
  inutilisé     Page vidéo     Taille de la page     Adresse de départ (1024 positions)  

Bit 13 Bit 12 Page vidéo
0 0 #0000 - #3FFF
0 1 #4000 - #7FFF
1 0 #8000 - #BFFF
1 1 #C000 - #FFFF
Bit 11 Bit 10 Taille de la page
0 0 16K
0 1 16K
1 0 16K
1 1 32K

L'adresse de départ est sur 1024 positions et concerne uniquement la première ligne de bloc, la ligne zéro. Pour mémoire, nos lignes de bloc font chacune 2048 octets c'est donc une position au mot (16 bits) et non à l'octet qui doit être renseignée ici. L'écran se déplacera de deux octets en deux octets (oui, c'est beaucoup d'un coup!). Il faudra bien penser lors de nos calculs à RESTER dans la première ligne de bloc. La gestion du débordement se fera avec l'instruction RES 2,H qui enlèvera #400 d'un coup en cas de débordement. Et ne fera rien sinon.

Résumé de la situation : Quand le CRTC incrémente de 1 son adresse, l'adresse écran augmente de DEUX!
CRTC 12/13 : #3000 (Page 3 / Adresse #000)
Début de l'écran en haut à gauche : #C000
; après incrémentation
CRTC 12/13 : #3000 (Page 3 / Adresse #001)
Début de l'écran en haut à gauche : #C002
; après incrémentation
CRTC 12/13 : #3000 (Page 3 / Adresse #002)
Début de l'écran en haut à gauche : #C004


Préparation des données


Comme nous allons nous déplacer de deux octets en deux octets, nous allons préparer une suite de sprites qui auront tous une largeur de 2 octets. On utilise toujours notre superbe et magnifique outil convgeneric mais vous pouvez bien utiliser l'outil qui vous chante, tant que vous sortez des données CPC stockées linéairement de 2 octets de large.

; mode 1, taille 8 pixels sur 100, flat car on va avoir +16k de données, on ne veut pas découper
convgeneric.exe -m 1 -g -size 8x100 -c 999 BobWinnerFrance.png -flat

On récupère nos encres (defb #58,#47,#43,#4B) et notre [fichier.bin], 120 sprites ont été extraits, il ne reste plus qu'à les afficher!

Nos sprites ne font que 100 lignes de haut, nous complèterons le bas de l'image avec une trame.
BUILDSNA : BANKSET 0
ORG #100 : RUN #100

ld bc,#7F00+%10001100+%01 : out (c),c ; MODE 1
ld bc,#7F10 : out (c),c : ld a,#58 : out (c),a
ld bc,#7F00 : out (c),c : ld a,#58 : out (c),a
ld bc,#7F01 : out (c),c : ld a,#47 : out (c),a
ld bc,#7F02 : out (c),c : ld a,#43 : out (c),a
ld bc,#7F03 : out (c),c : ld a,#4B : out (c),a

Recommence
ld b,#F5
VBL in a,(c) : rra : jr nc,VBL
; incrémenter l'adresse dans la ligne de bloc avec gestion de débordement
ld hl,(adresseBloc) : inc hl : res 2,h : ld (adresseBloc),hl

; envoyer au CRTC
ld bc,#BC00+12 : out (c),c : ld a,h : or #30 : inc b : out (c),a
dec b : inc c : out (c),c : inc b : out (c),l

; tracer le sprite avant que le balayage arrive :)
ld xl,100
ld hl,(spriteCourant)
ld de,(adresseSpriteEcran)
.envoie100lignes
ldi : ld a,(hl) : ld (de),a : inc hl : dec e ; incrémenter les données mais revenir à l'adresse initiale écran
ld a,d : add 8 : ld d,a ; ajouter #800 à DE
jr nc,.okLigne ; pas de retenue, on est toujours dans le même bloc de lignes
ld a,80 : add e : ld e,a ; on ajoute 80 (largeur d'une ligne en octets) pour passer au bloc suivant
ld a,#C0 : adc d : ld d,a ; et on enlève #4000 (additionner #C000 c'est comme enlever #4000)
res 3,d ; au cas où on reboucle dans la ligne de bloc (trait bleu), on ajuste dans tous les cas
.okLigne
dec xl : jr nz,.envoie100lignes
; gérer le déroulé des sprites
ld a,(spriteNumero) : inc a : cp 120 : jr nz,.enregistreAdresseSprite
xor a : ld hl,bandesSprites ; réarmer les compteurs
.enregistreAdresseSprite ld (spriteCourant),hl : ld (spriteNumero),a

ex hl,de ; on va utiliser HL plutôt que DE pour effacer, les adressages sont plus nombreux
ld xl,50 ; compteur à 50, on va effacer en zig-zag :)
ld bc,%1010111101011111 ; on précharge une trame sur les encres 2 et 3
Raz100
ld (hl),b : inc l : ld (hl),b : ld a,h : add 8 : ld h,a ; ligne paire, on sait que la ligne suivante est dans le bloc
ld (hl),c : dec l : ld (hl),c : ld a,h : add 8 : ld h,a : jr nc,.okRaz
ld a,80 : add l : ld l,a
ld a,#C0 : adc h : ld h,a
res 3,h
.okRaz
dec xl : jr nz,Raz100

ld hl,(adresseSpriteEcran) : inc hl : inc hl : res 3,h ; gérer le débordement à #C800
ld (adresseSpriteEcran),hl
jp Recommence


adresseBloc defw #0000 ; notre écran démarre sur le premier octet de la ligne de bloc
adresseSpriteEcran defw #C000+80 ; avant le premier scroll, cette adresse correspond à la ligne suivante
spriteNumero defb 0
spriteCourant defw bandesSprites
bandesSprites incbin 'BobWinnerFrance.bin'

Vous pourrez comparer la routine de passage de ligne avec celle d'Amstrad 100%, directement tirée de la ROM si je ne m'abuse. On s'évite quelques tests inutiles et notre routine fonctionne dans tous les cas (Pour la page #C000).

Comme beaucoup de nos programmes, il y a un petit problème... ...ça va trop vite! Et pour cause, nous nous déplaçons de 2 octets par image.

À 50 images par seconde, l'écran entier est déplacé en à peine plus d'une seconde et demi...

On va voir ce qu'on peut faire dans le [deuxième cours sur les scrolls]