BUILDSNA : BANKSET 0
ORG #38 : EI : RET
ORG #100 : RUN #100
ld sp,#100 : ei
ld bc,#7F00+%10001100+%00 : out (c),c ; MODE 0
ld hl,palette : ld bc,#7F00
setPalette out (c),c : inc c : inc b : outi : ld a,(hl) : or a : jr nz,setPalette
; définir notre coordonnée X et son incrément pour faire bouger le sprite tout seul
ld hl,40 ; milieu écran en nombre d'octets
ld (positionx),hl
ld hl,1
ld (incrementx),hl
;****************
BouclePrincipale
;****************
call waitVBL ; on attend d'être sûr que l'écran précédent soit complètement affiché
ld bc,#BC00+12 : out (c),c : ld a,#30 : inc b : out (c),a ; écran visible en #C000
; si restorex8 vaut 255 c'est le premier affichage, il ne faut pas 'restituer'
ld b,#80 : ld a,(restorex8) : cp 255 : jr z,.first8 : ld c,a : ld de,backup8 : call RestituerTampon : .first8
ld b,#80 : ld a,(positionx) : ld c,a : ld de,backup8 : call SauvegarderPortionEcran
ld b,#80 : ld a,(positionx) : ld (restorex8),a : ld c,a : call AfficherHibou
call DeplacerHibou
;
call waitVBL ; on attend d'être sûr que l'écran précédent soit complètement affiché
ld bc,#BC00+12 : out (c),c : ld a,#20 : inc b : out (c),a ; écran visible en #8000
; si restorexC vaut 255 c'est le premier affichage, il ne faut pas 'restituer'
ld b,#C0 : ld a,(restorexC) : cp 255 : jr z,.firstC : ld c,a : ld de,backupC : call RestituerTampon : .firstC
ld b,#C0 : ld a,(positionx) : ld c,a : ld de,backupC : call SauvegarderPortionEcran
ld b,#C0 : ld a,(positionx) : ld (restorexC),a : ld c,a : call AfficherHibou
call DeplacerHibou
jr BouclePrincipale
DeplacerHibou
; déplacer notre sprite
ld hl,(positionx) : ld bc,(incrementx) : add hl,bc : ld (positionx),hl
; gérer le "rebond" aux bords
ld a,h : or l : jr nz,.pasGauche : ld hl,1 : ld (incrementx),hl : .pasGauche
ld a,l : cp 79-9 : jr nz,.pasDroite : ld hl,-1 : ld (incrementx),hl : .pasDroite
ret
AfficherHibou
ld de,donnees_sprite
RestituerTampon ; nécessite DE pré-positionné
ld hl,80 ; Y=80 pour être à peu prêt centré
ld xl,9 : ld xh,36 ; dimensions du sprite largeur/lignes
call AfficheSprite
ret
waitVBL ld b,#F5
.loop in a,(c) : rra : ret c : jr .loop
SauvegarderPortionEcran
ld hl,80 ; Y=80 pour être à peu prêt centré
ld xl,9 : ld xh,36 ; dimensions du sprite largeur/lignes
; BC=page + coordonnée X (0-79) / HL=coordonnée Y (0-199) / DE=adresse du tampon de sauvegarde
; XL=largeur du sprite en octets / XH=hauteur du sprite en nombre de lignes
call CalculeAdressePixel
; HL=source écran
; DE=tampon de sauvegarde
ld b,0
.sauvegardeLignes
ld c,xl ; chargeur la largeur d'une ligne
push hl ; on met l'adresse de début de la ligne de côté
ldir
pop hl ; on récupère l'adresse du début de ligne
; et on calcule le passage à la ligne suivante
ld a,h : add 8 : ld h,a ; ajouter #800 à HL
and #38 ; on teste si on déborde de la bank (passage de page+#3800 à page+#0000)
jr nz,.nextLine ; pas zéro, on est toujours dans le même bloc de lignes
ld a,80 : add l : ld l,a ; on ajoute 80 (largeur d'une ligne en octets) pour passer au bloc suivant
ld a,#C0 : adc h : ld h,a ; et on enlève #4000 (additionner #C000 c'est comme enlever #4000)
.nextLine
dec xh ; notre compteur de lignes
jr nz,.sauvegardeLignes
ret
; -------------------------------
AfficheSprite
; BC=page + coordonnée X (0-79) / HL=coordonnée Y (0-199) / DE=adresse des données du sprite
; XL=largeur du sprite en octets / XH=hauteur du sprite en nombre de lignes
call CalculeAdressePixel
; HL=destination écran
; DE=toujours l'adresse source des données
ex hl,de ; on permute source et destination pour être utilisées
; avec l'instruction LDIR
ld b,0
.afficheLignes
ld c,xl ; chargeur la largeur d'une ligne
push de ; on met l'adresse de début de la ligne de côté
ldir
pop de ; on récupère l'adresse du début de ligne
; et on calcule le passage à la ligne suivante
; notre routine de passage à la ligne suivante, adaptée pour DE
ld a,d : add 8 : ld d,a ; ajouter #800 à DE
and #38 ; on teste si on déborde de la bank (passage de page+#3800 à page+#0000)
jr nz,.nextLine ; pas zéro, 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)
.nextLine
dec xh ; notre compteur de lignes
jr nz,.afficheLignes
ret
;-------------------
CalculeAdressePixel
; B=page vidéo #00, #40, #80 ou #C0
; C=coordonnée X (0-79)
; HL=coordonnée Y (0-199)
; adresse de la ligne dans HL en résultat
add hl,hl ; adresses 16 bits, il faut indexer de 2 en 2
ld a,lo(tableau) : add l : ld l,a : ld a,h : adc hi(tableau): ld h,a
ld a,(hl) : inc hl
ld h,(hl) : ld l,a
add hl,bc ; ajouter la position X en octets et la page!
ret
;-------------------
adresse_ecran=#0000
largeur_ecran=80
tableau
repeat 25
repeat 8
defw adresse_ecran
adresse_ecran+=#800
rend
adresse_ecran+=largeur_ecran
adresse_ecran-=#4000
rend
palette defb #54,#56,#5C,#46,#5E,#40,#47,#43,#4D,#4E,#4B,#4C,0 ; Rose
donnees_sprite incbin 'hibouRose.bin'
restorex8 defb 255 ; il ne faut pas restituer le fond la première fois
restorexC defb 255 ; il ne faut pas restituer le fond la première fois
positionx defw 0
incrementx defw 0
backup8 defs 9*36 ; on réserve la place de sauvegarde pour notre sprite
backupC defs 9*36 ; on réserve la place de sauvegarde pour notre sprite
; initialiser notre écran sur les deux pages!
org #8000 : incbin 'foret8couleurs.bin'
org #C000 : incbin 'foret8couleurs.bin'
|