; Exemple de routines d'affichage de sprites
; (c) Pict/Logon System 1993 pour A100% ; Assemble avec DAMS charge en #4000 ; ; Coordonnees du sprite x EQU 40 y EQU 2 ; ; Dimensions du sprite haut EQU 13 larg EQU 4 size EQU larg*haut mask EQU 4*size ; ; Adresse de la pile du programme ; stack ORG #2000 ; ; Adresse des donnees du sprite ; sprite EQU #1000 tabspr DW size*0+sprite DW size*2+sprite DW size*1+sprite DW size*3+sprite ; ; Largeur de l'ecran en word r1 EQU 40 ; ; Routine de chargement du sprite ; nom1 DM sprite .BIN load LD b,#0C PUSH de CALL #BC77 POP hl CALL #BC83 JP #BC7A ; ; Debut du programme run ; ENT $ LD hl,nom1 LD de,sprite CALL load ; ; Passage en mode 1 et affichage d'un fond quelquonque ; go LD a,1 CALL #BC0E LD hl,fond affond LD a,(hl) INC hl OR a JP z,finaff PUSH hl CALL #bb5A POP hl JP affond finaff ; ; Bloquage du Firmware pour avoir la jouissance de tous ; les registres du Z-80 qu'on sauvegarde ; DI LD hl,(#38) LD (sys1+1),hl LD hl,#C9FB LD (#38),hl LD (stasys1+1),sp LD sp,stack EXX EX af,af PUSH hl PUSH de PUSH bc PUSH af ; ; Initialisation des couleurs du sprite ; LD bc,#7F00 LD de,#5458 LD hl,#4D4B OUT (c),c OUT (c),d INC c OUT (c),c OUT (c),e INC c OUT (c),c OUT (c),h INC c OUT (c),c OUT (c),l ; ; Creation de la table des ordonnees ; (hauteur normale= 200 lignes) ; (adresse normale= #C000) ; LD hl,#C000 LD de,r1*2+#C000 LD bc,#800 LD ix,taby LD a,200 creey LD (ix+1),h LD (ix+0),l INC ix INC ix ADD hl,bc JP nc,nocarry ADD hl,de nocarry DEC a JP nz,creey ; ; Appel du listing d'affichage (listing1,listing2) ; CALL listing2 ; ; Attente d'appui sur Espace ; key LD bc,#f782 OUT (c),c LD bc,#f40e OUT (c),c LD bc,#f6c0 OUT (c),c XOR a OUT (c),a LD bc,#f792 OUT (c),c LD de,#f4f6 LD c,#45 LD b,e OUT (C),c LD b,d IN d,(c) LD bc,#f782 OUT (c),c DEC c OUT (c),a RL d JP c,key ; ; Mets le pen 1 blanc LD bc,#7f01 LD a,#4b OUT (c),c OUT (c),a ; ; Retablissement du Firmware ; firm DI POP af POP bc POP de POP hl EXX EX af,af stasys1 LD sp,0 sys1 LD hl,0 LD (#38),hl EI RET ; fond DM LOGON SYSTEM DB 10,13 DM AMSTRAD 100% DB 0 taby DS 2*200 ; ; Programme principal : on transforme ; les coordonees x et y en adresse ecran. ; listing1 ; on s'occupe d'abord de l'abscisse LD bc,x XOR a LD d,a SRL b RR c RLA SRL b RR c RLA ADD a,a ; Les 2 derniers bits de x determinent le sprite a afficher ; parmi les sprites decales au pixel dans la memoire LD e,a LD hl,tabspr ADD hl,de LD e,(hl) INC hl LD d,(hl) LD a,c ; ; L'ordonnee permet de pointer dans une table sur l'adresse ; de la ligne {cran correspondante LD hl,y ADD hl,hl LD bc,taby ADD hl,bc LD c,(hl) INC hl LD b,(HL) ; ; On additionne a cette adresse ; ; l'abscisse en octets LD h,0 LD l,a ADD hl,bc ; On a l'adresse finale dans HL LD a,haut ; ... qu'on transfere dans DE EX de,hl ; ; ROUTINES D'AFFICHAGE DU SPRITE ; ; (jp loop1_1,loop1_2,...,loop1_6) ; routine JP loop1_5 ; ; 1ERE ROUTINE AFFICHAGE LE PLUS SIMPLE: LDIR SEULEMENT ; loop1_1 LD bc,larg LDIR LD bc,#800-larg EX de,hl ADD hl,bc JP nc,nocarry1 LD bc,r1*2+#c000 ADD hl,bc nocarry1 EX de,hl DEC a JP nz,loop1_1 RET ; ; 2EME ROUTINE: A PEU PRES IDENTIQUE A LA PREMIERE ; MAIS ON REMPLACE LDIR PAR AUTANT DE LDI QUE LE SPRITE ; EST LARGE EN OCTETS. ; loop1_2 LDI LDI LDI LDI LD bc,#800-larg EX de,hl ADD hl,bc JP nc,nocar1_2 LD bc,r1*2+#c000 ADD hl,bc nocar1_2 EX de,hl DEC a JP nz,loop1_2 RET ; ; 3EME ROUTINE: ON TESTE CHAQUE OCTET DU SPRITE A AFFICHER: ; S'IL EST NUL, ON NE L'AFFICHE PAS. ; loop1_3 EX de,hl loop1_31 PUSH af LD b,larg loop1_32 LD a,(de) INC de OR a JP z,noaff1_3 LD (hl),a noaff1_3 INC hl DJNZ loop1_32 LD bc,#800-larg ADD hl,bc JP nc,nocar1_3 LD bc,#c050 ADD hl,bc nocar1_3 POP af DEC a JP nz,loop1_31 RET ; ; 4EME ROUTINE:LE SPRITE ET LE FOND SONT "MELANGES" AVEC UN OR ; LE RESULTAT N'EST PAS TOUJOURS GRACIEUX,MAIS LA RAPIDITE ; D'AFFICHAGE EST CONVENABLE... ON AURAIT PU UTILISER UN XOR ; A LA PLACE DE XOR CE QUI D'EMPLOYER LA MEME ROUTINE POUR L'AFFICHAGE ; ET L'EFFACAGE, MAIS LE RESULTAT A L'ECRAN EST SOUVENT TRES LAID... ; LOOP1_4 EX de,hl loop1_41 PUSH af LD b,larg loop1_42 LD a,(de) OR (hl) LD (hl),a INC hl INC de DJNZ loop1_42 LD bc,#800-larg ADD hl,bc JP nc,nocar1_4 LD bc,r1*2+#c000 ADD hl,bc nocar1_4 POP af DEC a JP nz,loop1_41 RET ; ; 5EME ROUTINE: AFFICHAGE MASQUE:LE PLUS EFFICACE MAIS AUSSI LE PLUS ; LENT! A MOINS D'UTILISER DU CODE AUTO-GENERE (VOIR LISTING 2) ; LOOP1_5 ; on recupere le masque correspondant au sprite decale LD bc,mask PUSH hl ADD hl,bc LD b,h LD c,l POP hl EX de,hl EXX DI LD (sp1_5+1),sp LD sp,#800-larg loop1_51 EX af,af LD b,4 loop1_52 EXX ; ; DE=sprite ; BC=masque ; HL=adresse ecran ; LD a,(bc) AND (hl) EX de,hl OR (hl) EX de,hl LD (hl),a INC hl INC de INC bc EXX DJNZ loop1_52 EXX ADD hl,sp JP nc,nocar1_5 LD sp,r1*2+#c000 nocar1_5 EXX EX af,af DEC a JP nz,loop1_51 sp1_5 LD sp,0 EI RET ; ; 6EME ROUTINE:AFFICHAGE A LA PILE: RAPIDE MAIS LE FOND EST DETRUIT ; ET LE SPRITE DOIT ETRE COMPOSE D'UN NOMBRE PAIR D'OCTETS EN LARGEUR ; loop1_6 DI LD (sp1_6+1),sp LD sp,hl EX de,hl LD b,a loop1_61 LD c,larg/2 loop1_62 POP de LD (hl),e INC hl LD (hl),d INC hl DEC c JP nz,loop1_62 LD de,#800-larg ADD hl,de JP nc,nocar1_6 LD de,#c050 ADD hl,de nocar1_6 DJNZ loop1_61 sp1_6 LD sp,0 EI RET ; ; Listing2:Sprite Autogenere: les donnees du sprite ; sont incrustees dans la routine ; listing2 CALL gener CALL affiche RET ; ; routine d'affichage en code genere: cette partie ; determine laquelle des 4 routines doit etre appelee. ; on se sert de la pile pour recuperer l'adresse de la ; ligne de l'ecran et celle de la routine d'affichage dont on a besoin. ; affiche DI LD (sp2+1),sp ; ; on recupere d'abord l'adresse de la routine d'affichage ; tout en transformant l'abscisse. ; LD de,x LD a,e SRL d RR e SRL d RR e LD sp,tabadsp AND 3 ADD a,a LD h,d LD l,a ADD hl,sp LD sp,hl POP ix ; ; on recupere maintenant l'adresse de la ligne de l'ecran. ; LD sp,taby LD hl,y ADD hl,hl ADD hl,sp LD sp,hl POP hl ADD hl,de LD bc,#800-larg+1 LD de,r1*2+#c000 sp2 LD sp,0 EI ; ; saut a la routine d'affichage selon l'abscisse ; JP (ix) ; ; Programme de generation des 4 routines de sprites. ; gener LD iy,sprout LD hl,sprite LD de,sprite+mask LD ix,tabadsp LD a,4 codebyte PUSH af PUSH hl PUSH iy POP hl LD (ix+0),l LD (ix+1),h POP hl INC ix INC ix CALL calc POP ix POP af DEC a JP nz,codebyte RET ; calc LD b,haut pokeline PUSH bc LD b,larg poke LD a,(de) ; ; on teste d'abord si le masque est plein ; CP #ff ; ; si oui, pas la peine d'afficher l'octet, on passe au suivant. ; JP z,nxtbyte ; ; on teste ensuite si le masque est nul: dans ce cas, pas besoin ; de masquer, on affiche la donnee de l'octet du sprite directement ; OR A JP nz,maskbyte LD a,(hl) LD (iy+0),#36 INC iy LD (iy+0),a INC iy nxtbyte LD (iy+0),#23 INC iy JP coded maskbyte PUSH bc ; ; on recopie le "bout" de code qui affiche et masque un octet du sprite ; pkr LD a,(ix+0) LD (iy+0),a INC ix INC iy DJNZ pkr POP bc ; ; on incruste dans le code le masque et la donnee de l'octet du sprite ; LD a,(de) LD (iy-5),a LD a,(hl) LD (iy-3),a coded INC de INC hl DJNZ poke ; ; on passe a la ligne le "INC L" inutile en decrementant IY ; DEC iy LD b,4 ; ; on recopie le "bout" de code qui permet de descendre d'une ligne. ; LD ix,nxtline pknx LD a,(ix+0) LD (iy+0),a INC ix INC iy DJNZ pknx POP bc DJNZ pokeline ; ; fin de la routine d'affichage. On n'a pas besoin de redescendre ; d'une ligne donc on elimine le morceau de code precedent en reculant ; le pointeur du code genere pour reecrire par dessus. ; LD BC,-4 ADD IY,BC LD (iy+0),#c9 INC iy RET ; ; "morceau" de programme necessaire pour masquer et afficher un octet. ; oper bytes LD a,(hl) AND 0 OR 0 LD (hl),a INC l ; ; "morceau de programme necessaire pour descendre d'une ligne. ; nxtline bytes ADD hl,bc JR nc,noaddde ADD hl,de noaddde end_ ; ; table cree par le generateur qui contient les adresses ; des 4 routines generees. ; tabadsp DS 4*2 ; ; les routines sont generees dans l'espace de memoire debutant ici meme. sprout |