;------------------------------------------------------------------------------------------
; [LIB_GRAPH] Copyright (c) 2007-2016. Vincent Bouffigny
;
; Copyright	Cette librairie va faire l'objet d'une publication en cours de rédaction et
;		ne peut donc être utilisée à des fins commerciales
;
; Auteur	Vincent Bouffigny
; Web		projet.infos.free.fr
;
; Informations  Développé sous WinAPE 2.0 alpha 13
;
;		Librairie de méthodes graphiques utilisables directement dans vos programmes
;		supporte les modes 0,1,2 du CPC. Le mode graphique  doit être indiqué via la
;		constante CST_GRAPH_VIDEO_MODE. L'adresse de la mémoire  graphique peut être
;		redéfinie via la variable DEF_GRAPH_VIDEO_ADR. Attention  si vous changez le
;		mode graphique n'oubliez pas  que le nombre  de couleurs maxi dépend du mode
;		graphique, de 0 à 15 pour le mode 0, de 0 à 3 pour  le mode 1, de 0 à 1 pour
;		le mode 2. La démo est prévue pour fonctionner avec 16 couleurs en mode 0.
;
;		A partir de la version 2.xx de la librairie, deux méthodes ont été implémentées GRAPH_ACTIVE_DIRECT_MODE
;		et GRAPH_ACTIVE_INDIRECT_MODE. La  première  méthode  utilise  une table d' adresse pré-calculées , pour
;		l'affichage des données, les données graphiques sont directement envoyées à l'adresse &C000. La  seconde
;		méthode permet d'activer le mode de tracé indirect, dans ce mode les données graphiques sont envoyées à
;		l'adresse définit par DEF_GRAPH_VIDEO_ADR. Le mode de tracé direct est plus rapide.
;
;		N'hésitez pas à me contacter pour des questions, des évolutions ou tout autre projet !
;
; Version	2.0 de 27/06/2016
;		
; Modifications
;		2.0a du 27/06/2016
;			 - Test version Alpha (voir documentation plus bas):
;				GRAPH_SPRITE_SHOW_FAST_SPRITE
;				GRAPH_SPRITE_SHOW_MEMORY_BLOCK
;				GRAPH_SPRITE_SAVE_MEMORY_BLOCK
;				GRAPH_SPRITE_COMPILE_SPRITE
;				GRAPH_SPRITE_HIDE_OBJECT
;				GRAPH_SPRITE_SAVE_BACKGROUND_OBJECT
;				GRAPH_SPRITE_SHOW_BACKGROUND_OBJECT
;
;		2.0 du 02/06/2016
;			- Ajout        - Gestion d'objets et de sprites
;			- Ajout	       - Contrôle sur le n° de la couleur passé en paramètre aux fonctions de traçage
;			- Ajout	       - Fonctions de tracés en effectuant un OU exclusif sur les données graphiques
;			- Ajout	       - Fonctions d'affichage d'un pixel en effectuant un OU exclusif sur les données graphiques
;			- Optimisation - Remplacement des méthodes MATH_MUL_SP_16x8, MATH_DIV_SP_16x8 par MATH_MUL_16x8p et MATH_DIV_16x8
;			- Optimisation - Ajout d'une table des adresses de base des lignes, ADDRESS_OF_LIGNES
;			- Optimisation - Prise en charge du calcul de l'adresse d'un point via la table des adresses de base des lignes
;			- optimisation - Optimisation de la méthode de calcul de l'adresse d'un point GRAPH_ADR_OF_PIXEL
;			- Optimisation - Ajout de deux mode d'adressage pour les tracés, le mode d'adressage direct (par défaut) ou indirect
;			  		 utilisation des fonctions GRAPH_ACTIVE_DIRECT_MODE, GRAPH_ACTIVE_INDIRECT_MODE
;			- Optimisation - Optimisation des fonctions de tracé horizontal 2,4 et 16 couleurs
;
;		1.0 du 13/10/2007 - Version de lancement
;
;------------------------------------------------------------------------------------------
;				Liste des méthodes
;
;	[Evolutions en cours...]
;
;		GRAPH_SPRITE_SHOW_FAST_SPRITE		; Traçage rapide rapide d'un sprite
;		GRAPH_SPRITE_SHOW_MEMORY_BLOCK		; Permet de restaurer un bloc mémoire à l'écran
;		GRAPH_SPRITE_SAVE_MEMORY_BLOCK		; Permet de sauvegarder une zone écran dans une structure MemoryBloc
;		GRAPH_SPRITE_COMPILE_SPRITE		; Permet d'adapter les données d'un sprite au format logique de l'écran
; 							; Toutes les couleurs brutes sont remplacées par les donées des couleurs entrelacées
;		GRAPH_SPRITE_HIDE_OBJECT		; Permet de cacher un objet graphique
;		GRAPH_SPRITE_SAVE_BACKGROUND_OBJECT	; Permet de sauvegarder une zone de l'écran impacté par l'affichage d'un objet graphique
;		GRAPH_SPRITE_SHOW_BACKGROUND_OBJECT	; Permet de restaurer une zone de l'écran impacté par l'affichage d'un objet graphique
;
;	[v2.0]
;
;	- Ajouts -
;		
;		GRAPH_WAIT_RETRACE			; Attend le retour du balayage de l'écran
;		GRAPH_SPRITE_SIZE_ON_SCREEN		; Calcul le nombre d'octets occupés en mémoire par un sprite en fonction du mode graphique
;		GRAPH_ACTIVE_DIRECT_MODE		; Activation de mode de tracé direct
;		GRAPH_ACTIVE_INDIRECT_MODE		; Activation de mode de tracé indirect	
;		GRAPH_ADR_OF_PIXEL_WITH_DIRECT_MODE	; Calcul de l'adresse d'un pixel pour le mode de tracé direct
;		GRAPH_ADR_OF_PIXEL_WITH_INDIRECT_MODE	; Calcul de l'adresse d'un pixel pour le mode de tracé indirect
;		GRAPH_SPRITE_TEST_POSITION		; Permet de vérifier la position d'un sprite à l'écran et de connaître ses parties invisibles
;		GRAPH_SPRITE_SHOW_SPRITE		; Permet d'afficher un sprite quelque soit le mode graphique
;		GRAPH_SPRITE_SHOW_SPRITE_16		; Permet d'afficher un sprite avec le mode graphique 0, 16 couleurs
;		GRAPH_SPRITE_SHOW_SPRITE_4		; Permet d'afficher un sprite avec le mode graphique 1, 4 couleurs
;		GRAPH_SPRITE_SHOW_SPRITE_2		; Permet d'afficher un sprite avec le mode graphique 2, 2 couleurs
;		GRAPH_SPRITE_NEW_MEMORYBLOCK		; Création d'un nouveau bloc mémoire
;		GRAPH_SPRITE_NEW_SPRITE			; Création d'un nouveau sprite
;		GRAPH_SPRITE_NEW_SPRITE_FROM_DATAS	; Création d'un nouveau sprite à partir de données existantes
;		GRAPH_SPRITE_NEW_OBJECT			; Création d'un nouvel objet vièrge
;		GRAPH_SPRITE_NEW_OBJECT_FROM_DATAS	; Création d'un nouvel objet à partir de données existantes
;		GRAPH_SPRITE_FREE_MEMORYBLOCK		; Libération des ressources utilisées par un bloc mémoire
;		GRAPH_SPRITE_FREE_SPRITE		; Libération des ressources utilisées par un sprite
;		GRAPH_SPRITE_FREE_OBJECT		; Libération des ressources utilisées par un objet
;		GRAPH_SPRITE_OBJECT_SET_STATE		; Modification de l'état d'un objet
;
;		GRAPH_LINE_XOR		; Tracé d'une ligne oblique quelque soit le mode graphique, avec une opération logique XOR
;		GRAPH_LINE_2_XOR	; Tracé d'une ligne oblique pour le mode graphique 2 couleurs, avec une opération logique XOR
;		GRAPH_LINE_4_XOR	; Tracé d'une ligne oblique pour le mode graphique 4 couleurs, avec une opération logique XOR
;		GRAPH_LINE_16_XOR	; Tracé d'une ligne oblique pour le mode graphique 16 couleurs, avec une opération logique XOR
;		GRAPH_LINE_H_2_XOR	; Tracé d'une ligne horizontale pour le mode graphique 2 couleurs, avec une opération logique XOR
;		GRAPH_LINE_H_4_XOR	; Tracé d'une ligne horizontale pour le mode graphique 4 couleurs, avec une opération logique XOR
;		GRAPH_LINE_H_16_XOR	; Tracé d'une ligne horizontale pour le mode graphique 16 couleurs, avec une opération logique XOR
;		GRAPH_LINE_V_2_XOR	; Tracé d'une ligne verticale pour le mode graphique 2 couleurs, avec une opération logique XOR
;		GRAPH_LINE_V_4_XOR	; Tracé d'une ligne verticale pour le mode graphique 4 couleurs, avec une opération logique XOR
;		GRAPH_LINE_V_16_XOR	; Tracé d'une ligne verticale pour le mode graphique 16 couleurs, avec une opération logique XOR
;		GRAPH_PUT_PIXEL_XOR	; Affichage d'un pixel quelque soit le mode graphique, avec une opération logique XOR
;		GRAPH_PUT_PIXEL_2_XOR	; Affichage d'un pixel en mode 2 couleurs, avec une opération logique XOR
;		GRAPH_PUT_PIXEL_4_XOR	; Affichage d'un pixel en mode 4 couleurs, avec une opération logique XOR
;		GRAPH_PUT_PIXEL_16_XOR	; Affichage d'un pixel en mode 16 couleurs, avec une opération logique XOR
;		
;		MATH_MUL_8x8		; Multiplication de deux entiers de 8 bits
;		MATH_SLA_8		; Décalage de n bit(s) vers la gauche, sur un entier de 8 bits
;		MATH_SLA_16		; Décalage de n bit(s) vers la gauche, sur un entier de 16 bits
;
;		SYS_BEEP		; Emission d'un beep système
;		SYS_GET_MEMORY		; Allocation de mémoire via la table virtuelle
;		SYS_FREE_MEMORY		; Libération de mémoire via la table virtuelle
;
;	- Optimisations -
;		GRAPH_ADR_OF_PIXEL
;		GRAPH_LINE_H_2
;		GRAPH_LINE_H_4
;		GRAPH_LINE_H_16
;
;	- Supressions -
;		MATH_MUL_SP_16x8p
;		MATH_DIV_SP_16x8
;
;
;	[v1.0]
;
;		GRAPH_ADR_OF_PIXEL		; Calcul de l'adresse de base d'un point
;		GRAPH_CLEAR_SCREEN		; Efface l'écran
;		GRAPH_FILL_SCREEN		; Replissage de l'écran avec une couleur
;		GRAPH_LINE			; Traçage d'une ligne quelque soit le mode graphique
;		GRAPH_LINE_2			; Traçage d'une ligne pour le mode graphique 2 couleurs
;		GRAPH_LINE_4			; Traçage d'une ligne pour le mode graphique 4 couleurs
;		GRAPH_LINE_16			; Traçage d'une ligne pour le mode graphique 16 couleurs
;		GRAPH_RECTANGLE			; Traçage d'un cadre vide quelque soit le mode graphique
;		GRAPH_RECTANGLE_16		; Traçage d'un cadre vide pour le mode graphique 16 couleurs
;		GRAPH_RECTANGLE_4		; Traçage d'un cadre vide pour le mode graphique 4 couleurs
;		GRAPH_RECTANGLE_2		; Traçage d'un cadre vide pour le mode graphique 2 couleurs
;		GRAPH_RECTANGLE_FILLED		; Traçage d'un cadre plein quelque soit le mode graphique
;		GRAPH_RECTANGLE_FILLED_2	; Traçage d'un cadre plein pour le mode graphique 2 couleurs
;		GRAPH_RECTANGLE_FILLED_4	; Traçage d'un cadre plein pour le mode graphique 4 couleurs
;		GRAPH_RECTANGLE_FILLED_16	; Traçage d'un cadre plein pour le mode graphique 16 couleurs
;		GRAPH_LINE_H			; Traçage d'une ligne horizontale quelque soit le mode graphique
;		GRAPH_LINE_H_2			; Traçage d'une ligne horizontale pour le mode graphique 2 couleurs
;		GRAPH_LINE_H_4			; Traçage d'une ligne horizontale pour le mode graphique 4 couleurs
;		GRAPH_LINE_H_16			; Traçage d'une ligne horizontale pour le mode graphique 16 couleurs
;		GRAPH_LINE_V			; Traçage d'une ligne verticale quelque soit le mode graphique
;		GRAPH_LINE_V_2			; Traçage d'une ligne verticale pour le mode graphique 2 couleurs
;		GRAPH_LINE_V_4			; Traçage d'une ligne verticale pour le mode graphique 4 couleurs
;		GRAPH_LINE_V_16			; Traçage d'une ligne verticale pour le mode graphique 16 couleurs
;		GRAPH_PUT_PIXEL			; Affichage d'un pixel quelque soit le mode graphique
;		GRAPH_PUT_PIXEL_2		; Affichage d'un pixel pour le mode graphique 2 couleurs
;		GRAPH_PUT_PIXEL_4		; Affichage d'un pixel pour le mode graphique 4 couleurs
;		GRAPH_PUT_PIXEL_16		; Affichage d'un pixel pour le mode graphique 16 couleurs
;
;		MATH_SRL_8			; Décalage de n bit(s) vers la droite d'un entier de 8 bits
;		MATH_SRL_16			; Décalage de n bit(s) vers la droite d'un entier de 16 bits
;		MATH_MUL_SP_16x8p		; Multiplication d'un entier de 16 bits par un entier de 8 bits, avec empilage des paramètres
;		MATH_DIV_SP_16x8		; Division d'un entier de 16 bits par un entier de 8 bits, avec empilage des paramètres
;
;------------------------------------------------------------------------------------------

NOLIST		; Ne pas affiche le code pendant la compilation
ORG &4000	; Placement en mémoire &4000 après compilation
RUN &4000	; Lancement automatique à l'adresse &4000


START_PRG:	; Début du programme

	LD SP, STACK + STACK_SIZE - 1

	; Initialisation de la vitesse du clavier
	LD H, 1
	LD L, 1
	CALL CALLBACK_KEYBR_SPEED_KEY
	
	; Affichage du mode graphique courant (constante CST_GRAPH_VIDEO_MODE)
        LD A, CST_GRAPH_VIDEO_MODE
        CALL CALLBACK_GRAPH_INIT_VIDEO_MODE      ;Sous-routine d'initialisation de l'écran

	; Bordure de l'écran en noire
	LD BC, 0
	CALL CALLBACK_GRAPH_BORDER
	HALT	; Attente du rafaîchissement de l'écran
	HALT	;
	HALT	;
	HALT	;

	DI	; Désactivation des intérruptions matérielles
		; Nécessaire pendant les traitements graphiques

	; Mode d'adresse direct de la mémoire vidéo
	CALL GRAPH_ACTIVE_DIRECT_MODE

	; Affichage de la démo
	;CALL DEMO
	
	;LD HL, SYS_CALLBACK
	;LD A,(&0038)
	;LD (HL), A
	;INC HL
	;LD A,(&0039)
	;LD (HL), A
	;INC HL
	;LD A,(&003A)
	;LD (HL), A
	;INC HL

	;LD HL, GET_KEY
	;LD A, &CD
	;LD (&0038), A
	;LD (&0039), HL
	


	;LD D, 20
	;LD E, 20
	;CALL GRAPH_SPRITE_NEW_MEMORYBLOCK

	; Sauvearde du bloc pour test
	;LD BC, 2
	;LD A, 2
	;CALL GRAPH_SPRITE_SAVE_MEMORY_BLOCK	

	; Restauration du bloc mémoire
	;CALL GRAPH_SPRITE_SHOW_MEMORY_BLOCK	

	; Libération des ressources mémoire
	;CALL GRAPH_SPRITE_FREE_MEMORYBLOCK




	;LD D, 9
	;LD E, 9
	;LD IX, SPRITES
	;LD IY, MASKS
	;LD A, 2
	
	;CALL GRAPH_SPRITE_NEW_SPRITE_FROM_DATAS
	;CALL GRAPH_SPRITE_COMPILE_SPRITE

	;PUSH IX
	;LD BC, 200
_1

	;LD D, B
	;LD E, C
	
	;CALL GRAPH_SPRITE_SHOW_SPRITE

	;DEC BC
	;LD A, B
	;OR C
	;JP nz, _1



	;********************************************************************
	; Permet de créer un nouvel object à partir d'un sprite existant
	;
	; En entrée
	;	D  <=> Largeur de l'objet en pixel
	;	E  <=> Hauteur de l'objet en pixel
	;	IX <=> Adresse des données du sprite existant
	;	IY <=> Adresse des données du masque existant
	; En sortie
	;	IX <=> Adresse mémoire du nouvel objet
	;
	LD D, 9
	LD E, 9
	LD IX, SPRITES
	LD IY, MASKS
	CALL GRAPH_SPRITE_NEW_OBJECT_FROM_DATAS
	PUSH IX
	POP IY

	LD H, (IY + 8)
	LD L, (IY + 7)
	PUSH HL
	POP IX
	CALL GRAPH_SPRITE_COMPILE_SPRITE


	
	; IY adresse de l'objet
	LD BC, 0	; Positions de l'objet à l'écran
	LD DE, 0	;
	
	LD (IY + 1), B	; (IY + 0) (IY + 1) Position x sur 16 bits (signé)
	LD (IY + 0), C	; 
	LD (IY + 3), D	; (IY + 2) (IY + 3) Position y sur 16 bits (signé)
	LD (IY + 2), E	;

	CALL GRAPH_SPRITE_SAVE_BACKGROUND_OBJECT

	JP Show

	EI	
_boucle:


	; Vérifie si une touche est pressée
	PUSH BC
	LD A, CST_KEY_UP
	CALL CALLBACK_KEYBR_INKEY
	JP nz, _up
	LD A, CST_KEY_DOWN
	CALL CALLBACK_KEYBR_INKEY
	JP nz, _down
	LD A, CST_KEY_LEFT
	CALL CALLBACK_KEYBR_INKEY
	JP nz, _left
	LD A, CST_KEY_RIGHT
	CALL CALLBACK_KEYBR_INKEY
	JP nz, _right
	LD A, CST_KEY_ESC
	CALL CALLBACK_KEYBR_INKEY
	JP nz, _fin

	POP BC
	JP _boucle

_up:
	POP BC
	DEC DE
	DEC DE
	DEC DE
	JP Show
_down:
	POP BC
	INC DE
	INC DE
	INC DE
	JP Show
_left:
	POP BC
	DEC BC
	DEC BC
	JP Show
_right:
	POP BC
	INC BC
	INC BC
	JP Show


Show:
	
	DI
	LD (IY + 1), B	; (IY + 0) (IY + 1) Position x sur 16 bits (signé)
	LD (IY + 0), C	; 
	LD (IY + 3), D	; (IY + 2) (IY + 3) Position y sur 16 bits (signé)
	LD (IY + 2), E	;

	CALL GRAPH_WAIT_RETRACE
	CALL GRAPH_SPRITE_HIDE_OBJECT
	CALL GRAPH_SPRITE_SHOW_OBJECT

	EI	
	JP _boucle

_fin:
	POP BC
	; Libération des ressources utiliées par l'objet
	CALL GRAPH_SPRITE_FREE_OBJECT


	; Libération des ressources utilisées par le sprite
	;CALL GRAPH_SPRITE_FREE_SPRITE

	;EI	; Ré-activation des intérruptions matérielles

	;CALL CALLBACK_KEYBR_KEYPRESS		; Attente qu'une touche soit pressée
	RST 0

END_PRG:




;******************************************************************** 
; Permet d'afficher un sprite à l'écran 
; 
; En entrée 
;       BC <=> Position sur x 
;       A  <=> Position sur y 
;       IX <=> Adresse d'une structure Sprite 
; En sortie 
;       aucun 
; Registres affectés 
;       aucun 
; Remarques 
;       - La zone d'affichage du sprite doit être obligatoirement comprise dans la zone visible de l'écran 
; 
;       Sprite { 
;               BYTE width       ; largeur du sprite en pixel 
;               BYTE height      ; hauteur du sprite en pixel 
;               WORD sprite_size ; taille du tampon 
;               WORD sprite      ; adresse du tampon contenant les données du sprite 
;               WORD mask        ; adresse du tampon du masque logique qui doit avoir la même taille que le sprite 
;               BYTE static_datas; indique si les données du sprite sont issues de données statiques 
;       } (9 octets) 
; 
; 
; Affichage d'un sprite en mode 16 couleurs 
; 
GRAPH_SPRITE_SHOW_FAST_SPRITE_16: 

        PUSH AF         ; Sauvegarde des registres 
        PUSH BC 
        PUSH DE 
        PUSH HL 
        PUSH IX 
        PUSH IY 

        ; - 1 - 
        EX AF,AF' 
        PUSH AF 
        EX AF,AF' 

        ; - 2 - 
        ; Calcul de l'adresse de base du premier pixel à afficher 
        ; 
        ; En entrée 
        ;       BC <=> X1 sur 16 bits 
        ;       A  <=> Y1 sur 8 bits 
        ; En sortie 
        ;       HL <=> Adresse du premier point 
        ; 
        CALL GRAPH_ADR_OF_PIXEL 
        PUSH HL         ; Sauvegarde de l'adresse du premier point  

        ; - 3 - 
        ; Calcul du nombre de lignes restant à traiter dans la série de lignes courante 
        AND 7           ; Préservation des 3 premiers bits pour connaître le n° de la ligne courante dans la série de lignes
        NEG             ; Valeur négative de A 
        ADD 8           ; Ajout de 8 pour obtenir le nombre de lignes restant à traiter dans la série 
        EX AF,AF'       ; Sauvegarde du nombre de lignes dans A' 

        ; - 4 - 
        ; Calcul du nombre de décalages binaires à effectuer pour afficher 
        ; le premier point du sprite 
        ; 
        LD A, C         ; Transfert de la partie basse de BC (x) pour calculer la position du premier point 
        LD B, CST_GRAPH_PIXELS_PER_BYTE - 1 
        AND B 
        LD C, A         ; A dans C pour calculer le nombre de décalages binaire pour afficher le premier point 
        LD A, B         ; 
        SUB C           ; A contient le nombre de décalages 

        ; - 5 - 
        ; Calcul du masque de préservation par défaut 
        ; 
        LD E, %10101010         ; Masque par défaut 
        OR A 
        JP z, _GRAPH_SPRITE_SHOW_FAST_SPRITE_16_DecalageMasquePreservation 

        SRL E   ; Décalage du masque de préservation d'une position vers la droite 
                ; le manière à préserver les données du pixel voisin 

_GRAPH_SPRITE_SHOW_FAST_SPRITE_16_DecalageMasquePreservation 

        LD (____GRAPH_SPRITE_SHOW_FAST_SPRITE_16_PreAffectation_Decalages + 1), A 
        LD A, E                 ; Transfert du masque dans A pour stockage 
        LD (____GRAPH_SPRITE_SHOW_FAST_SPRITE_16_PreAffectation_MasquePreservation + 1), A 

        ; - 6 - 
        ; Nombre de lignes à afficher 
        LD A, (IX + 1)  ; (IX + 1) Hauteur du sprite en pixel 
        LD (____GRAPH_SPRITE_SHOW_FAST_SPRITE_16_PreAffectation_nbLignes + 1), A 
        
        ; Nombre de pixels à afficher 
        LD A, (IX + 0)  ; (IX + 0) Largeur du sprite en pixel 
        LD (____GRAPH_SPRITE_SHOW_FAST_SPRITE_16_PreAffectation_nbPixels + 1), A 

        ; - 7 - 
        ; Calcul de l'offset utilisé pour passer à la ligne suivante sur l'écran 
	SRL A		; Sachant que l'on a deux pixels par octet on doit diviser par 2 la largeur en octet, du sprite
        LD B, 0         ; Largeur du sprite 
        LD C, A         ;
        LD HL, &800     ; Largeur d'une ligne graphique 
        SBC HL, BC      ; On retire le décalage en octet pour le calcul de l'adresse finale 
        LD A, H         ; Pré-affectation de l'offset 
        LD (____GRAPH_SPRITE_SHOW_FAST_SPRITE_16_PreAffectation_OffsetLigne + 2), A 
        LD A, L         ; 
        LD (____GRAPH_SPRITE_SHOW_FAST_SPRITE_16_PreAffectation_OffsetLigne + 1), A 

        ; - 8 - 
        ; Aadresse de départ des données du sprite en fonctions des décalages 
        ; 
        LD H, (IX + 5)  ; Adresse du sprite dans HL 
        LD L, (IX + 4)  ; 
        PUSH HL         ; Transfert de l'adresse des données du sprite dans IY 
        POP IY          ; 

        LD H, (IX + 7)  ; Adresse du masque dans HL 
        LD L, (IX + 6)  ; 
        PUSH HL         ; Transfert de l'adresse des données du sprite dans IX 
        POP IX          ; 

        POP HL          ; Restauration de l'adresse du premier point à afficher 

        ; - 9 - 
        ; Initialisation du nombre de lignes à traiter 
        ____GRAPH_SPRITE_SHOW_FAST_SPRITE_16_PreAffectation_nbLignes 
        LD B, 0         ; Pré-affectation (nbLignes) 


_GRAPH_SPRITE_SHOW_FAST_SPRITE_16_BoucleSurLesLignes 

        ; - 10 - 
        ; Intialisation du nombre de points à traiter par ligne 
        ____GRAPH_SPRITE_SHOW_FAST_SPRITE_16_PreAffectation_nbPixels 
        LD C, 0         ;Pré-affectation (nbPixels) 

        ; - 11 - 
        ; Nombre de décalage par défaut 
        ____GRAPH_SPRITE_SHOW_FAST_SPRITE_16_Preaffectation_Decalages 
        LD D, 0         ; Pré-affectation (Decalages) 

        ; - 12 - 
        ; Masque de préservation par défaut 
        ____GRAPH_SPRITE_SHOW_FAST_SPRITE_16_PreAffectation_MasquePreservation 
        LD E, 0         ; Pré-affectation (Masque) 

        
_GRAPH_SPRITE_SHOW_FAST_SPRITE_16_BoucleSurLesPixels 

        ; - 13 - 
        ; Vérification que tous les pixels de la ligne courante ont été traités 
        ; 
        LD A, C ; Transfert du nombre de pixels restant à traiter dans A 
        OR A    ; Si tous les point ont été traités, on calcul l'adresse graphique suivante en ajoutant l'offset 
        JP z, _GRAPH_SPRITE_SHOW_FAST_SPRITE_16_TestNombreDeLignes 

        PUSH BC         ; Sauvegarde des compteurs B et C (nombre de lignes et nombre de pixels par ligne) 

        ; - 14 - 
        ; Récupération des données du masque et du sprite 
        ; 
        LD B, (IY)      ; Récupération du point à afficher et décalage des bits en fonction de la position logique à l'écran
        LD C, (IX)      ; Récupération du masque logique associé au sprite et décalage des bits en fonction de la position logique à l'écran

        ; - 15 - 
        ; Déclage des données du masque et des données du sprite si un décalage doit être effectué 
        LD A, D         ; Nombre de décalages dans A 
        OR A    
        JP z, _GRAPH_SPRITE_SHOW_FAST_SPRITE_16_AucunDeclageMasqueEtSprite 

        SLA B           ; Décalage des données du sprite en fonction du nombre de décalages courant 
        SLA C           ; Décalage du masque en fonction du nombre de décalages courant 

_GRAPH_SPRITE_SHOW_FAST_SPRITE_16_AucunDeclageMasqueEtSprite 

        ; - 16 - 
        ; Calcul du masque logique de préservation des données 
        LD A, C         ; Masque logique associé au sprite 
        OR E            ; Association avec le masque de préservation des données du point voisin au point courant 
        LD C, A         ; Sauvegarde du masque dans C 

        ; - 17 - 
        ; Affichage du nouveau point 
        LD A, (HL)      ; Récupération de l'octet graphique courant 
        AND C           ; Préservation des données à partir du masque précédement calculé 
        OR B            ; Ajout des données du nouveau point 
        LD (HL), A      ; Affichage du nouveau point à l'écran 

        ; - 18 - 
        ; Restauration et ajustement des compteurs 
        ; 
        POP BC          ; Restauration de compteurs 
        DEC C           ; Décrémentation du nombre de points à traiter 

        ; - 19 - 
        ; Traitement du point suivant 
        INC IX          ; Incrémentation de l'adresse du masque logique 
        INC IY          ; Incrémentation de l'adresse du sprite 

        ; - 20 - 
        ; Décalage du masque de préservation pour traiter les données du point suivant 
        RRC E           ; Décalage du masque de préservation des données du point voisin 
                        ; de manière à traiter le point suivant 

        ; - 21 - 
        ; L'octet graphique courant a t-il complètement été traité ? (Nombre de décalage = 0) 
        LD A, D 
        OR A 
        JP z, _GRAPH_SPRITE_SHOW_FAST_SPRITE_16_OctetSuivant 

        ; - 22 - 
        ; Ajustement de nombre de déclages restant à effectuer dur l'octet courant 
        DEC D   ; Décrémentation du nombre de décalages à affectuer pour traiter les pixels restant 
        JP _GRAPH_SPRITE_SHOW_FAST_SPRITE_16_BoucleSurLesPixels 

_GRAPH_SPRITE_SHOW_FAST_SPRITE_16_OctetSuivant 

        ; - 23 - 
        ; Octet suivant 
        INC HL  ; Octet graphique suivant 
        LD D, CST_GRAPH_PIXELS_PER_BYTE - 1 
                ; D va contenir le nombre de décalages à effectuer pour traiter 
                ; les données du point suivant. 

        JP _GRAPH_SPRITE_SHOW_FAST_SPRITE_16_BoucleSurLesPixels 

_GRAPH_SPRITE_SHOW_FAST_SPRITE_16_TestNombreDeLignes 

        ; - 24 - 
        ; Toutes les lignes ont elles été toutes traitées 
        DJNZ _GRAPH_SPRITE_SHOW_FAST_SPRITE_16_LigneSuivante 
        JP z, _GRAPH_SPRITE_SHOW_FAST_SPRITE_16_FinBoucleSurLesLignes 

_GRAPH_SPRITE_SHOW_FAST_SPRITE_16_LigneSuivante 
        
        ; - 25 - 
        ; Vérification que la série de lignes a complètement été traitée 
        EX AF, AF' 
        DEC A 
        OR A 
        JP nz, _GRAPH_SPRITE_SHOW_FAST_SPRITE_16_NouvelleLigne 

        OR 8    ; Nouvelle série de 8 lignes 
        LD DE, &3FB0    ; &3FB0 = &4000 - &50 = Espace d'adressage d'une série complète de lignes - Offset pour la série de lignes suivantes

        SBC HL, DE      ;       => HL = HL - &4000 + &50 

_GRAPH_SPRITE_SHOW_FAST_SPRITE_16_NouvelleLigne 

        ; - 26 - 
        ; Calcul de l'adresse vidéo de la nouvelle ligne en fonction des déclages dx1 et dx2 
        ____GRAPH_SPRITE_SHOW_FAST_SPRITE_16_PreAffectation_OffsetLigne 
        LD DE, 0        ; Pré-affectation (offset_ligne) 
        ADD HL, DE      ; Passage à la ligne suivante 

        EX AF, AF'      ; Sauvegarde de AF' 
        JP _GRAPH_SPRITE_SHOW_FAST_SPRITE_16_BoucleSurLesLignes 

_GRAPH_SPRITE_SHOW_FAST_SPRITE_16_FinBoucleSurLesLignes 

        EX AF, AF'      ; Restauration de AF' 
        POP AF          ; 
        EX AF, AF'      ; 

_GRAPH_SPRITE_SHOW_FAST_SPRITE_16_END 

        POP IY          ; Restauration des registres 
        POP IX 
        POP HL 
        POP DE 
        POP BC 
        POP AF 
        RET 


;********************************************************************
; Permet de cacher un objet graphique
;
; En entrée
;	IY <=> Adresse d'une structure Object
; En sortie
;	aucun
; Registres affectés
;	aucun
; Remarques
;	- Cette méthode doit être utilisée pour sauver la zone recouvert par 
;	  un objet, avant son affichage. Cette méthode permet de restaurater
;	  la zone de l'écran lorsque l'objet est caché.
;
;	Object {
;		WORD x		 ; position sur x de l'objet (peut être une coordonnée graphique ou autre)
;		WORD y		 ; position sur y de l'objet (peut être une coordonnée graphique ou autre)
;		BYTE xincr	 ; incrémentation sur x, permet de définir une direction sur x
;		BYTE yincr	 ; incrémentation sur y, permet de définir une direction sur y
;		BYTE state	 ; liste des différents états du sprite, codés sous forme binaire
;				 ;   Bit    Description
;				 ;    0		Visibilité de l'objet { 1 = visible }
;				 ;    1		Type d'objet { 0 = fixe, 1 = animé }
;				 ;    2		Mode fantôme { 1 = mode fantôme activé } (permet de désactiver l'interactivité avec d'autres objets)
;				 ;    3		-
;				 ;    4		-
;				 ;    5		-
;				 ;    6		-
;				 ;    7		-
;		WORD sprite	 ; référence à la structure contenant les données du sprite associé à l'objet
;		WORD memory_block; référence à la structure contenant les données de la zone graphique impactée par le sprite
;	} (11 octets)
;
GRAPH_SPRITE_HIDE_OBJECT:

	PUSH BC

	CALL GRAPH_SPRITE_SHOW_BACKGROUND_OBJECT
	; Mise à jour de l'état de l'objet
	LD B, CST_GRAPH_OBJECT_ATTRIBUT_VISIBLE
	LD C, 0
	CALL GRAPH_SPRITE_OBJECT_SET_STATE
	
_GRAPH_SPRITE_HIDE_OBJECT_END

	POP BC
	RET



;********************************************************************
; Permet d'afficher un objet
; d'un objet
;
; En entrée
;	BC <=> x
;	DE <=> y
;	IY <=> Adresse d'une structure Object
; En sortie
;	aucun
; Registres affectés
;	aucun
; Remarques
;	- Cette méthode doit être utilisée pour sauver la zone recouvert par 
;	  un objet, avant son affichage. Cette méthode permet de restaurater
;	  la zone de l'écran lorsque l'objet est caché.
;
;	Object {
;		WORD x		 ; position sur x de l'objet (peut être une coordonnée graphique ou autre)
;		WORD y		 ; position sur y de l'objet (peut être une coordonnée graphique ou autre)
;		BYTE xincr	 ; incrémentation sur x, permet de définir une direction sur x
;		BYTE yincr	 ; incrémentation sur y, permet de définir une direction sur y
;		BYTE state	 ; liste des différents états du sprite, codés sous forme binaire
;				 ;   Bit    Description
;				 ;    0		Visibilité de l'objet { 1 = visible }
;				 ;    1		Type d'objet { 0 = fixe, 1 = animé }
;				 ;    2		Mode fantôme { 1 = mode fantôme activé } (permet de désactiver l'interactivité avec d'autres objets)
;				 ;    3		-
;				 ;    4		-
;				 ;    5		-
;				 ;    6		-
;				 ;    7		-
;		WORD sprite	 ; référence à la structure contenant les données du sprite associé à l'objet
;		WORD memory_block; référence à la structure contenant les données de la zone graphique impactée par le sprite
;	} (11 octets)
;
GRAPH_SPRITE_SHOW_OBJECT:

	PUSH HL
	PUSH IX

	; Mise à jour de l'état de l'objet
	LD H, B
	LD L, C
	LD B, CST_GRAPH_OBJECT_ATTRIBUT_VISIBLE
	LD C, 1
	CALL GRAPH_SPRITE_OBJECT_SET_STATE
	LD B, H
	LD C, L
	
	; Sauvegarde de l'arrière plan de l'objet
	CALL GRAPH_SPRITE_SAVE_BACKGROUND_OBJECT

	; Affichage du sprite
	LD H, (IY + 8)	; Adresse du sprite
	LD L, (IY + 7)	;
	PUSH HL
	POP IX
	CALL GRAPH_SPRITE_SHOW_SPRITE

_GRAPH_SPRITE_SHOW_OBJECT_END

	POP IX
	POP HL
	RET


;********************************************************************
; Permet de sauvegarder une zone de l'écran impacté par l'affichage
; d'un objet graphique
;
; En entrée
;	IY <=> Adresse d'une structure Object
;	BC <=> x
;	DE <=> y
; En sortie
;	aucun
; Registres affectés
;	aucun
; Remarques
;	- Cette méthode doit être utilisée pour sauver la zone recouvert par 
;	  un objet, avant son affichage. Cette méthode permet de restaurater
;	  la zone de l'écran lorsque l'objet est caché.
;
;	Object {
;		WORD x		 ; position sur x de l'objet (peut être une coordonnée graphique ou autre)
;		WORD y		 ; position sur y de l'objet (peut être une coordonnée graphique ou autre)
;		BYTE xincr	 ; incrémentation sur x, permet de définir une direction sur x
;		BYTE yincr	 ; incrémentation sur y, permet de définir une direction sur y
;		BYTE state	 ; liste des différents états du sprite, codés sous forme binaire
;				 ;   Bit    Description
;				 ;    0		Visibilité de l'objet { 1 = visible }
;				 ;    1		Type d'objet { 0 = fixe, 1 = animé }
;				 ;    2		Mode fantôme { 1 = mode fantôme activé } (permet de désactiver l'interactivité avec d'autres objets)
;				 ;    3		-
;				 ;    4		-
;				 ;    5		-
;				 ;    6		-
;				 ;    7		-
;		WORD sprite	 ; référence à la structure contenant les données du sprite associé à l'objet
;		WORD memory_block; référence à la structure contenant les données de la zone graphique impactée par le sprite
;	} (11 octets)
;
;	Sprite {
;		BYTE width	 ; largeur du sprite en pixel
;		BYTE height	 ; hauteur du sprite en pixel
;		WORD sprite_size ; taille du tampon
;		WORD sprite	 ; adresse du tampon contenant les données du sprite
;		WORD mask	 ; adresse du tampon du masque logique qui doit avoir la même taille que le sprite
;		BYTE static_datas; indique si les données du sprite sont issues de données statiques
;	} (9 octets)
;
;	MemoryBlock {
;		BYTE width	 ; largeur en octet du block mémoire
;		BYTE height	 ; hauteur du block en pixel
;		BYTE lines_count ; nombre total de lignes, réellement traitées
;		WORD buffer	 ; adresse du tampon contenant les données du block mémoire
;		WORD buffer_size ; taille du tampon
;		WORD memory_adr	 ; adresse mémoire de base, de la zone sauvegardé
;		BYTE ligne	 ; numéro de la ligne courante dans la série de lignes
;	} (10 octets)
;
_x DB 0
_y DB 0
GRAPH_SPRITE_SAVE_BACKGROUND_OBJECT:

	PUSH AF
	PUSH BC
	PUSH DE
	PUSH HL
	PUSH IX

	; Récupération de la position de l'objet
	LD B, (IY + 1)	; (IY + 0) (IY + 1) Position x sur 16 bits (signé)
	LD C, (IY + 0)	; 
	LD D, (IY + 3)	; (IY + 2) (IY + 3) Position y sur 16 bits (signé)
	LD E, (IY + 2)	;

	; Récupération de l'adresse du sprite
	LD H, (IY + 8)	; (IY + 8) (IY + 7) Adresse du sprite
	LD L, (IY + 7)	;
	PUSH HL
	POP IX

	LD A, (IX + 0)
	LD (_x), A
	LD A, (IX + 1)
	LD (_y), A
	;----------------------------------------------------------------
	; - 1 -
	; Vérification de la position du sprite à l'écran
	;
	; En entrée
	;	BC <=> Position sur x
	;	DE <=> Position sur y
	;	IX <=> Adresse d'une structure Sprite
	;
	; En sortie
	;	A  <=> Si le sprite est visible à l'écran, A contient 1 sinon 0
	;	GRAPH_POSITION_DX1 => renseigné
	;	GRAPH_POSITION_DX2 => renseigné
	;	GRAPH_POSITION_DY1 => renseigné
	;	GRAPH_POSITION_DY2 => renseigné
	;
	;	Si DX1 <> 0 => BC = 0
	;	Si DY1 <> 0 => DE = 0
	;
	CALL GRAPH_SPRITE_TEST_POSITION
	OR A	; Vérification si A = 1, si oui le sprite est visible à l'écran
		; sinon on sort
	JP z, GRAPH_SPRITE_SAVE_BACKGROUND_OBJECT_END


	;********************************************************************
	; - 2 -
	; Calcul de la largeur et la hauteur de la zone mémoire sauvegardée
	; en fonction de la partie visible et du nombre de pixels par octet
	;
	LD D, E		; Sauvegarde de Y
	
	; Récupération de l'adresse du block
	LD H, (IY + 10)	; (IY + 10) (IY + 9) Adresse du bloc mémoire
	LD L, (IY + 9)	;
	PUSH HL
	POP IX		;

	LD A, (GRAPH_POSITION_DX1)
	LD H, A
	LD A, (GRAPH_POSITION_DX2)
	ADD H
	
	LD E, A
	LD A, CST_GRAPH_PIXELS_PER_BYTE
	DEC A
	CALL MATH_SRL_8
	LD A, (_x)
	SBC E		; On ajoute une éventuelle retenue (carry) pour prendre en compte le reste de la division
	; Sauvegarde de la largeur en octet, de la zone graphique à sauvegarder
	LD (IX + 0), A	; (IX + 0) Largeur en octet de la zone graphique
	
	; Calcul du nombre d'octets nécessaires pour stocker la hauteur de l'image
	LD A, (GRAPH_POSITION_DY1)
	LD H, A
	LD A, (GRAPH_POSITION_DY2)
	LD L, A
	LD A, (_y)	;(IX + 1) Hauteur de l'image
	SUB H
	SUB L

	; Sauvegarde de la hauteur en pixel, de la zone graphique à sauvegarder
	LD (IX + 1), A	; (IX + 1) Hauteur en octet de la zone graphique


	;********************************************************************
	; - 3 -
	; Sauvegarde de la zone impactée par le sprite dans la structure MemoryBloc
	;
	; En entrée
	;	IX <=> Adresse d'une structure MemoryBlock
	;	BC <=> Position sur x en mémoire graphique
	;	A  <=> Position sur y en mémoire graphique
	; En sortie
	;	aucun
	;
	; Récupération de la position du Y (partie basse de DE)
	; BC conteient déjà la position sur X
	LD A, D		; Y dans A
	
	CALL GRAPH_SPRITE_SAVE_MEMORY_BLOCK

GRAPH_SPRITE_SAVE_BACKGROUND_OBJECT_END

	POP IX
	POP HL
	POP DE
	POP BC
	POP AF
	RET



;********************************************************************
; Permet de restaurer une zone de l'écran impacté par l'affichage
; d'un objet graphique
;
; En entrée
;	IY <=> Adresse d'une structure Object
; En sortie
;	aucun
; Registres affectés
;	aucun
; Remarques
;	- Cette méthode doit être utilisée pour sauver la zone recouvert par 
;	  un objet, avant son affichage. Cette méthode permet de restaurater
;	  la zone de l'écran lorsque l'objet est caché.
;
;	Object {
;		WORD x		 ; position sur x de l'objet (peut être une coordonnée graphique ou autre)
;		WORD y		 ; position sur y de l'objet (peut être une coordonnée graphique ou autre)
;		BYTE xincr	 ; incrémentation sur x, permet de définir une direction sur x
;		BYTE yincr	 ; incrémentation sur y, permet de définir une direction sur y
;		BYTE state	 ; liste des différents états du sprite, codés sous forme binaire
;				 ;   Bit    Description
;				 ;    0		Visibilité de l'objet { 1 = visible }
;				 ;    1		Type d'objet { 0 = fixe, 1 = animé }
;				 ;    2		Mode fantôme { 1 = mode fantôme activé } (permet de désactiver l'interactivité avec d'autres objets)
;				 ;    3		-
;				 ;    4		-
;				 ;    5		-
;				 ;    6		-
;				 ;    7		-
;		WORD sprite	 ; référence à la structure contenant les données du sprite associé à l'objet
;		WORD memory_block; référence à la structure contenant les données de la zone graphique impactée par le sprite
;	} (11 octets)
;

GRAPH_SPRITE_SHOW_BACKGROUND_OBJECT:

	PUSH HL
	PUSH IX

	; Récupération de la position de l'objet
	LD H, (IY + 10)	; (IY + 10) (IY + 9) Adresse du block mémoire
	LD L, (IY + 9)	; 
	PUSH HL
	POP IX

	; Restauration du block mémoire	
	CALL GRAPH_SPRITE_SHOW_MEMORY_BLOCK

GRAPH_SPRITE_SHOW_BACKGROUND_OBJECT_END

	POP IX
	POP HL
	RET


;********************************************************************
; Permet de restaurer un bloc mémoire à l'écran
;
; En entrée
;	IX <=> Adresse d'une structure MemoryBlock
; En sortie
;	aucun
; Registres affectés
;	aucun
; Remarques
;	- Cette méthode doit être utilisée pour restaurer une zone de l'écran
;
;	MemoryBlock {
;		BYTE width	 ; largeur en octet du block mémoire
;		BYTE height	 ; hauteur du block en pixel
;		BYTE lines_count ; nombre total de lignes, réellement traitées
;		WORD buffer	 ; adresse du tampon contenant les données du block mémoire
;		WORD buffer_size ; taille du tampon
;		WORD memory_adr	 ; adresse mémoire de base, de la zone sauvegardé
;		BYTE ligne	 ; numéro de la ligne courante dans la série de lignes
;	} (10 octets)
;

GRAPH_SPRITE_SHOW_MEMORY_BLOCK:

	PUSH AF		; Sauvegarde des registres
	PUSH BC
	PUSH DE
	PUSH HL
	PUSH IY

	EX AF, AF'	; Sauvegarde de AF'
	PUSH AF		;
	EX AF, AF'	;

	; Récupération de la taille 
	LD A, (IX + 2)	; Nombre total de lignes à traiter

	; Si A = 0 on sort
	OR A
	JP z, _GRAPH_SPRITE_SHOW_MEMORY_BLOCK_END

	; Calcul de l'offset à ajouter pour se positionner sur l'adresse de base
	LD B, 0		; Reset de B pour addition avec HL
	LD C, (IX + 0)	; Récupération du nombre d'octets à traiter par ligne
	LD HL, &800	; Offset par défaut pour passer d'une ligne à l'autre
	SBC HL, BC	; Ajustement de l'offset en fonction du nombre d'octet traité par ligne
	LD B, C		; Transfert de C dans B pour préparation du compteur de lignes
	SLA C		; On multiplie C par 2 de manière à ce que C soit = à 2 fois B pour la gestion du compteur de lignes


	; Utilisation de SP pour stocker le décalage entre chaque ligne lors du passage à une nouvelle ligne
	LD IY, 0	
	ADD IY, SP	; Sauvegarde de SP dans IY pour le retour
	LD SP, HL	; Sauvegarde du décalage dans SP
	
	; Préparation des adresses de transfert
	LD H, (IX + 4)	; Adresse du tampon dans HL pour traitement
	LD L, (IX + 3)	;
	LD D, (IX + 8)	; Adresse de destination dans DE, pour traitement
	LD E, (IX + 7)	;

	EX AF, AF'
	LD A, (IX + 9)	;
	EX AF, AF'

_GRAPH_SPRITE_SHOW_MEMORY_BLOCK_1

	LDI		; Restauration des données de la ligne courante
	DJNZ _GRAPH_SPRITE_SHOW_MEMORY_BLOCK_1

	EX HL, DE	; Echange de HL avec DE pour calculer l'adresse de la ligne suivante par rapport au décalage

	; Décrémentation du n° de la ligne courant dans la série de lignes
	EX AF, AF'	; Récupération du n° de la ligne courante dans la série de lignes
	DEC A		; Décrémentation du n° de la ligne courante
	JP nz, _GRAPH_SPRITE_SHOW_MEMORY_BLOCK_2

	; Test que toutes les lignes de la série de lignes courante ont été traitées
	LD A, C
	LD BC, &3FB0	; &3FB0 = &4000 - &50 = Espace d'adressage d'une série complète de lignes - Offset pour la série de lignes suivantes
	SBC HL, BC	;       => HL = HL - &4000 + &50
	LD C, A
	LD A, 8		; Traitement des huit prochaines lignes

_GRAPH_SPRITE_SHOW_MEMORY_BLOCK_2

	ADD HL, SP	; Passage à la ligne suivante
	EX HL, DE	; Restauration des deux registres
	LD B, C		; Sachant que C étati = à 2 fois B, C contient actuellement le d'octet par ligne
	SLA C		; On remultiplie C par 2 pour le prochain décompte

	EX AF, AF'
	DEC A		; Décrémentation du nombre de ligne à traiter
	JP nz, _GRAPH_SPRITE_SHOW_MEMORY_BLOCK_1

_GRAPH_SPRITE_SHOW_MEMORY_BLOCK_END

	LD SP, IY	; Restauration de SP

	EX AF, AF'	; Restauration de AF'
	POP AF		;
	EX AF, AF'	;

	POP IY		; Restauration des registres
	POP HL
	POP DE
	POP BC
	POP AF
	RET




;********************************************************************
; Permet de sauvegarder une zone écran dans une structure MemoryBloc
;
; En entrée
;	IX <=> Adresse d'une structure MemoryBlock
;	BC <=> Position sur x en mémoire graphique
;	A  <=> Position sur y en mémoire graphique
; En sortie
;	aucun
; Registres affectés
;	aucun
; Remarques
;	- Cette méthode doit être utilisée pour sauver une zone de l'écran
;
;	MemoryBlock {
;		BYTE width	 ; largeur en octet du block mémoire
;		BYTE height	 ; hauteur du block en pixel
;		BYTE lines_count ; nombre total de lignes, réellement traitées
;		WORD buffer	 ; adresse du tampon contenant les données du block mémoire
;		WORD buffer_size ; taille du tampon
;		WORD memory_adr	 ; adresse mémoire de base, de la zone sauvegardé
;		BYTE ligne	 ; numéro de la ligne courante dans la série de lignes
;	} (10 octets)
;

GRAPH_SPRITE_SAVE_MEMORY_BLOCK:

	PUSH AF		; Sauvegarde des registres
	PUSH BC
	PUSH DE
	PUSH HL
	PUSH IY


	; Calcul de l'adresse de base du premier pixel à sauvegarder
	;
	; En entrée
	;	BC <=> X1 sur 16 bits
	;	A  <=> Y1 sur 8 bits
	; En sortie
	; 	HL <=> Adresse du premier point
	;
	CALL GRAPH_ADR_OF_PIXEL
	LD (IX + 8), H	; Sauvegarde de l'adresse de base de la zone graphique
	LD (IX + 7), L	;

	; Calcul du n° de la ligne courante dans la série de ligne
	LD C, A		; Stockage du n° de la ligne courante dans C
	EX AF, AF'	; Utilisationde A'
	PUSH AF		; Sauvegarde de AF'
	LD A, C		; Stockage du n° de la ligne courante dans A'
	AND 7		;
	LD C, A		; Calcul du n° de la ligne courante dans la série de lignes	
	LD A, 8		;
	SBC C		;
	LD (IX + 9), A	; Stockage du n° de la ligne courante dans la série de lignes
	EX AF, AF'

	; Récupération de la taille 
	LD B, (IX + 1)	; Hauteur du sprite en pixels

	; Vérification que l'on ne dépasse pas la hauteur maximale sur y pour la sauvegarde, CST_GRAPH_SCREEN_HEIGTH
	ADD A, B	; Nombre de lignes à traiter ajouté à A
	DEC A
	CP CST_GRAPH_SCREEN_HEIGTH - 1
	JP c, _GRAPH_SPRITE_SAVE_MEMORY_BLOCK_1
			; Ajustement en fonction de la hauteur de l'écran et du nombre de lignes à traiter
	SUB A, CST_GRAPH_SCREEN_HEIGTH - 1
	LD B, A		

_GRAPH_SPRITE_SAVE_MEMORY_BLOCK_1

	; Restauration du nombre de lignes à traiter dans A
	LD A, B
	LD (IX + 2), A	; Sauvegarde du nombre réel de lignes traitées
	OR A		; Si A = 0 on sort
	JP z, _GRAPH_SPRITE_SAVE_MEMORY_BLOCK_END

	; Calcul de l'offset à ajouter pour se positionner sur l'adresse de base
	EX HL, DE
	LD B, 0		; Reset de B pour addition avec HL
	LD C, (IX + 0)	; Récupération du nombre d'octets à traiter par ligne
	LD HL, &800	; Offset par défaut pour passer d'une ligne à l'autre
	SBC HL, BC	; Ajustement de l'offset en fonction du nombre d'octet traité par ligne
	LD B, C		; Transfert de C dans B pour préparation du compteur de lignes
	SLA C		; On multiplie C par 2 de manière à ce que C soit = à 2 fois B pour la gestion du compteur de lignes
	
	; Sauvegarde de SP pour utilisation
	LD IY, 0
	ADD IY, SP	; Sauvegarde de SP dans IY pour utilisation
	LD SP, HL	; Transfert de l'offset dans SP pour utilisation lors du passage de ligne à ligne
	
	; Préparation des addreses de transfert
	EX HL, DE	; Récupération de l'adresse de base de la première ligne
	LD D, (IX + 4)	; Transfert de l'adresse du tampon dans DE
	LD E, (IX + 3)	;
	
_GRAPH_SPRITE_SAVE_MEMORY_BLOCK_2

	LDI		; Sauvegarde des données de la ligne courante
	DJNZ _GRAPH_SPRITE_SAVE_MEMORY_BLOCK_2
	
	; Décrémentation du n° de la ligne courant dans la série de lignes
	EX AF, AF'	; Récupération du n° de la ligne courante dans la série de lignes
	DEC A		; Décrémentation du n° de la ligne courante
	JP nz, _GRAPH_SPRITE_SAVE_MEMORY_BLOCK_3

	; Test que toutes les lignes de la série de lignes courante ont été traitées
	LD A, C
	LD BC, &3FB0	; &3FB0 = &4000 - &50 = Espace d'adressage d'une série complète de lignes - Offset pour la série de lignes suivantes
	SBC HL, BC	;       => HL = HL - &4000 + &50
	LD C, A
	LD A, 8		; Traitement des huit prochaines lignes

_GRAPH_SPRITE_SAVE_MEMORY_BLOCK_3
	
	ADD HL, SP	; Passage à la ligne suivante
	LD B, C		; Sachant que C était = à 2 fois B, C contient actuellement le d'octet par ligne
	SLA C		; On remultiplie C par 2 pour le prochain décompte

	EX AF, AF'	; Récupération du nombre de lignes à traiter
	DEC A		; Décrémentation du nombre de ligne à traiter
	JP nz, _GRAPH_SPRITE_SAVE_MEMORY_BLOCK_2

_GRAPH_SPRITE_SAVE_MEMORY_BLOCK_END

	LD SP, IY	; Restauration de SP

	EX AF, AF'	; Restauration de AF'
	POP AF		;
	EX AF, AF'	;

	POP IY		; Restauration des registres
	POP HL
	POP DE
	POP BC
	POP AF
	RET









;------------------------------------------------------------------------------------------
;			Déclarations des variables et constantes
;------------------------------------------------------------------------------------------
CALLBACK_TEXT_PRINT_CHAR	EQU	&BB5A   ; Affichage d'un caractère ou d'un code de contrôle sur l'écran en mode texte
CALLBACK_GRAPH_INIT_VIDEO_MODE	EQU 	&BC0E	; Adresse de la routine d'initialisation vidéo
CALLBACK_GRAPH_BORDER			EQU	&BC38	; B et C
CALLBACK_GRAPH_ADR_OF_PIXEL 	DW	GRAPH_ADR_OF_PIXEL_WITH_DIRECT_MODE
				; Adresse de la routine permettant d'effectuer le calcul de l'adresse de base
				; d'un point. L'adresse de cette routine peut changer en fonction du mode de
				; tracé sélectionné, le mode direct ou indirect. Le mode direct est plus performant,
				; utilise une table d'adresse et peut être activé via la fonction GRAPH_ACTIVE_DIRECT_MODE
; Définitions liées aux données graphiques
DEF_GRAPH_VIDEO_ADR		DEFW	&C000		; Segment vidéo variable
DEF_GRAPH_TABLE_PIXEL_2		DEFB 	0, 128		; &00, &80
DEF_GRAPH_TABLE_PIXEL_4		DEFB 	0, 8, 128, 136	; &00, &08, &80, &88
DEF_GRAPH_TABLE_PIXEL_16	DEFB 	0, 2, 8, 10, 32, 34, 40, 42, 128, 130, 136, 138, 160, 162, 168, 170
				; 	&00, &02, &08, &0A, &20, &22, &28, &80, &82, &88, &8A, &A0, &A2, &A8, &AA
; Constantes graphiques
CST_GRAPH_VIDEO_MODE			EQU	0
CST_GRAPH_PIXELS_PER_BYTE		EQU	CST_GRAPH_VIDEO_MODE + 1 * CST_GRAPH_VIDEO_MODE + 2
CST_GRAPH_SCREEN_WIDTH			EQU	CST_GRAPH_VIDEO_MODE + 1 * CST_GRAPH_VIDEO_MODE * 80 + 160
CST_GRAPH_SCREEN_HEIGTH			EQU	200
CST_GRAPH_OBJECT_ATTRIBUT_VISIBLE	EQU	1	; Bit 0 de l'état d'un objet - Objet visible
CST_GRAPH_OBJECT_ATTRIBUT_MOVING	EQU	2	; Bit 1 de l'état d'un objet - Objet fixe
CST_GRAPH_OBJECT_ATTRIBUT_GHOST		EQU	4	; Bit 2 de l'état d'un objet - Objet fantôme

; Constantes liées au matériel
CST_GATE_ARRAY_PORT			EQU	&7F	; Port du Gate Array du CPC
CST_GATE_ARRAY_REG_INK_NUMBER		EQU	0	; Bits 7=0, 6=0, les bits 0-3 donnent le n° de la couleur (Selection du n° de l'encre)
CST_GATE_ARRAY_REG_INK_COLOR		EQU	64	; Bits 7=0, 6=1 (Selection de la couleur de l'encre)
CST_GATE_ARRAY_REG_ROM_COMMUTATIONS	EQU	128	; Bits 7=1, 6=0 (Commutations Roms, gestion du diviseur d'interruptions et du mode écran)
CST_GATE_ARRAY_REG_RAM_COMMUTATIONS	EQU	198	; Bits 7=1, 6=1 (Commutations RAM sur 6128)

CST_PPI_CONTROLER_PORT			EQU	&F5	; Port du Programmable Peripheral Interface


; n° des position des couleurs du CPC. (table de correspondances)
; Permet d'associé un n° de couleur de la palette image à une encre
CPC_COLORS_POSITIONS_MODE0		DB 0,8,2,10,4,12,6,14,1,9,3,11,5,13,7,15
CPC_COLORS_POSITIONS_MODE1		DB 0,2,1,3
CPC_COLORS_POSITIONS_MODE2		DB 0,1


; Variables liées à l'affichage des sprites
GRAPH_POSITION_DX1	DB 0	; Les variables (dx1), (dx2), (dy1) et (dy2) sont utilisées avant l'affichage des sprites
GRAPH_POSITION_DX2	DB 0	; lors du calcul des positions. Lorsqu'une partie d'un sprite n'est pas visible à l'écran,
GRAPH_POSITION_DY1	DB 0	; elles permettent de connaître le nombre de pixels non visibles. Ces variables sont affectées
GRAPH_POSITION_DY2	DB 0	; suite à un appel à la méthode "GRAPH_SPRITE_TEST_POSITION"
				; Voir la description détaillée plus bas.

; Tables des données
VIRTUAL_TABLE_OFFSET	DEFW 0	  ; Permet gérer les décalages dans la table virtuelle
VIRTUAL_TABLE_SIZE	EQU 1000  ; Taille en octet de la table virtuelle
STACK_SIZE		EQU 50	  ; Taille de la pile. ATTENTION de réserver un espace nécessaire dans le cas contraire
				  ; des problèmes d'affichage ou de blocage peuvent arriver

STACK			DEFS STACK_SIZE ; Déclaration de la pile
VIRTUAL_TABLE		DEFS VIRTUAL_TABLE_SIZE 

SPRITES		DEFB  3, 3, 3, 3, 3, 3, 3, 3, 3
		DEFB  3, 2, 0, 0, 0, 0, 0, 2, 3
		DEFB  3, 0, 2, 0, 0, 0, 2, 0, 3
		DEFB  3, 0, 0, 2, 0, 2, 0, 0, 3
		DEFB  3, 0, 0, 0, 2, 0, 0, 0, 3
		DEFB  3, 0, 0, 2, 0, 2, 0, 0, 3
		DEFB  3, 0, 2, 0, 0, 0, 2, 0, 3
		DEFB  3, 2, 0, 0, 0, 0, 0, 2, 3
		DEFB  3, 3, 3, 3, 3, 3, 3, 3, 3

MASKS		DEFB  0, 0, 0, 0, 0, 0, 0, 0, 0
		DEFB  0, 0, 0, 0, 0, 0, 0, 0, 0
		DEFB  0, 0, 0, 0, 0, 0, 0, 0, 0
		DEFB  0, 0, 0, 0, 0, 0, 0, 0, 0
		DEFB  0, 0, 0, 0, 0, 0, 0, 0, 0
		DEFB  0, 0, 0, 0, 0, 0, 0, 0, 0
		DEFB  0, 0, 0, 0, 0, 0, 0, 0, 0
		DEFB  0, 0, 0, 0, 0, 0, 0, 0, 0
		DEFB  0, 0, 0, 0, 0, 0, 0, 0, 0

ADDRESS_OF_LINES
		DW &C000,&C800,&D000,&D800,&E000,&E800,&F000,&F800 ; Ligne n° 0-7
	        DW &C050,&C850,&D050,&D850,&E050,&E850,&F050,&F850 ; Ligne n° 8-15
		DW &C0A0,&C8A0,&D0A0,&D8A0,&E0A0,&E8A0,&F0A0,&F8A0 ; Ligne n° 16-23
		DW &C0F0,&C8F0,&D0F0,&D8F0,&E0F0,&E8F0,&F0F0,&F8F0 ; Ligne n° 24-31
 		DW &C140,&C940,&D140,&D940,&E140,&E940,&F140,&F940 ; Ligne n° 32-39
   		DW &C190,&C990,&D190,&D990,&E190,&E990,&F190,&F990 ; Ligne n° 40-47
     		DW &C1E0,&C9E0,&D1E0,&D9E0,&E1E0,&E9E0,&F1E0,&F9E0 ; Ligne n° 48-55
       		DW &C230,&CA30,&D230,&DA30,&E230,&EA30,&F230,&FA30 ; Ligne n° 56-63
        	DW &C280,&CA80,&D280,&DA80,&E280,&EA80,&F280,&FA80 ; Ligne n° 64-71
         	DW &C2D0,&CAD0,&D2D0,&DAD0,&E2D0,&EAD0,&F2D0,&FAD0 ; Ligne n° 72-79
         	DW &C320,&CB20,&D320,&DB20,&E320,&EB20,&F320,&FB20 ; Ligne n° 80-87
         	DW &C370,&CB70,&D370,&DB70,&E370,&EB70,&F370,&FB70 ; Ligne n° 88-95
         	DW &C3C0,&CBC0,&D3C0,&DBC0,&E3C0,&EBC0,&F3C0,&FBC0 ; Ligne n° 96-103
         	DW &C410,&CC10,&D410,&DC10,&E410,&EC10,&F410,&FC10 ; Ligne n° 104-111
        	DW &C460,&CC60,&D460,&DC60,&E460,&EC60,&F460,&FC60 ; Ligne n° 112-119
         	DW &C4B0,&CCB0,&D4B0,&DCB0,&E4B0,&ECB0,&F4B0,&FCB0 ; Ligne n° 120-127
         	DW &C500,&CD00,&D500,&DD00,&E500,&ED00,&F500,&FD00 ; Ligne n° 128-135
         	DW &C550,&CD50,&D550,&DD50,&E550,&ED50,&F550,&FD50 ; Ligne n° 136-143
         	DW &C5A0,&CDA0,&D5A0,&DDA0,&E5A0,&EDA0,&F5A0,&FDA0 ; Ligne n° 144-151
         	DW &C5F0,&CDF0,&D5F0,&DDF0,&E5F0,&EDF0,&F5F0,&FDF0 ; Ligne n° 152-159
         	DW &C640,&CE40,&D640,&DE40,&E640,&EE40,&F640,&FE40 ; Ligne n° 160-167
         	DW &C690,&CE90,&D690,&DE90,&E690,&EE90,&F690,&FE90 ; Ligne n° 168-175
         	DW &C6E0,&CEE0,&D6E0,&DEE0,&E6E0,&EEE0,&F6E0,&FEE0 ; Ligne n° 176-183
         	DW &C730,&CF30,&D730,&DF30,&E730,&EF30,&F730,&FF30 ; Ligne n° 184-191
         	DW &C780,&CF80,&D780,&DF80,&E780,&EF80,&F780,&FF80 ; Ligne n° 192-199



; Constantes liées au clavier (vecteurs et touches)
READ "KEYBR.asm"

;------------------------------------------------------------------------------------------
;			Informations techniques
;
; Etat des registres après comparaison
;
; C = 0 si A >= r
; C = 1 si A <  r
; Z = 0 si A <> r
; Z = 1 si A =  r
;
; Si A < r => S = 1, H = 1, N = 1, C = 1
; Si A = r => Z = 1, N = 1
; Si A > r => N = 1
;
;
;
;------------------------------------------------------------------------------------------
;			Informations sur les vecteurs systèmes utilisés
;------------------------------------------------------------------------------------------
;
; CALLBACK_KEYBR_INKEY	(&BB1E) INKEY
;
;	Description - Teste si la  touche dont le numero est contenu dans A est 
;	pressee. Si ce n'est pas le cas, A vaut zero en sortie et le flag z est mis, 
;	sinon A est non nul mais modifie. Dans es deux cas, C contient l'etat des 
;	touches (SHIFT) et (CTRL), par ses bits 7 (pour (CTRL)) et 5 (pour (SHIFT)), 
;	ces bits etant mis lorsque les touches correspondantes sont enfoncees.
;	Notes - De toute facon, HL est modifie.
;	Adresses d'execution - 1CBDH (464), 1 E45H (664 et 6128).
;
; CALLBACK_KEYBR_SPEED_KEY (&BB3F) SPEEK
;
;	Description - Realise la fonction BASIC SPEED KEY x,y. En entree, x est place 
;	dans H, et y dans L.
;		H = temps avant la premiere repetition,
;		L = La vitesse de repetition.
;	Ces vitesses sont indiquees en cinquantieme de seconde (LD H,50 pour une seconde).
;	Notes - AF est modifie.
;	Adresses d'execution - 1C6DH (464), 1DF6H (664 et 6128).
;
;
;
;------------------------------------------------------------------------------------------
;					Algorithmes
;------------------------------------------------------------------------------------------
; Rappel du calcul de l'adresse de base d'une ligne
; -------------------------------------------------
;
;	[Adresse de base de la ligne] = [Adresse vidéo]
;					+ [Adresse de la série]
;				 	+ [Offset de la ligne] * &800
;
;		- [Adresse de la série] = (Y1 \ 8) * &50
;		- [Offset de la ligne] = (Y1 MOD 8) * &800
;
;	[Adresse de base de la ligne] = &C000 + ((Y1 \ 8) * &50 + ((Y1 MOD 8) * &800)
;
; Rappel du calcul sur l'adresse d'un point
;
;	[Adresse du premier point] = [Adresse de base de la ligne] + [Offset du point]
;
;		- [Offset du point] = X1 \ [Nombre de pixels par octet]
;
;
; -------------------------------------------------
; Le tracé de lignes
; -------------------------------------------------
;
;	CALL Pixel (X1, Y1, Couleur)	; Premier pixel
;
;	IF X2 < X1 THEN Echange X2 avec X1
;	IF Y2 < Y1 THEN Echange Y2 avec Y1
;
;	dx = X2 – X1
;	dy = Y2 – Y1
;
;	IF dy > dx THEN
;		Cumul = dy \ 2
;		
;		FOR i = 1 TO dy 
;			Y1 = Y1 + 1
;			Cumul = cumul + dx
;			IF cumul >= dy THEN
;				Cumul = cumul - dy
;				X1 = X1 + 1
;			END
;			CALL Pixel (X1, Y1, Couleur)	; Pixels suivants
;		NEXT i
;	END
;	ELSE
;
;		Cumul = dx \ 2
;
;		FOR i = 1 TO dx
;			X1 = X1 + 1
;			Cumul = cumul + dy
;			IF cumul >= dx THEN
;				Cumul = cumul - dx
;				Y1 = Y1 + 1
;			END
;			CALL Pixel (X1, Y1, Couleur)	; Pixels suivants
;		NEXT i
;
;	END
;
;
;------------------------------------------------------------------------------------------
;	Utilisation des variables (dx1),(dx2),(dy1),(dy2) lors de l'affichage d'un sprite
;	
;		(dx1) <=> GRAPH_POSITION_DX1
;		(dx2) <=> GRAPH_POSITION_DX2
;		(dy1) <=> GRAPH_POSITION_DY1
;		(dy2) <=> GRAPH_POSITION_DY2
;
; 	Infos
;		- Ces variables sont renseignées après l'appel à la méthode "GRAPH_SPRITE_TEST_POSITION"
;		  Cette méthode prend en paramètre une position (x,y) respectivement (BC,DE) sur 16 bits
;		  et l'adresse de le structure d'un sprite via IX
;
;				   _______
;			partie	  |sprite |dy1
;			invisible |    ___|_____________
;				  |   |	  |             |
;				  |___|___|             |----
;				   dx1|	   partie       | dx2
;				      |	   visible  	|
;				      |    de l'écran	|
;				      |_________________|
;				          |
;					  |dy2
;
;------------------------------------------------------------------------------------------
;				Déclaration des structures
;
;	Sprite {
;		BYTE width	 ; largeur du sprite en pixel
;		BYTE height	 ; hauteur du sprite en pixel
;		WORD sprite_size ; taille du tampon
;		WORD sprite	 ; adresse du tampon contenant les données du sprite
;		WORD mask	 ; adresse du tampon du masque logique qui doit avoir la même taille que le sprite
;		BYTE static_datas; indique si les données du sprite sont issues de données statiques
;	} (9 octets)
;
;	MemoryBlock {
;		BYTE width	 ; largeur en octet du block mémoire
;		BYTE height	 ; hauteur du block en pixel
;		BYTE lines_count ; nombre total de lignes, réellement traitées
;		WORD buffer	 ; adresse du tampon contenant les données du block mémoire
;		WORD buffer_size ; taille du tampon
;		WORD memory_adr	 ; adresse mémoire de base, de la zone sauvegardé
;		BYTE ligne	 ; numéro de la ligne courante dans la série de lignes
;	} (10 octets)
;
;	Object {
;		WORD x		 ; position sur x de l'objet (peut être une coordonnée graphique ou autre)
;		WORD y		 ; position sur y de l'objet (peut être une coordonnée graphique ou autre)
;		BYTE xincr	 ; incrémentation sur x, permet de définir une direction sur x
;		BYTE yincr	 ; incrémentation sur y, permet de définir une direction sur y
;		BYTE state	 ; liste des différents états du sprite, codés sous forme binaire
;				 ;   Bit    Description
;				 ;    0		Visibilité de l'objet { 1 = visible }
;				 ;    1		Type d'objet { 0 = fixe, 1 = animé }
;				 ;    2		Mode fantôme { 1 = mode fantôme activé } (pas de collisions)
;				 ;    3		-
;				 ;    4		-
;				 ;    5		-
;				 ;    6		-
;				 ;    7		-
;		WORD sprite	 ; référence à la structure contenant les données du sprite associé à l'objet
;		WORD memory_block; référence à la structure contenant les données de la zone graphique impactée par le sprite
;	} (11 octets)
;
;
;------------------------------------------------------------------------------------------




;######################################################################################
;				Fonctions graphiques
;######################################################################################




;********************************************************************
; Attente du signal VBL du tracé vertical
;
; En entrée
;	néant
; En sortie
;	néant
; Registres affectés
;	aucun
; Remarques
;

GRAPH_WAIT_RETRACE:

	PUSH AF		; Sauvegarde des registres
	PUSH BC		; 

	LD B, CST_PPI_CONTROLER_PORT	; Port dU PPI pour la VBL

_GRAPH_WAIT_RETRACE_0

	; Attente de la fin du retour (partie basse de l'écran)
;	IN A,(C) 
;	RRA		; VLB = bit 0 à 0
;	JR c, _GRAPH_WAIT_RETRACE_0

_GRAPH_WAIT_RETRACE_1

	; Attente du retour vertical (le retour de la VBL)
	IN A,(C) 
	RRA		; VLB = bit 0 à 1
	JR nc, _GRAPH_WAIT_RETRACE_1
	
GRAPH_WAIT_RETRACE_END

	POP BC		; Restauration de registres
	POP AF		;
	RET



;********************************************************************
; Permet de calculer le nombre d'octets que doit occuper un sprite
; entrelacé dans la mémoire graphique en fonction du mode graphique
;
; En entrée
;	D  <=> Largeur du sprite en pixels
;	E  <=> Hauteur du sprite en pixel
; En sortie
;	DE <=> Nombre d'octets nécessaires pour stocker un sprite en fonction du mode graphique
;	A  <=> Nombre d'octets nécessaire pour stocker un ligne du sprite en fonction du mode graphique
; Registres affectés
;	DE, A
; Remarques
;	- Cette méthode doit être utilisée lors de la création d'une structure
;	MemoryBlock pour savoir combien d'octets sont nécessaires pour sauvegarder la zone
;	impactée par un sprite.
;

GRAPH_SPRITE_SIZE_ON_SCREEN:

	PUSH AF		; Sauvegarde de F

	; Calcul du nombre d'octets nécessaire pour coder une ligne en fonction du mode graphique
	LD A, CST_GRAPH_VIDEO_MODE
	INC A

_GRAPH_SPRITE_SIZE_ON_SCREEN_1

	SRL D
	DEC A
	JP nz, _GRAPH_SPRITE_SIZE_ON_SCREEN_1
	INC D	; Ajustement permettant de prévoir un octet supplémentaire dans le cas
		; où le sprite sera à chevel sur deux octets consécutifs, en mémoire
		; Cas de coordonnées impaires, ex
		;	- sprite de largeur 2 pixels à la position x = 1 => les octets 0 et 1 sont impactés

	POP AF	; Restauration de F

	; Calcul du nombre d'octets nécessaire pour coder toutes les lignes
	;
	; En entrée :
	;	D  <=> Multiplicande (A)
	;	E  <=> Multiplicateur (B)
	; En sortie :
	;	DE   Produit de A par B
	LD A, D		; Largeur d'une linge en octet
	CALL MATH_MUL_8x8	

_GRAPH_SPRITE_SIZE_ON_SCREEN_END

	RET



;********************************************************************
; Permet d'activer le mode d'adressage direct de la mémoire vidéo
;
; En entrée
;	aucun
; En sortie
;	aucun
; Registres affectés
;	aucun
; Remarques
;	- Le mode d'adressage direct est conseillé pour le tracé direct à l'écran
;	

GRAPH_ACTIVE_DIRECT_MODE:

	PUSH BC
	PUSH HL

	LD HL, CALLBACK_GRAPH_ADR_OF_PIXEL
	LD BC, GRAPH_ADR_OF_PIXEL_WITH_DIRECT_MODE
	LD (HL), C
	INC HL
	LD (HL), B

_GRAPH_ACTIVE_DIRECT_MODE_END

	POP HL
	POP BC
	RET

;********************************************************************
; Prmet d'activer le mode d'adressage indirect de la mémoire vidéo
;
; En entrée
;	aucun
; En sortie
;	aucun
; Registres affectés
;	aucun
; Remarques
;	- Le mode d'adressage indirect est utilisé si vous voulez redéfinir le
;	  segment de base du pointeur vidéo DEF_GRAPH_VIDEO_ADR pour effectuer
;	  du tracé indirect à l'écran et passer par une page intérmédiaire
;	

GRAPH_ACTIVE_INDIRECT_MODE:

	PUSH HL
	PUSH HL

	LD HL, CALLBACK_GRAPH_ADR_OF_PIXEL
	LD BC, GRAPH_ADR_OF_PIXEL_WITH_INDIRECT_MODE
	LD (HL), C
	INC HL
	LD (HL), B

_GRAPH_ACTIVE_INDIRECT_MODE_END

	POP HL
	POP BC
	RET


;*****************************************************
; Appel la function de ccalcul de l'adresse vidéo 
; de base d'un point en utilisant le mode d'adressage 
; vidéo direct ou indirecte
; En entrée
;	BC <=> X1 sur 16 bits
;	A  <=> Y1 sur 8 bits
; En sortie
; 	HL <=> Adresse du premier point
; Registres affectés
;	HL
;

GRAPH_ADR_OF_PIXEL:

	LD HL, (CALLBACK_GRAPH_ADR_OF_PIXEL)
	JP (HL)

_GRAPH_ADR_OF_PIXEL_END


	
;*****************************************************
; Calcul de l'adresse vidéo de base d'un point en 
; utilisant le mode d'adresse par calcul. Cette méthode
; méthode permet d'écrire dans différentes zones mémoire
;
; En entrée
;	BC <=> X1 sur 16 bits
;	A  <=> Y1 sur 8 bits
; En sortie
; 	HL <=> Adresse du premier point
; Registres affectés
;	HL
; Informations
;	- Le nombre de pixel par octet est calculé en fonction du mode graphique.
;	- X1 est codé sur 16 bits car pour une utilisation avec le mode graphique 2
;	 (640x200) 8 bits  ne suffisent plus.
;	- Toutes les fonctions utilisées sont en annexe.
;	- Cette méthode effectue tous les calculs nécessaires pour trouver l'adresse
;	  de base d'un point, elle n'est pas conseillé pour le tracé direct à l'écran.
;	  Pour le tracé direct activez plutôt le mode d'adressage direct de la mémoire
;	  vidéo via la fonction GRAPH_ACTIVE_DIRECT_MODE
;
; Rappel du calcul de l'adresse de base d'une ligne
;
;	[Adresse de base de la ligne] = [Adresse vidéo]
;					+ [Adresse de la série]
;				 	+ [Offset de la ligne] * &800
;
;		- [Adresse de la série] = (Y1 \ 8) * &50
;		- [Offset de la ligne] = (Y1 MOD 8) * &800
;
;	[Adresse de base de la ligne] = &C000 + ((Y1 \ 8) * &50 + ((Y1 MOD 8) * &800)
;
; Rappel du calcul sur l'adresse d'un point
;
;	[Adresse du premier point] = [Adresse de base de la ligne] + [Offset du point]
;
;		- [Offset du point] = X1 \ [Nombre de pixels par octet]
;

GRAPH_ADR_OF_PIXEL_WITH_INDIRECT_MODE:

	PUSH AF		; Préservation de AF pour le retour
	PUSH BC		; Préservation de BC pour le retour
	PUSH DE		; Préservation de DE pour le retour


	LD HL, (DEF_GRAPH_VIDEO_ADR)	; Adresse de la mémoire graphique

	; Calcul de l'offset sur point en fonction du nombre de pixels par octet
	;	[Offset du point] = X1 \ [Nombre de pixels par octet]
	;
	LD D, B		; L'opération X1 \ [Nombre de pixels par octet]
	LD E, C		; DE va contenir BC (X1). A va contenir le décalage pour la division
	LD C, A		; Sauvegarde de Y1 dans C pour la division par 8
	LD A, CST_GRAPH_VIDEO_MODE + 1
			; Le décalage de n bits vers la droite en fonction du mode graphique,
			; équivaut à une division en fonction du nombre de pixel par octet
	CALL MATH_SRL_16	; Décalage de n bits vers la droite

	ADD HL, DE	; Ajout de l'offset du point, à l'adresse calculée


	; Calcul de l'adresse de base de la ligne
	; 	[Adresse de base de la ligne] = [Adresse vidéo]
	;					+ [Adresse de la série]
	;				 	+ [Offset de la ligne] * &800
	;
	LD A, C		; Restauration de Y1 dans A avant la division par 8
	SRL A		; Opération (Y1 \ 8)
	SRL A		;
	SRL A		;
	LD B, A		; Sauvegarde de A


	; Opération (Y1 \ 8) * &50
	;	(n * &50) <=> (n * &10) + (n * &40)
	;	(n *  80) <=> (n *  16) + (n *  64)
	;	(n *  80) <=> (n SLA 4) + (n SLA 6)
	;
	LD D, 0		; (n SLA 4)
	LD E, B		;
	SLA E		;  Le décalage de 4 bits vers la gauche de (Y1 \ 8) peut entraîner un débordement à patir du 4ème décalage
	SLA E		;  donc nous avons pas besoin de récupérer un éventuel débordement (Carry) dans D via 'RL D'
	SLA E		;
	SLA E : RL D	;
	ADD HL, DE	; Ajout de la première partie de l'adresse de la série de lignes, à l'adresse calculée

	LD D, 0 
	LD E, B		; (n SLA 6)
	SLA E		; Déclage de (Y1 \ 8) de 6 bits vers la gauche. Lorsque l'on effectue un décalage sur les 4 premiers bits,
	SLA E		; nous ne pouvons pas avoir de débordement. A partir du cinquième décalage des débordements peuvent
	SLA E		; apparaître, nous les prenons en compte dans D via 'RL D'
	SLA E : RL D	;
	SLA E : RL D	;
	SLA E : RL D	;
	ADD HL, DE	; Ajout de la seconde partie de l'adresse de la série de lignes, à l'adresse calculée

	; Opération (Y1 MOD 8)
	LD A, C		; Restauration de A (Y1)
	AND 7		; (Y1 MOD 8)


	; Opération (Y1 MOD 8) * &800
	;	Multiplier par &800 <=> à décaler de 11 bits vers la gauche la première opérante
	;
	LD D, 0		; (n SLA 11)
	LD E, A		;
	SLA E		; Déclage de (Y1 \ 8) de 11 bits vers la gauche. Lorsque l'on effectue un décalage sur les 3 premiers bits,
	SLA E		; nous ne pouvons pas avoir de débordement. A partir du 4ème décalage des débordements peuvent
	SLA E		; apparaître, nous les prenons en compte dans D via 'RL D'
	SLA E : RL D	;
	SLA E : RL D	;
	SLA E : RL D	;
	SLA E : RL D	;
	SLA E : RL D	;
	SLA E : RL D	;
	SLA E : RL D	;
	SLA E : RL D	;
	ADD HL, DE	; Ajout de l'offset de la ligne, à l'adresse calculée
	
_GRAPH_ADR_OF_PIXEL_WIDTH_INDIRECT_MODE_END

	POP DE
	POP BC
	POP AF
	RET



;*****************************************************
; Calcul de l'adresse vidéo de base d'un point en
; utilisant le mode d'adressage vidéo direct
; En entrée
;	BC <=> X1 sur 16 bits
;	A  <=> Y1 sur 8 bits
; En sortie
; 	HL <=> Adresse du premier point
; Registres affectés
;	HL
; Informations
;	- Le nombre de pixel par octet est calculé en fonction du mode graphique.
;	- X1 est codé sur 16 bits car pour une utilisation avec le mode graphique 2
;	 (640x200) 8 bits  ne suffisent plus.
;	- La fonction utilise on table d'adresses pour calculer les adresses de base de chaque ligne
;	  Cette table permet d'optimiser le temps de calcul, conseillé pour un affichage direct des
;	  données.
;

GRAPH_ADR_OF_PIXEL_WITH_DIRECT_MODE:

	PUSH AF		; Préservation des registres pour le retour
	PUSH BC		;
	PUSH DE		;

			; Transfert de l'adresse de la table des adresses des lignes dans HL 
	LD HL, ADDRESS_OF_LINES
	LD D, 0		; A partir de l'adresse de base de la table des addresses des lignes, on calcule
	LD E, A		; le décalage par rapport au numéro de la ligne courante sachant que l'adresse
	ADD HL, DE	; de base de chaque ligne nécessite 2 octets
	ADD HL, DE	;
	LD E, (HL)	; Récupération de l'adresse de base de la ligne courante dans DE
	INC HL		;
	LD D, (HL)	;
	EX HL, DE	; Transfert de l'adresse de base de la ligne courante dans HL

	LD D, B		; Transfert de X1 dans D et A pour effectuer un décalage en fonction du nombre de pixels par octet
	LD A, C		;
	LD B, CST_GRAPH_VIDEO_MODE
	INC B

_GRAPH_ADR_OF_PIXEL_WITH_DIRECT_MODE_1

	SRL D		; L'adresse de base de chaque ligne correspond à la position X = 0 à l'écran
	RRA		; on va donc calculer le décalage de l'adresse par rapport la la position X du point
			; courant. Le décalage en fonction de X dépend du nombre de pixels par octet, nous
			; divisons donc X par le nombre de pixels par octet.
	DJNZ _GRAPH_ADR_OF_PIXEL_WITH_DIRECT_MODE_1
	LD E, A		; Ajout du décalage à l'adresse de base de la ligne courant
	ADD HL, DE	; 

_GRAPH_ADR_OF_PIXEL_WITH_DIRECT_MODE_END

	POP DE		; Restauration des registres
	POP BC
	POP AF
	RET




;-------------------------------------------------------------------------------------
; Permet de valider la position d'un sprite sur la partie visible de l'écran
; Calcul par la même occasion les déclages (dx) et (dy) permettant d'afficher
; un sprite
;
; En entrée
;	BC <=> Position sur x
;	DE <=> Position sur y
;	IX <=> Adresse d'une structure Sprite
;
; En sortie
;	A  <=> Si le sprite est visible à l'écran, A contient 1 sinon 0
; Registres affectés
;	AF, BC, DE
; Remarques
;	- Cette est utilisée par les méthodes d'affichages des sprites et peut être utilisée
;	  de manière indépendante
;	- x et y respectivement BC et DE peuvent être négatifs.
;	- BC et DE peuvent être ajustés dans le cas où une partie du sprite est invisible à l'écran
;
;		si (dx1) <> 0, BC = 0
;	    ou
;		si (dy1) <> 0, DE = 0
;
;		   _______
;	partie	  |sprite |dy1
;	invisible |    ___|_____________
;		  |   |	  |             |
;		  |___|___|             |----
;		   dx1|	   partie       | dx2
;		      |	   visible  	|
;		      |    de l'écran	|
;		      |_________________|
;		          |
;			  |dy2
;
;	  (dx1), (dx2), (dy1) et (dY2) contiennent respectivement le nombre de pixels non visibles à l'écran
;
;	- Liste des tests pour les calculs des dx et dy
;		1 - Si y < 0
;		2 - Si (y + [Hauteur du sprite]) < 0 => on sort
;		3 - Si y > [Hauteur de l'écran] => on sort
;		4 - Si (y + [Hauteur du sprite]) > [Hauteur de l'écran]
;		5 - Si x < 0
;		6 - Si (x + [Largeur sprite]) < 0 => on sort
;		7 - Si x > [Largeur de l'écran] => on sort
;		8 - Si (x + [Largeur sprite]) > [Largeur de l'écran]
;

GRAPH_SPRITE_TEST_POSITION

	XOR A		; On efface A pour le retour
	LD (GRAPH_POSITION_DX1), A
	LD (GRAPH_POSITION_DX2), A
	LD (GRAPH_POSITION_DY1), A
	LD (GRAPH_POSITION_DY2), A


	; Test 1
	; Si y < 0
	BIT 7, D	; Vérificaion que y(DE) est négatif, le bit 7 de D = 1
	JP z, _GRAPH_SPRITE_TEST_POSITION_Test3

	; Test 2
	; Si [(y + [Hauteur du sprite]) <= 0] => on sort
	LD H, 0 
	LD L, (IX + 1)	; (IX + 1) Hauteur du sprite
	ADC HL, DE
	JP m, _GRAPH_SPRITE_TEST_POSITION_END
	JP z, _GRAPH_SPRITE_TEST_POSITION_END

	; Calucl de dy1
	LD A , E	; Transfert de E dans A pour prendre la partie positive de y
			; La valeur de y est contenue dans un seul octet car (y + [Hauteur du sprite]) >= 0
	NEG		; récupération de la valeur positive du reste
			; Stockage de dy1
	LD (GRAPH_POSITION_DY1), A
	LD DE, 0	; Y = 0
	OR A		; On efface Carry pour les tests suivants
	JP _GRAPH_SPRITE_TEST_POSITION_Test5

_GRAPH_SPRITE_TEST_POSITION_Test3

	; Test 3
	; Si y > [Hauteur de l'écran] => on sort
	LD HL, CST_GRAPH_SCREEN_HEIGTH - 1
	SBC HL, DE	; [Hauteur de l'écran] - y
	JP m, _GRAPH_SPRITE_TEST_POSITION_END

	; Test 4
	; Si (y + [Hauteur du sprite]) > [Hauteur de l'écran]
	PUSH DE
	LD D, 0
	LD E, (IX + 1)  ; (IX + 1) Hauteur du sprite
	INC HL		;
	SBC HL, DE	; Soustraction de la hauteur du sprite
	POP DE
	JP p, _GRAPH_SPRITE_TEST_POSITION_Test5

	; Calcul de dy2
	LD A, L		; Récupération du reste de la soustraction
	NEG		; Récupération de la valeur positive de A pour définir dy2
			;
	LD (GRAPH_POSITION_DY2), A 
	OR A		; On efface Carry pour les test suivants

_GRAPH_SPRITE_TEST_POSITION_Test5

	; Test 5
	; Si x < 0
	BIT 7, B	; Vérification que x(BC) est négatif, le bit 7 de B = 1
	JP z, _GRAPH_SPRITE_TEST_POSITION_Test7

	; Test 6
	; Si (x + [Largeur sprite]) < 0 => on sort
	LD H, 0
	LD L, (IX)	; (IX + 0) Largeur du sprite en pixel
	ADC HL, BC
	JP m, _GRAPH_SPRITE_TEST_POSITION_END
	JP z, _GRAPH_SPRITE_TEST_POSITION_END

	; Calcul de dx1
	LD A, C		; Transfert de C dans A pour récupérter la partie positive de x.
			; La valeur de x est contenue dans un seul octet car ([la largeur du sprite] + x) >= 0
	NEG		; Récupération de la valeur positive du reste
			; Stockage de dx1
	LD (GRAPH_POSITION_DX1), A
	LD BC, 0	; X = 0
	JP _GRAPH_SPRITE_TEST_POSITION_Ok

_GRAPH_SPRITE_TEST_POSITION_Test7

	; Test 7
	; Si x > [Largeur écran] => on sort
	LD HL, CST_GRAPH_SCREEN_WIDTH - 1
	SBC HL, BC	; [Largeur de l'écran] - x
	JP M, _GRAPH_SPRITE_TEST_POSITION_END

	; Test 8
	; Si (x + [Largeur sprite]) > [Largeur de l'écran]
	PUSH BC
	LD B, 0
	LD C, (IX)	; (IX + 0) Largeur du sprite en pixel
	INC HL
	SBC HL, BC	; Soustraction de la largeur du sprite
	POP BC
	JP P, _GRAPH_SPRITE_TEST_POSITION_Ok

	; Calcul de dx2
	LD A, L		; Transfert du reste négatif de HL dans A pour récupéré le reste positif
	NEG		; Récupération du reste positif pour définir dx2
			;
	LD (GRAPH_POSITION_DX2), A

_GRAPH_SPRITE_TEST_POSITION_Ok

	LD A, 1		; Retour Ok

_GRAPH_SPRITE_TEST_POSITION_END

	RET




;********************************************************************
; Permet d'afficher un sprite à l'écran
;
; En entrée
;	BC <=> Position sur x
;	DE <=> Position sur y
;	IX <=> Adresse d'une structure Sprite
; En sortie
;	aucun
; Registres affectés
;	aucun
; Remarques
;	- Les zones d'affichage horizontale et verticale peuvent être comprises entre -32767 à +32768
;	  La zone d'affichage de l'écran va de (0,0) à (CST_GRAPH_SCREEN_WIDTH - 1,CST_GRAPH_SCREEN_HEIGHT - 1)
;	- x et y respectivement BC et DE peuvent être négatifs.
;	- Positions et nommages des décalages en fonction des parties visibles du sprite à l'écran
;	
;		   _______
;	partie	  |sprite |dy1
;	invisible |    ___|_____________
;		  |   |	  |             |
;		  |___|___|             |----
;		   dx1|	   partie       | dx2
;		      |	   visible  	|
;		      |    de l'écran	|
;		      |_________________|
;		          |
;			  |dy2
;
;	Les valeurs de (dx1),(dx2),(dy1) et (dy2) sont stockées respectivement dans
;	GRAPH_POSITION_DX1, GRAPH_POSITION_DX2, GRAPH_POSITION_DY1, GRAPH_POSITION_DY2
;
;	Sprite {
;		BYTE width	 ; largeur du sprite en pixel
;		BYTE height	 ; hauteur du sprite en pixel
;		WORD sprite_size ; taille du tampon
;		WORD sprite	 ; adresse du tampon contenant les données du sprite
;		WORD mask	 ; adresse du tampon du masque logique qui doit avoir la même taille que le sprite
;		BYTE static_datas; indique si les données du sprite sont issues de données statiques
;	} (9 octets)
;


;-----------------------------------------------------
; Affichage d'un sprite quelque soit le mode graphique
;
GRAPH_SPRITE_SHOW_SPRITE:

	PUSH AF		; Sauvegarde de AF pour le retour

	; Vérification du mode graphique en cours
	LD A, CST_GRAPH_VIDEO_MODE
	OR A
	JP nz, _GRAPH_SPRITE_SHOW_SPRITE_4

	; Affichage du sprite en mode 2, 16 couleurs
	CALL GRAPH_SPRITE_SHOW_SPRITE_16
	POP AF		; Restauration de AF
	RET

_GRAPH_SPRITE_SHOW_SPRITE_4

	CP 1
	JP nz, _GRAPH_SPRITE_SHOW_SPRITE_2

	; Affichage du sprite en mode 1, 4 couleurs
	CALL GRAPH_SPRITE_SHOW_SPRITE_4
	POP AF		; Restauration de AF
	RET

_GRAPH_SPRITE_SHOW_SPRITE_2

	CP 2
	JP nz, _GRAPH_SPRITE_SHOW_SPRITE_END

	; Affichage du sprite en mode 2, 2 couleurs
	CALL GRAPH_SPRITE_SHOW_SPRITE_2

_GRAPH_SPRITE_SHOW_SPRITE_END

	POP AF		; Restauration de AF
	RET



;-------------------------------------------------
; Affichage d'un sprite en mode 16 couleurs
;
GRAPH_SPRITE_SHOW_SPRITE_16:

	PUSH AF		; Sauvegarde des registres
	PUSH BC
	PUSH DE
	PUSH HL
	PUSH IX
	PUSH IY


	;----------------------------------------------------------------
	; - 1 -
	; Vérification de la position du sprite à l'écran
	;
	; En entrée
	;	BC <=> Position sur x
	;	DE <=> Position sur y
	;	IX <=> Adresse d'une structure Sprite
	;
	; En sortie
	;	A  <=> Si le sprite est visible à l'écran, A contient 1 sinon 0
	CALL GRAPH_SPRITE_TEST_POSITION
	OR A	; Vérification si A = 1, si oui le sprite est visible à l'écran
		; sinon on sort
	JP z, _GRAPH_SPRITE_SHOW_SPRITE_16_END


_GRAPH_SPRITE_SHOW_SPRITE_16_Initialisation


	;----------------------------------------------------------------
	; - 2 -
	; Calcul du n° de la ligne courante dans la série de lignes
	;
	EX AF, AF'	; Travail sur AF'
	PUSH AF		; Sauvegarde de AF' pour le retour
	LD A, E		; Y dans A'
	AND 7		; Préservation des 3 premiers bits pour connaître le n° de la ligne courante
	NEG		; Valeur négative de A
	ADD 8		; Ajout de 8 pour obtenir le nombre de lignes restant à traiter dans la série
	EX AF, AF'	; Sauvegarde AF'


	;----------------------------------------------------------------
	; - 3 -
	; Calcul de l'adresse de base du premier pixel à afficher
	;
	; En entrée
	;	BC <=> X1 sur 16 bits
	;	A  <=> Y1 sur 8 bits
	; En sortie
	; 	HL <=> Adresse du premier point
	;
	LD A, E		; Y dans A
	CALL GRAPH_ADR_OF_PIXEL
	PUSH HL		; Sauvegarde de l'adresse du premier point
	

	;----------------------------------------------------------------
	; - 4 -
	; Calcul du nombre de décalage binaire à effectuer pour afficher
	; le premier point du sprite
	;
	LD A, C		; Transfert de la partie basse de BC (x) pour calculer la position du premier point
	LD L, A		; Sauvegarde de la partie basse de x dans L pour pouvoir calculer le nombre d'octets de données du sprite à ne pas traiter
	LD B, CST_GRAPH_PIXELS_PER_BYTE - 1
	AND B
	LD C, A		; A dans C pour calculer le nombre de décalages binaire pour afficher le premier point
	LD A, B		; 
	SUB A, C	; A contient le nombre de décalages


	;----------------------------------------------------------------
	; - 5 -
	; Calcul du masque de préservation par défaut et du nombre de
	; déclages restants
	;
	; Décalage vers la droite d'un entier de 8 bits
	; carry est ré-injecté vers la gauche
	;
	; En entrée
	;	E  <=> Entier de 8 bits
	;	A  <=> Nombre de bits à décaler
	; En sortie
	;	E <=> Résultat du décalage des n bits
	; Registres affectés
	;	F, E
	;
	LD E, %10101010		; Masque par défaut
	OR A
	JP z, _GRAPH_SPRITE_SHOW_SPRITE_16_DecalageMasquePreservation

	RLC E	; Déclage du masque de préservation d'une position vers la gauche
		; le manière à préserver les données du pixel voisin

_GRAPH_SPRITE_SHOW_SPRITE_16_DecalageMasquePreservation

	LD (____GRAPH_SPRITE_SHOW_SPRITE_16_PreAffectation_Decalages + 1), A
	LD A, E			; Transfert du masque dans A pour stockage
	LD (____GRAPH_SPRITE_SHOW_SPRITE_16_PreAffectation_MasquePreservation + 1), A


	;----------------------------------------------------------------
	; - 6 -
	; Calcul du nombre de pixels à afficher et du nombre de lignes
	;
	; Nombre de lignes à afficher
	LD A, (GRAPH_POSITION_DY1)	; dy1 dans C. Lignes non affichées
	LD C, A		; 
	LD A, (GRAPH_POSITION_DY2)	; dy2 dans B. Lignes non affichées
	LD B, A		; 
	LD A, (IX + 1)	; (IX + 1) Hauteur du sprite en pixel
	LD E, C		; E contient le nombre de lignes à passer avant l'affichage du sprite
	SUB B		; On retire dy1 et dy2 de la hauteur du sprite pour connaître le nombre de lignes à afficher
	SUB C		;
	LD (____GRAPH_SPRITE_SHOW_SPRITE_16_PreAffectation_nbLignes + 1), A
	
	; Nombre de pixels à afficher
	LD A, (GRAPH_POSITION_DX1)	; dx1 dans B. Pixels non affichés
	LD B, A		; 
	LD A, (GRAPH_POSITION_DX2)	; dx2 dans C. Pixels non affichés
	LD C, A		; 
	LD A, (IX + 0)	; (IX + 0) Largeur du sprite en pixel
	LD D, A		; Largeur du sprite dans D
	SUB B		; On retire dx1 et dx2 pour connaître le nombre de pixels à afficher
	SUB C		;
	LD (____GRAPH_SPRITE_SHOW_SPRITE_16_PreAffectation_nbPixels + 1), A


	;----------------------------------------------------------------
	; - 7 -
	; Calcul du déclage utilisé pour recalculer les adresses des données du sprite
	; et du masque logique, lors du passage à la ligne de données suivante
	LD A, B		; Transfert de (dx1) dans A
	ADD C		; Ajout de (dx2) à A
			; Le total de (dx1) + (dx2) ne peut pas dépasser un octet car la largeur d'un sprite ne dépasse pas un octet	
	LD (____GRAPH_SPRITE_SHOW_SPRITE_16_PreAffectation_OffsetSprite + 1), A


	;----------------------------------------------------------------
	; - 8 -
	; Calcul du déclage utilisé pour recaluler l'adresse de la ligne
	; suivante, lors du passage d'une ligne à l'autre
	; 
	; - Pour calculer l'Offset qui permet d'ajuster l'adresse graphique contenue dans HL,
	;   il faut prendre en compte la largeur du sprite, le fait que les 2 premiers pixels du sprite soient affichés à cheval
	;   sur 2 octets consécutifs et les éventuelles parties cachées du sprite via (dx1) et (dx2)
	; - Ce décalage correspond au nombre total d'octets qui ne sont pas traités, dans notre cas ce décalage va se calculer
	;   de cette façon
	;	1 - Vérification que le sprite est affiché à une position impaire, ce qui provoque un chevauchement des 2 premiers
	;	    pixels du sprite sur 2 octets graphiques consécutifs. Application d'un ET logique sur la valeur de x.
	;	    Dans notre cas x avait été sauvé dans L.
	;	2 - Prise en compte de la largeur du sprite se trouvant dans D
	;	3 - Prise en compte des éventuelles débordements, (dx1) et (dx2), engendrés par le fait que le sprite déborde de l'écran
	;	4 - Division du nombre total de pixels par 2 car le mode graphique 16 couleurs iomplique 2 pixels par octet
	; 
	LD A, L		; Transfert de la partie basse de x dans A
	AND 1		; 1 - Vérification que les 2 premiers pixels du sprite sont à cheval sur 2 octets graphiques consécutifs
			;     Application d'un ET logique sur la valeur de x pour prendre en compte le décalage des 2 premiers pixels .
			;     Dans notre cas x avait été sauvé dans L.
	ADD A, D	; 2 - Prise en compte de la largeur du sprite en pixel
	SUB B		; 3 - Prise en compte des éventuelles débordements (dx1) et (dx2)
	SUB C		;     B = (dx1), C = (dx2)
	SRL A		; 4 - Division du total par 2 car on a deux pixels par octet en mode 0
			;
			; Au final, le décalage total = ([x(L) AND 1] + [Largeur du sprite (D)] - [(dx1) + (dx2)]) / 2
			;
	LD C, A		; Nombre de bytes non traités (déclage) dans C
	LD A, B		; Sauvegarde de (dx1) dans A
	LD B, 0		; Initialisation de B à 0 car le nombre de bytes non traités est codé sur un octet
	OR A		; On éfface Carry qui est éventuellement posé suite au décalage de bit précédent (SRL)
	LD HL, &800	; Largeur d'une ligne graphique
	SBC HL, BC	; On retire le décalage en octet pour le calcul de l'offset final
	LD C, A		; Sauvegarde de (dx1) dans C pour les calculs suivant
	LD A, H		; Pré-affectation de l'offset
	LD (____GRAPH_SPRITE_SHOW_SPRITE_16_PreAffectation_OffsetLigne + 2), A
	LD A, L		;
	LD (____GRAPH_SPRITE_SHOW_SPRITE_16_PreAffectation_OffsetLigne + 1), A



	;-------------------------------------------------------------------------------------
	; - 9 -
	; Calcul de l'adresse de départ des données du sprite en fonctions des décalages
	;
	; D et E contiennent déjà la largeur du sprite en pixel ainsi que le nombre de ligne à
	; ne pas afficher.
	;
	; Multiplication du nombre de pixel par ligne par le nombre de lignes
	;
	; En entrée :
	;	D  <=> Multiplicande (A)
	;	E  <=> Multiplicateur (B)
	; En sortie :
	;	DE   Produit de A par B
	;
	; E contient déjà le nombre de lignes à passer
	; D contient la largeur du prise en pixel
	;
	CALL MATH_MUL_8x8

	; Adresse du sprite dans HL
	LD H, (IX + 5)
	LD L, (IX + 4)
	ADD HL, DE	; Ajout du décalage à l'adresse des données du sprite pour les lignes qui ne sont pas affichées
	ADD HL, BC	; BC contient (dx1), ajout du nombre de pixels qui ne sont pas affichées pour la ligne première ligne à afficher
	PUSH HL		; Transfert de l'adresse des données du sprite dans IY
	POP IY		;

	; Adresse du masque dans HL
	LD H, (IX + 7)
	LD L, (IX + 6)
	ADD HL, DE	; Ajout du décalage à l'adresse des données du sprite
	ADD HL, BC	; Ajout du nombre de pixels à passer avant d'afficher le sprite
	PUSH HL		; Transfert de l'adresse des données du sprite dans IY
	POP IX		;

	POP HL		; Restauration de l'adresse du premier point à afficher


	; - 10 -
	; Initialisation du nombre de lignes à traiter
	____GRAPH_SPRITE_SHOW_SPRITE_16_PreAffectation_nbLignes
	LD B, 0		; Pré-affectation (nbLignes)


_GRAPH_SPRITE_SHOW_SPRITE_16_BoucleSurLesLignes

	; - 11 -
	; Intialisation du nombre de points à traiter par ligne
	____GRAPH_SPRITE_SHOW_SPRITE_16_PreAffectation_nbPixels
	LD C, 0		;Pré-affectation (nbPixels)

	; - 12 -
	; Nombre de décalage par défaut
	____GRAPH_SPRITE_SHOW_SPRITE_16_Preaffectation_Decalages
	LD D, 0		; Pré-affectation (Decalages)

	; - 13 -
	; Masque de préservation par défaut
	____GRAPH_SPRITE_SHOW_SPRITE_16_PreAffectation_MasquePreservation
	LD E, 0		; Pré-affectation (Masque)

	
_GRAPH_SPRITE_SHOW_SPRITE_16_BoucleSurLesPixels

	; - 14 -
	; Vérification que tous les pixels de la ligne courante ont été traités
	;
	LD A, C	; Transfert du nombre de pixels restant à traiter dans A
	OR A	; Si tous les point ont été traités, on calcul l'adresse graphique suivante en ajoutant l'offset
	JP z, _GRAPH_SPRITE_SHOW_SPRITE_16_TestNombreDeLignes

	PUSH BC		; Sauvegarde des compteurs B et C (nombre de lignes et nombre de pixels par ligne)

	; - 15 -
	; Récupération des données du masque et du sprite
	;
	LD B, (IY)	; Récupération du point à afficher et décalage des bits en fonction de la position logique à l'écran
	LD C, (IX)	; Récupération du masque logique associé au sprite et décalage des bits en fonction de la position logique à l'écran

	; - 16 -
	; Déclage des données du masque et des données du sprite si un décalage doit être effectué
	LD A, D		; Nombre de décalages dans A
	OR A	
	JP z, _GRAPH_SPRITE_SHOW_SPRITE_16_DeclageMasqueEtSprite

	SLA B		; Décalage des données du sprite en fonction du nombre de décalages courant
	SLA C		; Décalage du masque en fonction du nombre de décalages courant

_GRAPH_SPRITE_SHOW_SPRITE_16_DeclageMasqueEtSprite

	; - 17 -
	; Calcul du masque logique de préservation des données
	LD A, C		; Masque logique associé au sprite
	OR E		; Association avec le masque de préservation des données du point voisin au point courant
	LD C, A		; Sauvegarde du masque dans C

	; - 18 -
	; Affichage du nouveau point
	LD A, (HL)	; Récupération de l'octet graphique courant
	AND C		; Préservation des données à partir du masque précédement calculé
	OR B		; Ajout des données du nouveau point
	LD (HL), A	; Affichage du nouveau point à l'écran

	; - 19 -
	; Restauration et ajustement des compteurs
	;
	POP BC		; Restauration de compteurs
	DEC C		; Décrémentation du nombre de points à traiter

	; - 20 -
	; Traitement du point suivant
	INC IX		; Incrémentation de l'adresse du masque logique
	INC IY		; Incrémentation de l'adresse du sprite

	; - 21 -
	; Décalage du masque de préservation pour traiter les données du point suivant
	RRC E		; Décalage du masque de préservation des données du point voisin
			; de manière à traiter le point suivant

	; - 22 -
	; L'octet graphique courant a t-il complètement été traité ? (Nombre de décalage = 0)
	LD A, D
	OR A
	JP z, _GRAPH_SPRITE_SHOW_SPRITE_16_OctetSuivant

	; - 23 -
	; Ajustement de nombre de déclages restant à effectuer dur l'octet courant
	DEC D	; Décrémentation du nombre de décalages à affectuer pour traiter les pixels restant
	JP _GRAPH_SPRITE_SHOW_SPRITE_16_BoucleSurLesPixels

_GRAPH_SPRITE_SHOW_SPRITE_16_OctetSuivant

	; - 24 -
	; Octet suivant
	INC HL	; Octet graphique suivant
	LD D, CST_GRAPH_PIXELS_PER_BYTE	- 1
		; D va contenir le nombre de décalages à effectuer pour traiter
		; les données du point suivant.

	JP _GRAPH_SPRITE_SHOW_SPRITE_16_BoucleSurLesPixels

_GRAPH_SPRITE_SHOW_SPRITE_16_TestNombreDeLignes

	; - 25 -
	; Toutes les lignes ont elles été toutes traitées
	DJNZ _GRAPH_SPRITE_SHOW_SPRITE_16_LigneSuivante
	JP _GRAPH_SPRITE_SHOW_SPRITE_16_FinBoucleSurLesLignes

_GRAPH_SPRITE_SHOW_SPRITE_16_LigneSuivante

	; - 26 -
	; Calcul des nouvelles adresses des données du sprite et du masque logique en fonction des décalages (dx1 et dx2)
	____GRAPH_SPRITE_SHOW_SPRITE_16_PreAffectation_OffsetSprite
	LD DE, 0	; Pré-affectation (offset_sprite)
	ADD IY, DE	; Décalage de l'adresse des données du sprite et du masque
	ADD IX, DE	;

	; - 27 -
	; Vérification que la série de ligne a complètement été traitée
	EX AF, AF'
	DEC A
	OR A
	JP nz, _GRAPH_SPRITE_SHOW_SPRITE_16_NouvelleLigne

	OR 8		; Nouvelle série de 8 lignes
	LD DE, &3FB0	; &3FB0 = &4000 - &50 = Espace d'adressage d'une série complète de lignes - Offset pour la série de lignes suivantes
	SBC HL, DE	;       => HL = HL - &4000 + &50

_GRAPH_SPRITE_SHOW_SPRITE_16_NouvelleLigne

	; - 28 -
	; Calcul de l'adresse vidéo de la nouvelle ligne en fonction des déclages dx1 et dx2
	____GRAPH_SPRITE_SHOW_SPRITE_16_PreAffectation_OffsetLigne
	LD DE, 0	; Pré-affectation (offset_ligne) 
	ADD HL, DE	; Passage à la ligne suivante

	EX AF, AF'	; Sauvegarde de AF'
	JP _GRAPH_SPRITE_SHOW_SPRITE_16_BoucleSurLesLignes

_GRAPH_SPRITE_SHOW_SPRITE_16_FinBoucleSurLesLignes

	EX AF, AF'	; Restauration de AF'
	POP AF		; 
	EX AF, AF'	; 

_GRAPH_SPRITE_SHOW_SPRITE_16_END

	POP IY		; Restauration des registres
	POP IX
	POP HL
	POP DE
	POP BC
	POP AF
	RET



;-------------------------------------------------
; Affichage d'un sprite en mode 4 couleurs
;
GRAPH_SPRITE_SHOW_SPRITE_4:

	PUSH AF		; Sauvegarde des registres
	PUSH BC
	PUSH DE
	PUSH HL
	PUSH IX
	PUSH IY


	;----------------------------------------------------------------
	; - 1 -
	; Vérification de la position du sprite à l'écran
	;
	; En entrée
	;	BC <=> Position sur x
	;	DE <=> Position sur y
	;	IX <=> Adresse d'une structure Sprite
	;
	; En sortie
	;	A  <=> Si le sprite est visible à l'écran, A contient 1 sinon 0
	CALL GRAPH_SPRITE_TEST_POSITION
	OR A	; Vérification si A = 1, si oui le sprite est visible à l'écran
		; sinon on sort
	JP z, _GRAPH_SPRITE_SHOW_SPRITE_4_END

_GRAPH_SPRITE_SHOW_SPRITE_4_Initialisation


	;----------------------------------------------------------------
	; - 2 -
	; Calcul du n° de la ligne courante dans la série de lignes
	;
	EX AF, AF'	; Travail sur AF'
	PUSH AF		; Sauvegarde de AF' pour le retour
	LD A, E		; Y dans A'
	AND 7		; Préservation des 3 premiers bits pour connaître le n° de la ligne courante
	NEG		; Valeur négative de A
	ADD 8		; Ajout de 8 pour obtenir le nombre de lignes restant à traiter dans la série
	EX AF, AF'	; Sauvegarde AF'


	;----------------------------------------------------------------
	; - 3 -
	; Calcul de l'adresse de base du premier pixel à afficher
	;
	; En entrée
	;	BC <=> X1 sur 16 bits
	;	A  <=> Y1 sur 8 bits
	; En sortie
	; 	HL <=> Adresse du premier point
	;
	LD A, E		; Y dans A
	CALL GRAPH_ADR_OF_PIXEL
	PUSH HL		; Sauvegarde de l'adresse du premier point
	

	;----------------------------------------------------------------
	; - 4 -
	; Calcul du nombre de décalage binaire à effectuer pour afficher
	; le premier point du sprite
	;
	LD A, C		; Transfert de la partie basse de BC (x) pour calculer la position du premier point
	LD L, A		; Sauvegarde de la partie basse de x dans L pour pouvoir calculer le nombre d'octets de données du sprite à ne pas traiter
	LD B, CST_GRAPH_PIXELS_PER_BYTE - 1
	AND B
	LD C, A		; A dans C pour calculer le nombre de décalages binaire pour afficher le premier point
	LD A, B		; 
	SUB A, C	; A contient le nombre de décalages
	

	;----------------------------------------------------------------
	; - 5 -
	; Calcul du masque de préservation par défaut
	;
	; Décalage vers la droite d'un entier de 8 bits
	; carry est ré-injecté vers la gauche
	;
	; En entrée
	;	E  <=> Entier de 8 bits
	;	A  <=> Nombre de bits à décaler
	; En sortie
	;	E <=> Résultat du décalage des n bits
	; Registres affectés
	;	F, E
	;
 	LD E, %11101110		; Masque par défaut
	CALL MATH_RLC_8

	LD (____GRAPH_SPRITE_SHOW_SPRITE_4_PreAffectation_Decalages + 1), A
	LD A, E			; Transfert du masque dans A pour stockage
	LD (____GRAPH_SPRITE_SHOW_SPRITE_4_PreAffectation_MasquePreservation + 1), A


	;----------------------------------------------------------------
	; - 6 -
	; Calcul du nombre de pixels à afficher et du nombre de lignes
	;
	; Nombre de lignes à afficher
	LD A, (GRAPH_POSITION_DY1)	; dy1 dans C. Lignes non affichées
	LD C, A		; 
	LD A, (GRAPH_POSITION_DY2)	; dy2 dans B. Lignes non affichées
	LD B, A		; 
	LD A, (IX + 1)	; (IX + 1) Hauteur du sprite en pixel
	LD E, C		; E contient le nombre de lignes à passer avant l'affichage du sprite
	SUB B		; On retire dy1 et dy2 de la hauteur du sprite pour connaître le nombre de lignes à afficher
	SUB C		;
	LD (____GRAPH_SPRITE_SHOW_SPRITE_4_PreAffectation_nbLignes + 1), A
	
	; Nombre de pixels à afficher
	LD A, (GRAPH_POSITION_DX1)	; dx1 dans B. Pixels non affichés
	LD B, A		; 
	LD A, (GRAPH_POSITION_DX2)	; dx2 dans C. Pixels non affichés
	LD C, A		; 
	LD A, (IX + 0)	; (IX + 0) Largeur du sprite en pixel
	LD D, A		; Largeur du sprite dans D
	SUB B		; On retire dx1 et dx2 pour connaître le nombre de pixels à afficher
	SUB C		;
	LD (____GRAPH_SPRITE_SHOW_SPRITE_4_PreAffectation_nbPixels + 1), A


	;----------------------------------------------------------------
	; - 7 -
	; Calcul du déclage utilisé pour recalculer les adresses des données du sprite
	; et du masque logique, lors du passage à la ligne de données suivante
	LD A, B		; Transfert de (dx1) dans A
	ADD C		; Ajout de (dx2) à A
			; Le total de (dx1) + (dx2) ne peut pas dépasser un octet car la largeur d'un sprite ne dépasse pas un octet	
	LD (____GRAPH_SPRITE_SHOW_SPRITE_4_PreAffectation_OffsetSprite + 1), A


	;----------------------------------------------------------------
	; - 8 -
	; Calcul du déclage utilisé pour recaluler l'adresse de la ligne
	; suivante, lors du passage d'une ligne à l'autre
	;
	; - Pour calculer l'Offset qui permet d'ajuster l'adresse graphique contenue dans HL,
	;   il faut prendre en compte la largeur du sprite, le fait que les 4 premiers pixels soient affichés à cheval
	;   sur 2 octets consécutifs et les éventuelles parties cachées du sprite via (dx1) et (dx2)
	; - Ce décalage correspond au nombre total d'octets qui ne sont pas traités, dans notre cas ce décalage va se calculer
	;   de cette façon
	;	1 - Vérification que les 4 premiers pixels du sprite sont à cheval sur 2 octets graphiques consécutifs
	;	    Application d'un ET logique sur la valeur de x. Dans notre cas x avait été sauvé dans L.
	;	2 - Prise en compte de la largeur du sprite se trouvant dans D
	;	3 - Prise en compte des éventuelles débordements, (dx1) et (dx2), engendrés par le fait que le sprite déborde de l'écran
	;	4 - Division du nombre total de pixels par 2 car le mode graphique 16 couleurs iomplique 2 pixels par octet
	; 
	LD A, L		; Transfert de la partie basse de x dans A
	AND 3		; 1 - Vérification que le sprite va être affiché à cheval sur 2 octets
			;     Application d'un ET logique sur la valeur de x pour prendre en compte le décalage des 4 premiers pixels .
			;     Dans notre cas x avait été sauvé dans L.
	ADD A, D	; 2 - Prise en compte de la largeur du sprite en pixel
	SUB B		; 3 - Prise en compte des éventuelles débordements (dx1) et (dx2)
	SUB C		;     B = (dx1), C = (dx2)
	SRL A		; 4 - Division par 4 car on a 4 pixels par octet en mode 1
	SRL A		;
			; Au final, le décalage total = ([x(L) AND 3] + [Largeur du sprite (D)] - [(dx1) + (dx2)]) / 4
	LD C, A		; Nombre de bytes non traités (déclage) dans C
	LD A, B		; Sauvegarde de (dx1) dans A
	LD B, 0		; Initialisation de B à 0 car le nombre de bytes non traités est codé sur un octet
	OR A		; On éfface Carry qui est éventuellement posé suite au décalage de bit précédent (SRL)
	LD HL, &800	; Largeur d'une ligne graphique
	SBC HL, BC	; On retire le décalage en octet pour le calcul de l'offset final
	LD C, A		; Sauvegarde de (dx1) dans C pour les calculs suivant
	LD A, H		; Pré-affectation de l'offset
	LD (____GRAPH_SPRITE_SHOW_SPRITE_4_PreAffectation_OffsetLigne + 2), A
	LD A, L		;
	LD (____GRAPH_SPRITE_SHOW_SPRITE_4_PreAffectation_OffsetLigne + 1), A



	;-------------------------------------------------------------------------------------
	; - 9 -
	; Calcul de l'adresse de départ des données du sprite en fonctions des décalages
	;
	; D et E contiennent déjà la largeur du sprite en pixel ainsi que le nombre de ligne à
	; ne pas afficher.
	;
	; Multiplication du nombre de pixel par ligne par le nombre de lignes
	;
	; En entrée :
	;	D  <=> Multiplicande (A)
	;	E  <=> Multiplicateur (B)
	; En sortie :
	;	DE   Produit de A par B
	;
	; E contient déjà le nombre de lignes à passer
	; D contient la largeur du prise en pixel
	;
	CALL MATH_MUL_8x8

	; Adresse du sprite dans HL
	LD H, (IX + 5)
	LD L, (IX + 4)
	ADD HL, DE	; Ajout du décalage à l'adresse des données du sprite pour les lignes qui ne sont pas affichées
	ADD HL, BC	; BC contient (dx1), ajout du nombre de pixels qui ne sont pas affichées pour la ligne première ligne à afficher
	PUSH HL		; Transfert de l'adresse des données du sprite dans IY
	POP IY		;

	; Adresse du masque dans HL
	LD H, (IX + 7)
	LD L, (IX + 6)
	ADD HL, DE	; Ajout du décalage à l'adresse des données du sprite
	ADD HL, BC	; Ajout du nombre de pixels à passer avant d'afficher le sprite
	PUSH HL		; Transfert de l'adresse des données du sprite dans IY
	POP IX		;

	POP HL		; Restauration de l'adresse du premier point à afficher


	; - 10 -
	; Initialisation du nombre de lignes à traiter
	____GRAPH_SPRITE_SHOW_SPRITE_4_PreAffectation_nbLignes
	LD B, 0		; Pré-affectation (nbLignes)


_GRAPH_SPRITE_SHOW_SPRITE_4_BoucleSurLesLignes

	; - 11 -
	; Intialisation du nombre de points à traiter par ligne
	____GRAPH_SPRITE_SHOW_SPRITE_4_PreAffectation_nbPixels
	LD C, 0		;Pré-affectation (nbPixels)

	; - 12 -
	; Nombre de décalage par défaut
	____GRAPH_SPRITE_SHOW_SPRITE_4_Preaffectation_Decalages
	LD D, 0		; Pré-affectation (Decalages)

	; - 13 -
	; Masque de préservation par défaut
	____GRAPH_SPRITE_SHOW_SPRITE_4_PreAffectation_MasquePreservation
	LD E, 0		; Pré-affectation (Masque)

	
_GRAPH_SPRITE_SHOW_SPRITE_4_BoucleSurLesPixels

	; - 14 -
	; Vérification que tous les pixels de la ligne courante ont été traités
	;
	LD A, C	; Transfert du nombre de pixels restant à traiter dans A
	OR A	; Si tous les point ont été traités, on calcul l'adresse graphique suivante en ajoutant l'offset
	JP z, _GRAPH_SPRITE_SHOW_SPRITE_4_TestNombreDeLignes

	PUSH BC		; Sauvegarde des compteurs B et C (nombre de lignes et nombre de pixels par ligne)

	; - 15 -
	; Récupération des données du masque et du sprite
	;
	LD A, D		; Nombre de décalages dans A
	LD B, A

	; - 16 -
	; Déclage des données du masque et des données du sprite si un décalage doit être effectué
	;
	OR A		; Vérification si l'on doit décaler les données du sprite

	LD C, (IY)	; Récupération du point à afficher et décalage des bits en fonction de la position logique à l'écran
	LD A, (IX)	; Récupération du masque logique associé au sprite et décalage des bits en fonction de la position logique à l'écran

	JP z, _GRAPH_SPRITE_SHOW_SPRITE_4_AffichagePixelCourant

_GRAPH_SPRITE_SHOW_SPRITE_4_DeclageMasqueEtSprite

	SLA C		; Décalage des données du point à afficher
	SLA A		; Décalage des données du masque logique associé aux données du sprite

	DJNZ _GRAPH_SPRITE_SHOW_SPRITE_4_DeclageMasqueEtSprite

_GRAPH_SPRITE_SHOW_SPRITE_4_AffichagePixelCourant

	; - 17 -
	; Calcul du masque logique de préservation des données
			; Le masque logique associé au sprite est déjà dans A
	OR E		; Association avec le masque de préservation des données du point voisin au point courant
	LD B, A		; Sauvegarde du masque dans C

	; - 18 -
	; Affichage du nouveau point
	LD A, (HL)	; Récupération de l'octet graphique courant
	AND B		; Préservation des données à partir du masque précédement calculé
	OR C		; Ajout des données du nouveau point
	LD (HL), A	; Affichage du nouveau point à l'écran

	; - 19 -
	; Restauration et ajustement des compteurs
	POP BC		; Restauration de compteurs
	DEC C		; Décrémentation du nombre de points à traiter

	; - 20 -
	; Traitement du point suivant
	INC IX		; Incrémentation de l'adresse du masque logique
	INC IY		; Incrémentation de l'adresse du sprite

	; - 21 -
	; Décalage du masque de préservation pour traiter les données du point suivant
	RRC E		; Décalage du masque de préservation des données du point voisin
			; de manière à traiter le point suivant

	; - 22 -
	; L'octet graphique courant a t-il complètement été traité ? (Nombre de décalage = 0)
	LD A, D
	OR A
	JP z, _GRAPH_SPRITE_SHOW_SPRITE_4_OctetSuivant

	; - 23 -
	; Ajustement de nombre de déclages restant à effectuer dur l'octet courant
	DEC D	; Décrémentation du nombre de décalages à affectuer pour traiter les pixels restant
	JP _GRAPH_SPRITE_SHOW_SPRITE_4_BoucleSurLesPixels

_GRAPH_SPRITE_SHOW_SPRITE_4_OctetSuivant

	; - 24 -
	; Octet suivant
	INC HL	; Octet graphique suivant
	LD D, CST_GRAPH_PIXELS_PER_BYTE - 1
		; D va contenir le nombre de décalages à effectuer pour traiter
		; les données du point suivant.

	JP _GRAPH_SPRITE_SHOW_SPRITE_4_BoucleSurLesPixels

_GRAPH_SPRITE_SHOW_SPRITE_4_TestNombreDeLignes

	; - 25 -
	; Toutes les lignes ont elles été toutes traitées
	DJNZ _GRAPH_SPRITE_SHOW_SPRITE_4_LigneSuivante
	JP _GRAPH_SPRITE_SHOW_SPRITE_4_FinBoucleSurLesLignes

_GRAPH_SPRITE_SHOW_SPRITE_4_LigneSuivante

	; - 26 -
	; Calcul des nouvelles adresses des données du sprite et du masque logique en fonction des décalages (dx1 et dx2)
	____GRAPH_SPRITE_SHOW_SPRITE_4_PreAffectation_OffsetSprite
	LD DE, 0	; Pré-affectation (offset_sprite)
	ADD IY, DE	; Décalage de l'adresse des données du sprite et du masque
	ADD IX, DE	;

	; - 27 -
	; Vérification que la série de ligne a complètement été traitée
	EX AF, AF'
	DEC A
	OR A
	JP nz, _GRAPH_SPRITE_SHOW_SPRITE_4_NouvelleLigne

	OR 8		; Nouvelle série de 8 lignes
	LD DE, &3FB0	; &3FB0 = &4000 - &50 = Espace d'adressage d'une série complète de lignes - Offset pour la série de lignes suivantes
	SBC HL, DE	;       => HL = HL - &4000 + &50

_GRAPH_SPRITE_SHOW_SPRITE_4_NouvelleLigne

	; - 28 -
	; Calcul de l'adresse vidéo de la nouvelle ligne en fonction des déclages dx1 et dx2
	____GRAPH_SPRITE_SHOW_SPRITE_4_PreAffectation_OffsetLigne
	LD DE, 0	; Pré-affectation (offset_ligne) 
	ADD HL, DE	; Passage à la ligne suivante

	EX AF, AF'	; Sauvegarde de AF'
	JP _GRAPH_SPRITE_SHOW_SPRITE_4_BoucleSurLesLignes

_GRAPH_SPRITE_SHOW_SPRITE_4_FinBoucleSurLesLignes

	EX AF, AF'	; Restauration de AF'
	POP AF		; 
	EX AF, AF'	; 

_GRAPH_SPRITE_SHOW_SPRITE_4_END

	POP IY		; Restauration des registres
	POP IX
	POP HL
	POP DE
	POP BC
	POP AF
	RET





;-------------------------------------------------
; Affichage d'un sprite en mode 2 couleurs
;
GRAPH_SPRITE_SHOW_SPRITE_2:

	PUSH AF		; Sauvegarde des registres
	PUSH BC
	PUSH DE
	PUSH HL
	PUSH IX
	PUSH IY


	;----------------------------------------------------------------
	; - 1 -
	; Vérification de la position du sprite à l'écran
	;
	; En entrée
	;	BC <=> Position sur x
	;	DE <=> Position sur y
	;	IX <=> Adresse d'une structure Sprite
	;
	; En sortie
	;	A  <=> Si le sprite est visible à l'écran, A contient 1 sinon 0
	CALL GRAPH_SPRITE_TEST_POSITION
	OR A	; Vérification si A = 1, si oui le sprite est visible à l'écran
		; sinon on sort
	JP z, _GRAPH_SPRITE_SHOW_SPRITE_2_END

_GRAPH_SPRITE_SHOW_SPRITE_2_Initialisation


	;----------------------------------------------------------------
	; - 2 -
	; Calcul du n° de la ligne courante dans la série de lignes
	;
	EX AF, AF'	; Travail sur AF'
	PUSH AF		; Sauvegarde de AF' pour le retour
	LD A, E		; Y dans A'
	AND 7		; Préservation des 3 premiers bits pour connaître le n° de la ligne courante
	NEG		; Valeur négative de A
	ADD 8		; Ajout de 8 pour obtenir le nombre de lignes restant à traiter dans la série
	EX AF, AF'	; Sauvegarde AF'


	;----------------------------------------------------------------
	; - 3 -
	; Calcul de l'adresse de base du premier pixel à afficher
	;
	; En entrée
	;	BC <=> X1 sur 16 bits
	;	A  <=> Y1 sur 8 bits
	; En sortie
	; 	HL <=> Adresse du premier point
	;
	LD A, E		; Y dans A
	CALL GRAPH_ADR_OF_PIXEL
	PUSH HL		; Sauvegarde de l'adresse du premier point
	

	;----------------------------------------------------------------
	; - 4 -
	; Calcul du nombre de décalage binaire à effectuer pour afficher
	; le premier point du sprite
	;
	LD A, C		; Transfert de la partie basse de BC (x) pour calculer la position du premier point
	LD L, A		; Sauvegarde de la partie basse de x dans L pour pouvoir calculer le nombre d'octets de données du sprite à ne pas traiter
	LD B, CST_GRAPH_PIXELS_PER_BYTE - 1
	AND B
	LD C, A		; A dans C pour calculer le nombre de décalages binaire pour afficher le premier point
	LD A, B		; 
	SUB A, C	; A contient le nombre de décalages
	

	;----------------------------------------------------------------
	; - 5 -
	; Calcul du masque de préservation par défaut
	;
	; Décalage vers la droite d'un entier de 8 bits
	; carry est ré-injecté vers la gauche
	;
	; En entrée
	;	E  <=> Entier de 8 bits
	;	A  <=> Nombre de bits à décaler
	; En sortie
	;	E <=> Résultat du décalage des n bits
	; Registres affectés
	;	F, E
	;
 	LD E, %11111110		; Masque par défaut
	CALL MATH_RLC_8

	LD (____GRAPH_SPRITE_SHOW_SPRITE_2_PreAffectation_Decalages + 1), A
	LD A, E			; Transfert du masque dans A pour stockage
	LD (____GRAPH_SPRITE_SHOW_SPRITE_2_PreAffectation_MasquePreservation + 1), A


	;----------------------------------------------------------------
	; - 6 -
	; Calcul du nombre de pixels à afficher et du nombre de lignes
	;
	; Nombre de lignes à afficher
	LD A, (GRAPH_POSITION_DY1)	; dy1 dans C. Lignes non affichées
	LD C, A		; 
	LD A, (GRAPH_POSITION_DY2)	; dy2 dans B. Lignes non affichées
	LD B, A		; 
	LD A, (IX + 1)	; (IX + 1) Hauteur du sprite en pixel
	LD E, C		; E contient le nombre de lignes à passer avant l'affichage du sprite
	SUB B		; On retire dy1 et dy2 de la hauteur du sprite pour connaître le nombre de lignes à afficher
	SUB C		;
	LD (____GRAPH_SPRITE_SHOW_SPRITE_2_PreAffectation_nbLignes + 1), A
	
	; Nombre de pixels à afficher
	LD A, (GRAPH_POSITION_DX1)	; dx1 dans B. Pixels non affichés
	LD B, A		; 
	LD A, (GRAPH_POSITION_DX2)	; dx2 dans C. Pixels non affichés
	LD C, A		; 
	LD A, (IX + 0)	; (IX + 0) Largeur du sprite en pixel
	LD D, A		; Largeur du sprite dans D
	SUB B		; On retire dx1 et dx2 pour connaître le nombre de pixels à afficher
	SUB C		;
	LD (____GRAPH_SPRITE_SHOW_SPRITE_2_PreAffectation_nbPixels + 1), A


	;----------------------------------------------------------------
	; - 7 -
	; Calcul du déclage utilisé pour recalculer les adresses des données du sprite
	; et du masque logique, lors du passage à la ligne de données suivante
	LD A, B		; Transfert de (dx1) dans A
	ADD C		; Ajout de (dx2) à A
			; Le total de (dx1) + (dx2) ne peut pas dépasser un octet car la largeur d'un sprite ne dépasse pas un octet	
	LD (____GRAPH_SPRITE_SHOW_SPRITE_2_PreAffectation_OffsetSprite + 1), A


	;----------------------------------------------------------------
	; - 8 -
	; Calcul du déclage utilisé pour recaluler l'adresse de la ligne
	; suivante, lors du passage d'une ligne à l'autre
	;
	; - Pour calculer l'Offset qui permet d'ajuster l'adresse graphique contenue dans HL,
	;   il faut prendre en compte la largeur du sprite, le fait que les 8 premiers pixels soient affichés à cheval
	;   sur 2 octets consécutifs et les éventuelles parties cachées du sprite via (dx1) et (dx2)
	; - Ce décalage correspond au nombre total d'octets qui ne sont pas traités, dans notre cas ce décalage va se calculer
	;   de cette façon
	;	1 - Vérification que les 4 premiers pixels du sprite sont à cheval sur 2 octets graphiques consécutifs
	;	    Application d'un ET logique sur la valeur de x. Dans notre cas x avait été sauvé dans L.
	;	2 - Prise en compte de la largeur du sprite se trouvant dans D
	;	3 - Prise en compte des éventuelles débordements, (dx1) et (dx2), engendrés par le fait que le sprite déborde de l'écran
	;	4 - Division du nombre total de pixels par 2 car le mode graphique 16 couleurs iomplique 2 pixels par octet
	; 
	LD A, L		; Transfert de la partie basse de x dans A
	AND 7		; 1 - Vérification que le sprite va être affiché à cheval sur 2 octets
			;     Application d'un ET logique sur la valeur de x pour prendre en compte le décalage des 8 premiers pixels .
			;     Dans notre cas x avait été sauvé dans L.
	ADD A, D	; 2 - Prise en compte de la largeur du sprite en pixel
	SUB B		; 3 - Prise en compte des éventuelles débordements (dx1) et (dx2)
	SUB C		;     B = (dx1), C = (dx2)
	SRL A		; 4 - Division par 8 car on a 4 pixels par octet en mode 1
	SRL A		;
	SRL A		; Au final, le décalage total = ([x(L) AND 7] + [Largeur du sprite (D)] - [(dx1) + (dx2)]) / 8
			;
	LD C, A		; Nombre de bytes non traités (déclage) dans C
	LD A, B		; Sauvegarde de (dx1) dans A
	LD B, 0		; Initialisation de B à 0 car le nombre de bytes non traités est codé sur un octet
	OR A		; On éfface Carry qui est éventuellement posé suite au décalage de bit précédent (SRL)
	LD HL, &800	; Largeur d'une ligne graphique
	SBC HL, BC	; On retire le décalage en octet pour le calcul de l'offset final
	LD C, A		; Sauvegarde de (dx1) dans C pour les calculs suivant
	LD A, H		; Pré-affectation de l'offset
	LD (____GRAPH_SPRITE_SHOW_SPRITE_2_PreAffectation_OffsetLigne + 2), A
	LD A, L		;
	LD (____GRAPH_SPRITE_SHOW_SPRITE_2_PreAffectation_OffsetLigne + 1), A



	;-------------------------------------------------------------------------------------
	; - 9 -
	; Calcul de l'adresse de départ des données du sprite en fonctions des décalages
	;
	; D et E contiennent déjà la largeur du sprite en pixel ainsi que le nombre de ligne à
	; ne pas afficher.
	;
	; Multiplication du nombre de pixel par ligne par le nombre de lignes
	;
	; En entrée :
	;	D  <=> Multiplicande (A)
	;	E  <=> Multiplicateur (B)
	; En sortie :
	;	DE   Produit de A par B
	;
	; E contient déjà le nombre de lignes à passer
	; D contient la largeur du prise en pixel
	;
	CALL MATH_MUL_8x8

	; Adresse du sprite dans HL
	LD H, (IX + 5)
	LD L, (IX + 4)
	ADD HL, DE	; Ajout du décalage à l'adresse des données du sprite pour les lignes qui ne sont pas affichées
	ADD HL, BC	; BC contient (dx1), ajout du nombre de pixels qui ne sont pas affichées pour la ligne première ligne à afficher
	PUSH HL		; Transfert de l'adresse des données du sprite dans IY
	POP IY		;

	; Adresse du masque dans HL
	LD H, (IX + 7)
	LD L, (IX + 6)
	ADD HL, DE	; Ajout du décalage à l'adresse des données du sprite
	ADD HL, BC	; Ajout du nombre de pixels à passer avant d'afficher le sprite
	PUSH HL		; Transfert de l'adresse des données du sprite dans IY
	POP IX		;

	POP HL		; Restauration de l'adresse du premier point à afficher


	; - 10 -
	; Initialisation du nombre de lignes à traiter
	____GRAPH_SPRITE_SHOW_SPRITE_2_PreAffectation_nbLignes
	LD B, 0		; Pré-affectation (nbLignes)


_GRAPH_SPRITE_SHOW_SPRITE_2_BoucleSurLesLignes

	; - 11 -
	; Intialisation du nombre de points à traiter par ligne
	____GRAPH_SPRITE_SHOW_SPRITE_2_PreAffectation_nbPixels
	LD C, 0		;Pré-affectation (nbPixels)

	; - 12 -
	; Nombre de décalage par défaut
	____GRAPH_SPRITE_SHOW_SPRITE_2_Preaffectation_Decalages
	LD D, 0		; Pré-affectation (Decalages)

	; - 13 -
	; Masque de préservation par défaut
	____GRAPH_SPRITE_SHOW_SPRITE_2_PreAffectation_MasquePreservation
	LD E, 0		; Pré-affectation (Masque)

	
_GRAPH_SPRITE_SHOW_SPRITE_2_BoucleSurLesPixels

	; - 14 -
	; Vérification que tous les pixels de la ligne courante ont été traités
	;
	LD A, C	; Transfert du nombre de pixels restant à traiter dans A
	OR A	; Si tous les point ont été traités, on calcul l'adresse graphique suivante en ajoutant l'offset
	JP z, _GRAPH_SPRITE_SHOW_SPRITE_2_TestNombreDeLignes

	PUSH BC		; Sauvegarde des compteurs B et C (nombre de lignes et nombre de pixels par ligne)

	; - 15 -
	; Récupération des données du masque et du sprite
	;
	LD A, D		; Nombre de décalages dans A
	LD B, A

	; - 16 -
	; Déclage des données du masque et des données du sprite si un décalage doit être effectué
	;
	OR A		; Vérification si l'on doit décaler les données du sprite

	LD C, (IY)	; Récupération du point à afficher et décalage des bits en fonction de la position logique à l'écran
	LD A, (IX)	; Récupération du masque logique associé au sprite et décalage des bits en fonction de la position logique à l'écran

	JP z, _GRAPH_SPRITE_SHOW_SPRITE_2_AffichagePixelCourant

_GRAPH_SPRITE_SHOW_SPRITE_2_DeclageMasqueEtSprite

	SLA C		; Décalage des données du point à afficher
	SLA A		; Décalage des données du masque logique associé aux données du sprite

	DJNZ _GRAPH_SPRITE_SHOW_SPRITE_2_DeclageMasqueEtSprite

_GRAPH_SPRITE_SHOW_SPRITE_2_AffichagePixelCourant

	; - 17 -
	; Calcul du masque logique de préservation des données
			; Le masque logique associé au sprite est déjà dans A
	OR E		; Association avec le masque de préservation des données du point voisin au point courant
	LD B, A		; Sauvegarde du masque dans C

	; - 18 -
	; Affichage du nouveau point
	LD A, (HL)	; Récupération de l'octet graphique courant
	AND B		; Préservation des données à partir du masque précédement calculé
	OR C		; Ajout des données du nouveau point
	LD (HL), A	; Affichage du nouveau point à l'écran

	; - 19 -
	; Restauration et ajustement des compteurs
	POP BC		; Restauration de compteurs
	DEC C		; Décrémentation du nombre de points à traiter

	; - 20 -
	; Traitement du point suivant
	INC IX		; Incrémentation de l'adresse du masque logique
	INC IY		; Incrémentation de l'adresse du sprite

	; - 21 -
	; Décalage du masque de préservation pour traiter les données du point suivant
	RRC E		; Décalage du masque de préservation des données du point voisin
			; de manière à traiter le point suivant

	; - 22 -
	; L'octet graphique courant a t-il complètement été traité ? (Nombre de décalage = 0)
	LD A, D
	OR A
	JP z, _GRAPH_SPRITE_SHOW_SPRITE_2_OctetSuivant

	; - 23 -
	; Ajustement de nombre de déclages restant à effectuer dur l'octet courant
	DEC D	; Décrémentation du nombre de décalages à affectuer pour traiter les pixels restant
	JP _GRAPH_SPRITE_SHOW_SPRITE_2_BoucleSurLesPixels

_GRAPH_SPRITE_SHOW_SPRITE_2_OctetSuivant

	; - 24 -
	; Octet suivant
	INC HL	; Octet graphique suivant
	LD D, CST_GRAPH_PIXELS_PER_BYTE - 1
		; D va contenir le nombre de décalages à effectuer pour traiter
		; les données du point suivant.

	JP _GRAPH_SPRITE_SHOW_SPRITE_2_BoucleSurLesPixels

_GRAPH_SPRITE_SHOW_SPRITE_2_TestNombreDeLignes

	; - 25 -
	; Toutes les lignes ont elles été toutes traitées
	DJNZ _GRAPH_SPRITE_SHOW_SPRITE_2_LigneSuivante
	JP _GRAPH_SPRITE_SHOW_SPRITE_2_FinBoucleSurLesLignes

_GRAPH_SPRITE_SHOW_SPRITE_2_LigneSuivante

	; - 26 -
	; Calcul des nouvelles adresses des données du sprite et du masque logique en fonction des décalages (dx1 et dx2)
	____GRAPH_SPRITE_SHOW_SPRITE_2_PreAffectation_OffsetSprite
	LD DE, 0	; Pré-affectation (offset_sprite)
	ADD IY, DE	; Décalage de l'adresse des données du sprite et du masque
	ADD IX, DE	;

	; - 27 -
	; Vérification que la série de ligne a complètement été traitée
	EX AF, AF'
	DEC A
	OR A
	JP nz, _GRAPH_SPRITE_SHOW_SPRITE_2_NouvelleLigne

	OR 8		; Nouvelle série de 8 lignes
	LD DE, &3FB0	; &3FB0 = &4000 - &50 = Espace d'adressage d'une série complète de lignes - Offset pour la série de lignes suivantes
	SBC HL, DE	;       => HL = HL - &4000 + &50

_GRAPH_SPRITE_SHOW_SPRITE_2_NouvelleLigne

	; - 28 -
	; Calcul de l'adresse vidéo de la nouvelle ligne en fonction des déclages dx1 et dx2
	____GRAPH_SPRITE_SHOW_SPRITE_2_PreAffectation_OffsetLigne
	LD DE, 0	; Pré-affectation (offset_ligne) 
	ADD HL, DE	; Passage à la ligne suivante

	EX AF, AF'	; Sauvegarde de AF'
	JP _GRAPH_SPRITE_SHOW_SPRITE_2_BoucleSurLesLignes

_GRAPH_SPRITE_SHOW_SPRITE_2_FinBoucleSurLesLignes

	EX AF, AF'	; Restauration de AF'
	POP AF		; 
	EX AF, AF'	; 

_GRAPH_SPRITE_SHOW_SPRITE_2_END

	POP IY		; Restauration des registres
	POP IX
	POP HL
	POP DE
	POP BC
	POP AF
	RET




;**********************************************************************
; Permet d'adapter les données d'un sprite au format logique de l'écran
; Toutes les couleurs brutes sont remplacées par les donées des couleurs
; entrelacées
;
; En entrée
;	IX <=> Adresse d'une structure Sprite
; En sortie
;	aucun
; Registres affectés
;	
; Remarques
;	- Cette fonction compile les données brutes d'un sprite.
;	  Elle remplace les données non entrelacées des couleurs par des données entrelacées
;	  Dans le cas où un masque est associé au sprite, les données du masque sont aussi
;	  compilées. Les données des pixels sont toutes alignées à droite.
;
;	Sprite {
;		BYTE width	 ; largeur du sprite en pixel
;		BYTE height	 ; hauteur du sprite en pixel
;		WORD sprite_size ; taille du tampon
;		WORD sprite	 ; adresse du tampon contenant les données du sprite
;		WORD mask	 ; adresse du tampon du masque logique qui doit avoir la même taille que le sprite
;		BYTE static_datas; indique si les données du sprite sont issues de données statiques
;	} (9 octets)
;

GRAPH_SPRITE_COMPILE_SPRITE:

	PUSH AF
	PUSH BC
	PUSH DE
	PUSH HL
	
	; Récupération de l'adresse de la table des couleurs en fonction du mode graphique 
	LD A, CST_GRAPH_VIDEO_MODE
	CP 0	; Mode 0, 16 couleurs
	JP nz, _GRAPH_SPRITE_COMPILE_SPRITE_1
	LD HL, DEF_GRAPH_TABLE_PIXEL_16
	JP _GRAPH_SPRITE_COMPILE_SPRITE_3

_GRAPH_SPRITE_COMPILE_SPRITE_1

	CP 1	; Mode 0, 4 couleurs
	LD HL, DEF_GRAPH_TABLE_PIXEL_4
	JP _GRAPH_SPRITE_COMPILE_SPRITE_3

_GRAPH_SPRITE_COMPILE_SPRITE_2

	CP 2	; Mode 0, 2 couleurs
	JP nz, _GRAPH_SPRITE_COMPILE_SPRITE_END
	LD HL, DEF_GRAPH_TABLE_PIXEL_2

_GRAPH_SPRITE_COMPILE_SPRITE_3

	; Récupération du nombre d'octet à traiter
	LD B, (IX + 3)
	LD C, (IX + 2)

	; Traitement des données du sprite
	LD D, (IX + 5)	; Traitement des données du sprite
	LD E, (IX + 4)	;
	CALL _GRAPH_SPRITE_COMPILE_SPRITE_4

	; Traitement des données du masque
	LD D, (IX + 7)	; Récupération de l'adresse du masque
	LD E, (IX + 6)	;
	CALL _GRAPH_SPRITE_COMPILE_SPRITE_4

	POP HL
	POP DE
	POP BC
	POP AF
	RET

_GRAPH_SPRITE_COMPILE_SPRITE_4

	; Sous-routine de traitement des données des couleurs
	; Remplacement des couleurs linéaires au format logique de l'écran,
	; remplacement des valeurs non entrelacées par les valeurs entrelacées des couleurs.
	; Les données entrelacées des couleurs sont décalées d'autant de bits vers la gauche
	; qu'il y a de pixels par octet.
	;
	;	BC <=> Taille du sprite en octets
	;	IY <=> Adresse des données du sprite
	;	HL <=> Adresse de la table des couleurs
	;
	PUSH BC

_GRAPH_SPRITE_COMPILE_SPRITE_5

	LD A, B		; Vérification si tous les bits de BC sont à 0, si oui tous les octets ont été traités
	OR C		;
	OR A		; Test de A
	JP z, _GRAPH_SPRITE_COMPILE_SPRITE_6

	DEC BC		; Décompte du nombre d'octets à traiter
	PUSH BC		; Sauvegarde du compteur

	; Traitement des données du sprite
	LD A, (DE)	; Récupération du n° de la couleur dans A
	LD B, 0		; Transfert du numéro de la couleur dans BC pour ajuster HL
	LD C, A		;
	
	; Récupération de la valeur entrelacée de la couleur du point courant
	ADD HL, BC	; Ajout du n° de la couleur à l'adresse de la table des couleurs
			; pour pointer directement sur la valeur de la couleur entrelacée
	LD A, (HL)	; Récupération des données de la couleur entrelacée courante
	SBC HL, BC	; Restauration de l'adresse initiale pour nouveau traitement

	; Décalage des données de la couleur entrelacée, vers le bas car les données sont alignées par défaut à gauche
	PUSH BC
	LD B, CST_GRAPH_PIXELS_PER_BYTE - 1

_GRAPH_SPRITE_COMPILE_SPRITE_DeclageVersLeBas

	SRL A		; Déclage des données de la couleur entrelacée d'1 bit vers le bas car
			; les données sont par défaut alignées à gauche
	DJNZ _GRAPH_SPRITE_COMPILE_SPRITE_DeclageVersLeBas

	POP BC
	LD (DE), A	; Sauvegarde des données entrelacées du pixel courant
			; Ces données sont alignées au foramt logique de l'écran
	INC DE		; Couleur suivante

	POP BC		; Restauration du compteur
	JP _GRAPH_SPRITE_COMPILE_SPRITE_5
	
_GRAPH_SPRITE_COMPILE_SPRITE_6

	POP BC		; Retour
	RET 

_GRAPH_SPRITE_COMPILE_SPRITE_END





;********************************************************************
; Permet de créer un nouvel object
;
; En entrée
;	D  <=> Largeur de l'objet en pixel
;	E  <=> Hauteur de l'objet en pixel
; En sortie
;	IX <=> Adresse mémoire du nouvel object
; Registres affectés
;	IX
; Remarques
;
;	Objet {
;		WORD x		 ; position sur x de l'objet
;		WORD y		 ; position sur y de l'objet
;		BYTE xincr	 ; incrémentation sur x, permet de définir une direction sur x
;		BYTE yincr	 ; incrémentation sur y, permet de définir une direction sur y
;		BYTE state	 ; liste des différents états du sprite, codés sous forme binaire
;				 ;   Bit    Description
;				 ;    0		Visibilité de l'objet, 1 = visible
;				 ;    1		Type d'objet, 0 = fixe, 1 = animé
;				 ;    2		Objet fantôme, 1 = mode fantôme (pas de collisions)
;				 ;    3		-
;				 ;    4		-
;				 ;    5		-
;				 ;    6		-
;				 ;    7		-
;		WORD sprite	 ; référence à la structure contenant les données du sprite associé à l'objet
;		WORD memory_block; référence à la structure contenant les données de la zone graphique impactée par le sprite
;	} (11 octets)
;

GRAPH_SPRITE_NEW_OBJECT:

	PUSH BC
	PUSH DE
	PUSH HL

	; Réservation de la mémoire pour la structure de l'objet
	; En entrée
	;	BC <=> Taille en octet
	; En sortie
	;       HL <=> Adresse de la nouvelle zone mémoire
	LD BC, 11
	CALL SYS_GET_MEMORY
	PUSH HL

	; Initialisation de la structure
	LD (HL), 0	; (HL + 0) Position sur x de l'objet (16 bits)
	INC HL
	LD (HL), 0
	INC HL
	LD (HL), 0	; (HL + 2) Position sur y de l'objet
	INC HL
	LD (HL), 0
	INC HL
	LD (HL), 0	; (HL + 4) xincr
	INC HL
	LD (HL), 0	; (HL + 5) yincr
	INC HL

	; Attributs par défaut de l'objet
	LD (HL), CST_GRAPH_OBJECT_ATTRIBUT_VISIBLE + CST_GRAPH_OBJECT_ATTRIBUT_MOVING
		; (HL + 6) Etat par défaut de l'objet (visible et animé) %00000011

	;------------------------------------------------
	; Création du sprite
	;
	; En entrée
	;	D  <=> Largeur du sprite en pixel
	;	E  <=> Hauteur du sprite en pixel
	; En sortie
	;	IX <=> Adresse mémoire du nouveau sprite
	;
	CALL GRAPH_SPRITE_NEW_SPRITE	
	PUSH IX
	POP BC		; Copie de l'adresse du sprite dans BC pour stockage

	INC HL		; (HL + 7), (HL + 8) Stockage de l'adrese du sprite (sur 16 bits)
	LD (HL), C	;
	INC HL		;
	LD (HL), B	;

	;------------------------------------------------
	; Création de la zone de sauvegarde des données graphiques
	;
	; En entrée
	;	D  <=> Largeur du block en pixel
	;	E  <=> Hauteur du block en pixel
	; En sortie
	;	IX <=> Adresse mémoire de la structure MémoryBlock
	;
	CALL GRAPH_SPRITE_NEW_MEMORYBLOCK
	PUSH IX
	POP BC		; Copie de l'adresse du bloc mémoire dans BC pour stockage

	INC HL		; (HL + 9), (HL + 10) Stockage de l'adrese du bloc mémoire (sur 16 bits)
	LD (HL), C	;
	INC HL		;
	LD (HL), B	;

	POP IX		; Restauration de l'adresse de la structure de l'objet
			; pour le retour

_GRAPH_SPRITE_NEW_OBJECT_END

	POP HL
	POP DE
	POP BC
	RET




;********************************************************************
; Permet de créer un nouvel object à partir d'un sprite existant
;
; En entrée
;	D  <=> Largeur de l'objet en pixel
;	E  <=> Hauteur de l'objet en pixel
;	IX <=> Adresse des données du sprite existant
;	IY <=> Adresse des données du masque existant
; En sortie
;	IX <=> Adresse mémoire du nouvel object
; Registres affectés
;	IX
; Remarques
;
;	Objet {
;		WORD x		 ; position sur x de l'objet
;		WORD y		 ; position sur y de l'objet
;		BYTE xincr	 ; incrémentation sur x, permet de définir une direction sur x
;		BYTE yincr	 ; incrémentation sur y, permet de définir une direction sur y
;		BYTE state	 ; liste des différents états du sprite, codés sous forme binaire
;				 ;   Bit    Description
;				 ;    0		Visibilité du sprite, 1 = visible
;				 ;    1		Type de sprite, 0 = fixe, 1 = animé
;				 ;    2		Mode fantôme { 1 = mode fantôme activé } (permet de désactiver l'interactivité avec d'autres objets)
;				 ;    3		-
;				 ;    4		-
;				 ;    5		-
;				 ;    6		-
;				 ;    7		-
;		WORD sprite	 ; référence à la structure contenant les données du sprite associé à l'objet
;		WORD memory_block; référence à la structure contenant les données de la zone graphique impactée par le sprite
;	} (11 octets)
;

GRAPH_SPRITE_NEW_OBJECT_FROM_DATAS:

	PUSH BC
	PUSH DE
	PUSH HL


	; Réservation de la mémoire pour la structure de l'objet
	; En entrée
	;	BC <=> Taille en octet
	; En sortie
	;       HL <=> Adresse de la nouvelle zone mémoire
	;
	LD BC, 11
	CALL SYS_GET_MEMORY
	PUSH HL

	; Initialisation de la structure
	LD (HL), 0	; (HL + 0) Position sur x de l'objet (16 bits)
	INC HL
	LD (HL), 0
	INC HL
	LD (HL), 0	; (HL + 2) Position sur y de l'objet
	INC HL
	LD (HL), 0
	INC HL
	LD (HL), 0	; (HL + 4) xincr
	INC HL
	LD (HL), 0	; (HL + 5) yincr
	INC HL

	; Attributs par défaut de l'objet
	LD (HL), CST_GRAPH_OBJECT_ATTRIBUT_VISIBLE + CST_GRAPH_OBJECT_ATTRIBUT_MOVING
		; (HL + 6) Etat par défaut de l'objet (visible et animé) %00000011


	;------------------------------------------------
	; Création du sprite
	;
	; En entrée
	;	D  <=> Largeur du sprite en pixels
	;	E  <=> Hauteur du sprite en pixel
	;	IX <=> Adresse des données d'un sprite existant
	;	IY <=> Adresse des données du masque associé au sprite
	; En sortie
	;	IX <=> Adresse du nouveau sprite
	;
	CALL GRAPH_SPRITE_NEW_SPRITE_FROM_DATAS
	PUSH IX
	POP BC		; Copie de l'adresse du sprite dans BC pour stockage

	INC HL		; (HL + 7), (HL + 8) Stockage de l'adrese du sprite (sur 16 bits)
	LD (HL), C	;
	INC HL		;
	LD (HL), B	;

	;------------------------------------------------
	; Création de la zone de sauvegarde des données graphiques
	;
	; En entrée
	;	D  <=> Largeur du block en pixel
	;	E  <=> Hauteur du block en pixel
	; En sortie
	;	IX <=> Adresse mémoire de la structure MémoryBlock
	;
	CALL GRAPH_SPRITE_NEW_MEMORYBLOCK
	PUSH IX
	POP BC		; Copie de l'adresse du bloc mémoire dans BC pour stockage

	INC HL		; (HL + 9), (HL + 10) Stockage de l'adrese du bloc mémoire (sur 16 bits)
	LD (HL), C	;
	INC HL		;
	LD (HL), B	;

	POP IX		; Restauration de l'adresse de la structure de l'objet
			; pour le retour

_GRAPH_SPRITE_NEW_OBJECT_FROM_DATAS_END

	POP HL
	POP DE
	POP BC
	RET




;********************************************************************
; Permet de détruire un objet existant et de libérer toutes
; les ressources mémoires associées
;
; En entrée
;	IX <=> Adresse d'une structure liée à un objet
; En sortie
;	IX <=> 0
; Registres affectés
;	IX
; Remarques
;
;	Objet {
;		WORD x		 ; position sur x de l'objet
;		WORD y		 ; position sur y de l'objet
;		BYTE xincr	 ; incrémentation sur x, permet de définir une direction sur x
;		BYTE yincr	 ; incrémentation sur y, permet de définir une direction sur y
;		BYTE state	 ; liste des différents états du sprite, codés sous forme binaire
;				 ;   Bit    Description
;				 ;    0		Visibilité du sprite, 1 = visible
;				 ;    1		Type de sprite, 0 = fixe, 1 = animé
;				 ;    2		Mode fantôme { 1 = mode fantôme activé } (permet de désactiver l'interactivité avec d'autres objets)
;				 ;    3		-
;				 ;    4		-
;				 ;    5		-
;				 ;    6		-
;				 ;    7		-
;		WORD sprite	 ; référence à la structure contenant les données du sprite associé à l'objet
;		WORD memory_block; référence à la structure contenant les données de la zone graphique impactée par le sprite
;	} (11 octets)
;

GRAPH_SPRITE_FREE_OBJECT:

	PUSH BC
	PUSH IY

	PUSH IX		; Transfert de l'adresse de la structure de l'objet dans IY
	POP IY		; pour récupération des différentes adresses
	
	; Libération du bloc de sauvegarde
	;
	; En entrée
	;	IX <=> adresse d'un bloc MemoryBloc
	; En sortie
	;	IX <=> 0, le bloc a été détruit
	; Registres affectés
	;	IX
	; 
	LD B, (IY + 10)	; Adresse de la structure MemoryBlock
	LD C, (IY + 9)
	PUSH BC
	POP IX
	CALL GRAPH_SPRITE_FREE_MEMORYBLOCK

	; Libération des données du sprite
	;
	; En entrée
	;	IX <=> Adresse d'une structure liée à un sprite
	; En sortie
	;	IX <=> 0
	;
	LD B, (IY + 8)	; Adresse de la structure du sprite
	LD C, (IY + 7)
	PUSH BC
	POP IX
	CALL GRAPH_SPRITE_FREE_SPRITE

	; Destruction de la structure de l'objet
	;
	; En entrée
	;       HL <=> Adresse du pointeur de la zone mémoire
	;	BC <=> Taille en octet
	; En sortie
	;       HL <=> 0 si la zone mémoire a été libérée
	;
	PUSH IY
	POP HL
	LD BC, 11
	CALL SYS_FREE_MEMORY
	LD IX, 0

_GRAPH_SPRITE_FREE_OBJECT_END

	POP IY
	POP BC
	RET




;********************************************************************
; Permet modifier les attributs d'un objet
;
; En entrée
;	B  <=> Identifiant d'un attribut ou des attributs à changer
;	C  <=> Nouvel valeur des attributs (0 ou 1)
;	IY <=> Adresse mémoire de l'objet
; En sortie
;	aucun
; Registres affectés
;	aucun
; Remarques
;
;	La liste des attributs de l'objet sont 
;		- CST_GRAPH_OBJECT_ATTRIBUT_VISIBLE
;		- CST_GRAPH_OBJECT_ATTRIBUT_MOVING
;		- CST_GRAPH_OBJECT_ATTRIBUT_GHOST
;
;	Ces constantes peuvent être ajoutées les une aux autres
;

GRAPH_SPRITE_OBJECT_SET_STATE:
	
	PUSH AF
	PUSH DE

	LD E, 0		; Initialisation de E à 0
	BIT 0, C	; Vérification si l'on doit activé l'état courant
	JP z, _GRAPH_SPRITE_OBJECT_SET_STATE_1
	LD E, B		; On stocke l'identifiant de l'état ou des états courants dans E, cet identifiant correspond au bit associé à l'état courant

_GRAPH_SPRITE_OBJECT_SET_STATE_1

	LD A, B		; Stockage de l'identifiant de l'état concerné dans A pour calculer un masque de préservation de bits
	CPL		; Masque de préservation permettant la récupération les valeurs courantes des l'état voisins de l'état concerné
	LD D, A		; Transfert de A dans D pour appliquer le masque logique
	LD A, (IY + 6)  ; Récupération des valeurs courantes de tous les états de l'objet
	AND D		; Récuparation des états voisins de l'état concerné
	OR E		; Affectation du bit de l'état concerné
	LD (IY + 6), A	; Sauvegarde du nouvel état

_GRAPH_SPRITE_OBJECT_SET_STAT_END

	POP DE
	POP AF
	RET




;********************************************************************
; Permet de créer un nouveau bloc mémoire pour la sauvegarde graphique
;
; En entrée
;	IX <=> adresse d'un bloc MemoryBloc
; En sortie
;	IX <=> 0, le bloc a été détruit
; Registres affectés
;	IX
; Remarques
;
;	MemoryBlock {
;		BYTE width	 ; largeur en octet du block mémoire
;		BYTE height	 ; hauteur du block en pixel
;		BYTE lines_count ; nombre total de lignes, réellement traitées
;		WORD buffer	 ; adresse du tampon contenant les données du block mémoire
;		WORD buffer_size ; taille du tampon
;		WORD memory_adr	 ; adresse mémoire de base, de la zone sauvegardé
;		BYTE ligne	 ; numéro de la ligne courante dans la série de lignes
;	} (10 octets)
;

GRAPH_SPRITE_FREE_MEMORYBLOCK:

	PUSH BC
	PUSH HL


	; Libération de la mémoire du tampon de sauvegarde de la zone mémoire
	;       HL <=> Adresse du pointeur de la zone mémoire
	;	BC <=> Taille en octet
	; En sortie
	;       HL <=> 0 si la zone mémoire a été libérée
	LD H, (IX + 4)	; Adresse du tampon à libérer
	LD L, (IX + 3)	;
	LD B, (IX + 6)	; Taille de la zone à libérer
	LD C, (IX + 5)	;
	CALL SYS_FREE_MEMORY

	; Libération de la mémoire du tampon de sauvegarde de la zone mémoire
	;       HL <=> Adresse du pointeur de la zone mémoire
	;	BC <=> Taille en octet
	; En sortie
	;       HL <=> 0 si la zone mémoire a été libérée
	LD BC, 10	; Taille de la zone à libérer
	PUSH IX
	POP HL
	CALL SYS_FREE_MEMORY
	LD IX, 0

_GRAPH_SPRITE_FREE_MEMORYBLOCK_END
	
	POP HL
	POP BC
	RET



;********************************************************************
; Permet de créer un nouveau bloc mémoire pour la sauvegarde graphique
;
; En entrée
;	D  <=> Largeur du block en pixel
;	E  <=> Hauteur du block en pixel
; En sortie
;	IX <=> Adresse mémoire de la structure MémoryBlock
; Registres affectés
;	IX
; Remarques
;
;	MemoryBlock {
;		BYTE width	 ; largeur en octet du block mémoire
;		BYTE height	 ; hauteur du block en pixel
;		BYTE lines_count ; nombre total de lignes, réellement traitées
;		WORD buffer	 ; adresse du tampon contenant les données du block mémoire
;		WORD buffer_size ; taille du tampon
;		WORD memory_adr	 ; adresse mémoire de base, de la zone sauvegardé
;		BYTE ligne	 ; numéro de la ligne courante dans la série de lignes
;	} (10 octets)
;

GRAPH_SPRITE_NEW_MEMORYBLOCK:

	PUSH AF
	PUSH BC
	PUSH DE
	PUSH HL


	; Réservation de la mémoire pour la structure MemoryBloc
	; En entrée
	;	BC <=> Taille en octet
	; En sortie
	;       HL <=> Adresse de la nouvelle zone mémoire
	LD BC, 10
	CALL SYS_GET_MEMORY
	PUSH HL		; Sauvegarde de l'adresse du bloc mémoire pour le retour
	LD B, E		; Sauvegarde la hauteur du bloc dans B

	; Calcul du nombre d'octet nécessaires pour stocker les infotmations
	;
	; En entrée
	;	D  <=> Largeur du sprite en pixels
	;	E  <=> Hauteur du sprite en pixel
	; En sortie
	;	DE <=> Nombre d'octets nécessaires pour stocker un sprite en fonction du mode graphique
	;	A  <=> Nombre d'octets nécessaires pour socker une ligne du sprite en fonction du mode graphique
	CALL GRAPH_SPRITE_SIZE_ON_SCREEN

	; Initialisation de la structure
	LD (HL), A	; (IX + 0) Largeur de chaque ligne en octet
	INC HL
	LD (HL), B	; (IX + 1) Hauteur du bloc en pixels
	INC HL
	LD (HL), 0	; (IX + 2) Nombre de lignes réellement à traiter

	; Réservation de la mémoire pour les données à sauvegarder
	; En entrée
	;	BC <=> Taille en octet
	; En sortie
	;       HL <=> Adresse de la nouvelle zone mémoire
	LD B, D
	LD C, E
	EX HL, DE	; Sauvegarde de HL
	CALL SYS_GET_MEMORY
	EX HL, DE	; Restauration de HL

	; Initialisation des données liées au nouveau bloc mémoire
	INC HL
	LD (HL), E	; (IX + 3), (IX + 4) Adresse zone de sauvegarde
	INC HL		;
	LD (HL), D	;
	INC HL
	LD (HL), C	; (IX + 5), (IX + 6) Taile de la zone de sauvegarde
	INC HL		;
	LD (HL), B	; 
	INC HL
	LD (HL), 0	; (IX + 7), (IX + 8) Adresse de base de la zone mémoire
	INC HL		;
	LD (HL), 0	; 
	INC HL	
	LD (HL), 0	; (IX + 9) n° de la ligne courant dans la série de lignes

	POP IX		; Restauration de l' adresse du nouveau bloc mémoire pour le retour

_GRAPH_SPRITE_NEW_MEMORYBLOCK_END
	
	POP HL
	POP DE
	POP BC
	POP AF
	RET




;********************************************************************
; Permet de créer un nouveau sprite
;
; En entrée
;	D  <=> Largeur du sprite en pixel
;	E  <=> Hauteur du sprite en pixel
; En sortie
;	IX <=> Adresse mémoire du nouveau sprite
; Registres affectés
;	IX
; Remarques
;
;	Sprite {
;		BYTE width	 ; largeur en pixel du sprite
;		BYTE height	 ; hauteur en pixel du sprite
;		WORD sprite_size ; taille du tampon
;		WORD sprite	 ; adresse du tampon contenant les données du sprite
;		WORD mask	 ; adresse du tampon du masque logique qui doit avoir la même taille que le sprite
;		BYTE static_datas; indique si les données du sprite sont issues de données statiques (tableaux dans le code assembleur par ex)
;	} (9 octets)
;

GRAPH_SPRITE_NEW_SPRITE:

	PUSH BC
	PUSH DE
	PUSH HL

	;---------------------------------------------------
	; Réservation de la mémoire pour la structure du sprite
	; En entrée
	;	BC <=> Taille en octet
	; En sortie
	;       HL <=> Adresse de la nouvelle zone mémoire
	;
	LD BC, 9
	CALL SYS_GET_MEMORY
	PUSH HL		; Transfert de l'adresse de la structure du nouveau sprite dans IX
	POP IX		; pour le retour

	; Stockage des dimensions du nomveau sprite
	LD (HL), D	; (HL + 0) Largeur en pixel
	INC HL
	LD (HL), E	; (HL + 1) Hauteur en pixel

	;---------------------------------------------------
	; Calcul du nombre d'octet à réserver pour stocker les données du sprite et du masque
	; associé au sprite
	;
	; En entrée :
	;	D <=> Multiplicande (A)
	;	E <=> Multiplicateur (B)
	; En sortie :
	;	DE   Produit de A par B
	;
	CALL MATH_MUL_8x8

	; Stockage de la taille du sprite, en octets
	INC HL		
	LD (HL), E	; (HL + 2), (HL + 3) Taille du sprite en octet (sur 16 bits)
	INC HL		;
	LD (HL), D	;

	;---------------------------------------------------
	; Réservation de la mémoire pour le sprite
	; En entrée
	;	BC <=> Taille en octet
	; En sortie
	;       HL <=> Adresse de la nouvelle zone mémoire
	;
	LD B, D
	LD C, E
	EX HL, DE	; Sauvegarde de HL

	CALL SYS_GET_MEMORY

	EX HL, DE	; Transfert de l'adresse des données du nouveau sprite dans DE pour stockage
			; et restauration de HL pour continuer l'adressage de la structure du sprite

	; Sauvegarde de l'adresse du tampon de sauvegarde des données du sprite
	INC HL
	LD (HL), E	; (HL + 4), (HL + 5) Adresse du tampon (sur 16 bits)
	INC HL		;
	LD (HL), D	;

	;---------------------------------------------------
	; Réservation de la mémoire pour le tampon du masque
	; En entrée
	;	BC <=> Taille en octet
	; En sortie
	;       HL <=> Adresse de la nouvelle zone mémoire
	;
	EX HL, DE	; Sauvegarde de HL
	CALL SYS_GET_MEMORY
	EX HL, DE	; Restauration de HL et stockage de l'adresse des donées du masque dans DE
	
	; Sauvegarde de l'adresse des données du masque
	INC HL
	LD (HL), E	; (HL + 6), (HL + 7) Adresse des données du masque (sur 16 bits)
	INC HL		;
	LD (HL), D	;
	INC HL
	LD (HL), 0	; (HL + 8) Indique que les données peuvent être supprimées de la mémoire
			; car le sprite est créé à partir de données dynamiques
	
_GRAPH_SPRITE_NEW_SPRITE_END

	POP HL
	POP DE
	POP BC
	RET



;********************************************************************
; Permet de créer un nouveau sprite à partir de données statiques
;
; En entrée
;	D  <=> Largeur du sprite en pixel
;	E  <=> Hauteur du sprite en pixel
;	IX <=> Adresse des données d'un sprite existant
;	IY <=> Adresse des données du masque associé au sprite
; En sortie
;	IX <=> Adresse mémoire du nouveau sprite
; Registres affectés
;	IX
; Remarques
;
;	Sprite {
;		BYTE width	 ; largeur en pixel du sprite
;		BYTE height	 ; hauteur en pixel du sprite
;		WORD sprite_size ; taille du tampon
;		WORD sprite	 ; adresse du tampon contenant les données du sprite
;		WORD mask	 ; adresse du tampon du masque logique qui doit avoir la même taille que le sprite
;		BYTE static_datas; indique si les données du sprite sont issues de données statiques
;	} (9 octets)
;

GRAPH_SPRITE_NEW_SPRITE_FROM_DATAS:

	PUSH BC
	PUSH DE
	PUSH HL

	; Sauvegarde des pointeurs
	PUSH IY
	PUSH IX
	
	; Réservation de la mémoire pour la structure du sprite
	; En entrée
	;	BC <=> Taille en octet
	; En sortie
	;       HL <=> Adresse de la nouvelle zone mémoire
	;
	LD BC, 12
	CALL SYS_GET_MEMORY
	PUSH HL		; Transfert de l'adresse de la structure du nouveau sprite dans IX
	POP IX		; pour le retour

	; Stockage des dimensions du nombeau sprite
	LD (HL), D	; (HL + 0) Largeur du sprite en pixel
	INC HL
	LD (HL), E	; (HL + 1) Hauteur du sprite en pixel
	
	;---------------------------------------------------
	; Calcul du nombre d'octet à réserver pour stocker les données du sprite et du masque
	; associé au sprite
	;
	; En entrée :
	;	D <=> Multiplicande (A)
	;	E <=> Multiplicateur (B)
	; En sortie :
	;	DE   Produit de A par B
	;
	CALL MATH_MUL_8x8

	; Stockage de la taille du sprite, en octets
	INC HL
	LD (HL), E	; (HL + 2), (HL + 3) Taille du sprite en octet (sur 16 bits)
	INC HL		;
	LD (HL), D	;
	; Adresse des données du sprite existant
	POP DE		; Récupération de IX
	INC HL
	LD (HL), E	; (HL + 4), (HL + 5) Adresse du sprite existant (sur 16 bits)
	INC HL		;
	LD (HL), D	;
	; Adresse des données du masque logique associé au sprite
	POP DE		; Récupération de IY
	INC HL
	LD (HL), E	; (HL + 6), (HL + 7) Adresse des données du masque existant (sur 16 bits)
	INC HL		;
	LD (HL), D	;
	INC HL
	LD (HL), 1	; (HL + 8) Indique que les données ne peuvent pas être supprimées de la mémoire
			; car le sprite est créé à partir de données statiques (tableau statique ou autre)

_GRAPH_SPRITE_NEW_SPRITE__FROM_DATAS_END

	POP HL
	POP DE
	POP BC
	RET

	
;********************************************************************
; Permet de détruire un sprite existant et de libérer toutes
; les ressources mémoires associées
;
; En entrée
;	IX <=> Adresse d'une structure liée à un sprite
; En sortie
;	IX <=> 0
; Registres affectés
;	IX
; Remarques
;
;	Sprite {
;		BYTE width	 ; largeur en pixel du sprite
;		BYTE height	 ; hauteur en pixel du sprite
;		WORD sprite_size ; taille du tampon
;		WORD sprite	 ; adresse du tampon contenant les données du sprite
;		WORD mask	 ; adresse du tampon du masque logique qui doit avoir la même taille que le sprite
;		BYTE static_datas; indique si les données du sprite sont issues de données statiques
;	} (9 octets)
;

GRAPH_SPRITE_FREE_SPRITE:

	PUSH AF
	PUSH BC
	PUSH HL

	; Vérification que les données du sprite peuvent être détruite
	; et qu'elles ne sont pas issues de données statiques
	LD A, (IX + 8)	; Type de données, si = 1 les ressources du sprite sont issues de données statiques et
			; ne peuvent être libérées
	OR A
	JP nz, _GRAPH_SPRITE_FREE_SPRITE_1

	; Récupération de la taille en octet des données liées au sprite
	LD B, (IX + 3)	; Taille des données
	LD C, (IX + 2)	;

	;--------------------------------------------------------
	; Libération de la mémoire du tampon de données du masque
	;       HL <=> Adresse du pointeur de la zone mémoire
	;	BC <=> Taille en octet
	; En sortie
	;       HL <=> 0 si la zone mémoire a été libérée
	;
	LD H, (IX + 7)	; Adresse du tampon de données du masque
	LD L, (IX + 6)
	CALL SYS_FREE_MEMORY

	;--------------------------------------------------------
	; Libération de la mémoire du tampon de données du sprite
	;       HL <=> Adresse du pointeur de la zone mémoire
	;	BC <=> Taille en octet
	; En sortie
	;       HL <=> 0 si la zone mémoire a été libérée
	;
	LD H, (IX + 5)	; Adresse du tampon de données du sprite
	LD L, (IX + 4)
	CALL SYS_FREE_MEMORY


_GRAPH_SPRITE_FREE_SPRITE_1

	; Récupération de la largeur du sprite en pixel
	;LD B, 0
	;LD C, (IX + 0)	; Taille des données

	;--------------------------------------------------------
	; Libération de la mémoire du tampon de travail
	;       HL <=> Adresse du pointeur de la zone mémoire
	;	BC <=> Taille en octet
	; En sortie
	;       HL <=> 0 si la zone mémoire a été libérée
	;
	;LD H, (IX + 3)	; Adresse du tampon de travail 
	;LD L, (IX + 2)
	;CALL SYS_FREE_MEMORY

	;--------------------------------------------------------
	; Destruction de la structure du sprite
	;       HL <=> Adresse du pointeur de la zone mémoire
	;	BC <=> Taille en octet
	; En sortie
	;       HL <=> 0 si la zone mémoire a été libérée
	LD BC, 9	; Taille de la zone à libérer
	PUSH IX
	POP HL
	CALL SYS_FREE_MEMORY
	LD IX, 0
		
_GRAPH_SPRITE_FREE_SPRITE_END

	POP HL
	POP BC
	POP AF
	RET




;********************************************************************
; Efface l'écran avec le couleur 0 quelque soit le mode graphique
;
; En entrée
;	néant
; En sortie
;	néant
; Registres affectés
;	aucun
; Remarques
;	Les interruptions doivent être activées avec EI
;	pour la rafraîchissement de l'écran
;

GRAPH_CLEAR_SCREEN:

	PUSH AF
	PUSH BC
	PUSH DE
	PUSH HL
	
	LD HL, (DEF_GRAPH_VIDEO_ADR)
	LD D, H
	LD E, L
	INC DE
	LD BC, &3FFF
	LD (HL), 0
	LDIR
	
GRAPH_CLEAR_SCREEN_END
	
	POP HL
	POP DE
	POP BC
	POP AF
	RET




;********************************************************************
; Remplissage l'écran par une couleur en fonction du mode graphique
;
; En entrée
;	A <=> La couleur de remplissage
; En sortie
;	néant
; Registres affectés
;	aucun
; Remarques
;	Les interruptions doivent être activées avec EI
;	pour la rafraîchissement de l'écran
;

GRAPH_FILL_SCREEN:
 
	PUSH AF
	PUSH BC
	PUSH DE
	PUSH HL

	LD D, 0
	LD E, A

	; Vérification du mode graphique
	LD A, CST_GRAPH_VIDEO_MODE
	OR A
	JP nz, _GRAPH_FILL_SCREEN_1

	LD HL, DEF_GRAPH_TABLE_PIXEL_16
	LD B, 1
	JP _GRAPH_FILL_SCREEN_3

_GRAPH_FILL_SCREEN_1

	CP 1
	JP nz, _GRAPH_FILL_SCREEN_2

	LD HL, DEF_GRAPH_TABLE_PIXEL_4
	LD B, 3
	JP _GRAPH_FILL_SCREEN_3

_GRAPH_FILL_SCREEN_2

	CP 2
	JP nz, GRAPH_FILL_SCREEN_END

	LD HL, DEF_GRAPH_TABLE_PIXEL_2
	LD B, 7

_GRAPH_FILL_SCREEN_3

	ADD HL, DE
	LD E, (HL)
	LD A, E

_GRAPH_FILL_SCREEN_4

	; Calcul du masque logique pour la couleur en fonction du masque graphique
	SRL A
	OR E
	DJNZ _GRAPH_FILL_SCREEN_4

_GRAPH_FILL_SCREEN_5

	; Remplissage
	LD HL, (DEF_GRAPH_VIDEO_ADR)
	LD D, H
	LD E, L
	INC DE
	LD BC, &3FFF
	LD (HL), A
	LDIR

GRAPH_FILL_SCREEN_END

	POP HL
	POP DE
	POP BC
	POP AF
	RET




;*********************************************************************
; Affichage d'une ligne quelque soit le mode graphique
;
; En entrée
;	BC <=> X1
;	HL <=> X2
;	D  <=> Y1
;	E  <=> Y2
;	A  <=> Couleur de la ligne (de 0 à 3)
; En sortie
;	néant
; Registres affectés
;	aucun
; Remarques
;

GRAPH_LINE:

	PUSH AF

	; Vérification du mode graphique en cours
	LD A, CST_GRAPH_VIDEO_MODE
	CP 2
	JP z, _GRAPH_LINE_2
	CP 1
	JP z, _GRAPH_LINE_4
	OR A
	JP z, _GRAPH_LINE_16

	; Retour si le mode graphique est <> 0,1 ou 2
	POP AF
	RET

_GRAPH_LINE_16

	; Affichage de la ligne 16 couleurs
	POP AF
	CALL GRAPH_LINE_16
	RET

_GRAPH_LINE_4

	; Affichage de la ligne 4 couleurs
	POP AF
	CALL GRAPH_LINE_4
	RET
	
_GRAPH_LINE_2

	; Affichage de la ligne 2 couleurs
	POP AF
	CALL GRAPH_LINE_2
	RET

GRAPH_LINE_END





;*********************************************************************
; Affichage d'une ligne en mode 2 (2 couleurs, 8 pixels par octet)
;
; En entrée
;	BC <=> X1
;	HL <=> X2
;	D  <=> Y1
;	E  <=> Y2
;	A  <=> Couleur de la ligne (de 0 à 1)
; En sortie
;	néant
; Registres affectés
;	aucun
; Remarques
;	Zone d'affichage x1 = 0, x2 = 639, y1 = 0, y2 = 199
;
LINE_2_COUNT DW 0

GRAPH_LINE_2:

	PUSH AF
	PUSH BC
	PUSH HL
	PUSH DE
	PUSH IX
	PUSH IY

	; Création de la pile de travail
	AND 1		; Préservation du bit 0 de A de manière à ne permettre que les couleurs 0 ou 1
	PUSH AF		; (SP) 	   <=> Y1
			; (SP + 1) <=> Couleur du point

	; Calcul de la position de la pile de travail
	PUSH HL
	LD HL, 0
	ADD HL, SP
	INC HL
	INC HL
	PUSH HL
	POP IY		; IY Contient l'adresse de base de la pile de travail
	POP HL


	; Test des valeurs en entrée
	; Echange des valeurs si X1 > à X2 ou Y1 > Y2
	;
	; IF X1 > X2 THEN X1 <=> X2
	; IF Y1 > Y2 THEN Y1 <=> Y2
	;

	;Y
	LD A, D		; Comparaison Y1 avec Y2
	CP E		; (D = Y1, E = Y2)
	JP c, _GRAPH_LINE_2_1
	LD D, E		; Echange Y1 avec Y2
	LD E, A		;
	 	
_GRAPH_LINE_2_1

	;X
	OR A		; On efface Carry
	PUSH HL
	SBC HL, BC	; Si inférieur à 0 Carry = 1
	JP nc, _GRAPH_LINE_2_2
	LD H, B
	LD L, C
	POP BC
	JP _GRAPH_LINE_2_3

_GRAPH_LINE_2_2

	POP HL

_GRAPH_LINE_2_3

	; -----------------------------------------------
	; Affichage du premier pixel
	;
	; Paramètres en entrée de la procédure GRAPH_PIXEL
	;
	; En entrée
	;	BC <=> X sur 16 bits
	;	D  <=> Y sur 8 bits
	;	E  <=> Couleur du pixel sur 8 bits
	;
	;	CALL Pixel (X1, Y1, Couleur) (BC, D, E)
	;
	PUSH DE
	LD E, (IY + 1)	; Chargement de E avec la couleur sauvegarder à (SP + 1)

	CALL GRAPH_PUT_PIXEL_2		; Affichage du point en 2 couleurs
	POP DE



	; Stockage de X1 et de Y1
	PUSH BC		; Récupération de X1 dans IX
	POP IX		;
	LD (IY), D	; Récupération de Y1 dans (IY)

	
	; -----------------------------------------------
	; Calcul de dx et de dy
	;
	; dx = X2 - X1
	; dy = Y2 - Y1
	;
	; HL <=> dx
	; BC <=> dy

	; dx
	OR A		; On efface Carry
	SBC HL, BC
		
	; dy
	LD A, E
	SUB D
	LD B, 0
	LD C, A

	; IF dy > dx THEN
	OR A		; On efface Carry
	PUSH HL
	SBC HL, BC
	POP DE		; DE <=> dx
	JP nc, _GRAPH_LINE_2_6


	; -----------------------------------------------
	;  	Tracé de la ligne (dy > dx)
	;
	; Rappel de l'affectation des registres
	;
	; HL  <=> Cumul
	; DE  <=> dx
	; BC  <=> dy
	; IX  <=> X1
	; A   <=> Compteur dy
	; (IY)<=> Y1

	; Cumul = dy \ 2
	; SRL -> RRA
	LD H, B
	LD A, C
	SRL H
	RRA
	LD L, A	; HL <=> Cumul

	; FOR i = dy TO 1
	LD (LINE_2_COUNT), BC
	LD A, (IY)

_GRAPH_LINE_2_4

	; 	Y1 = Y1 + 1
	INC A
	;	Cumul = cumul + dx
	ADD HL, DE
	;	IF cumul >= dy THEN
	PUSH HL
	SBC HL, BC
	POP HL
	JP c, _GRAPH_LINE_2_5
	;		Cumul = cumul - dy
	OR A
	SBC HL, BC
	;		X1 = X1 + 1
	INC IX
	;	END
_GRAPH_LINE_2_5

	; -----------------------------------------------
	; Affichage du pixel courant
	;
	; Paramètres en entrée de la procédure GRAPH_PIXEL
	;
	; En entrée
	;	BC <=> X sur 16 bits
	;	D  <=> Y sur 8 bits
	;	E  <=> Couleur du pixel sur 8 bits
	;
	;	CALL Pixel (X1, Y1, Couleur) (BC, D, E)
	;
	
	PUSH BC
	PUSH DE
	PUSH IX
	POP BC
	LD D, A
	LD E, (IY + 1)	; Chargement de E avec la couleur sauvegarder à (SP + 1)

	CALL GRAPH_PUT_PIXEL_2		; Affichage du point en 2 couleurs
	POP DE
	
	; NEXT i
	OR A
	PUSH HL
	LD BC, 1
	LD HL, (LINE_2_COUNT)
	SBC HL, BC
	LD (LINE_2_COUNT), HL
	POP HL
	POP BC
	JP nz, _GRAPH_LINE_2_4
	JP GRAPH_LINE_2_END

_GRAPH_LINE_2_6

	; -----------------------------------------------
	;  	Tracé de la ligne (dy <= dx)
	;
	; Rappel de l'affectation des registres
	;
	; HL  <=> Cumul
	; DE  <=> dx
	; BC  <=> dy
	; IX  <=> X1
	; (IY)<=> Y1

	; Cumul = dx \ 2
	; SRL -> RRA
	LD H, D
	LD A, E
	SRL H
	RRA
	LD L, A	; HL <=> Cumul

	; FOR i = dx TO 1
	LD (LINE_2_COUNT), DE
	LD A, (IY)

_GRAPH_LINE_2_7

	; 	X1 = X1 + 1
	INC IX
	;	Cumul = cumul + dy
	ADD HL, BC
	;	IF cumul >= dx THEN
	PUSH HL
	SBC HL, DE
	POP HL
	JP c, _GRAPH_LINE_2_8
	;		Cumul = cumul - dx
	OR A
	SBC HL, DE
	;		Y1 = Y1 + 1
	INC A
	;	END
_GRAPH_LINE_2_8

	; -----------------------------------------------
	; Affichage du pixel courant
	;
	; Paramètres en entrée de la procédure GRAPH_PIXEL
	;
	; En entrée
	;	BC <=> X sur 16 bits
	;	D  <=> Y sur 8 bits
	;	E  <=> Couleur du pixel sur 8 bits
	;
	;	CALL Pixel (X1, Y1, Couleur) (BC, D, E)
	;
	
	PUSH BC
	PUSH DE
	PUSH IX
	POP BC
	LD D, A		; Chargement de D avec Y1
	LD E, (IY + 1)	; Chargement de E avec la couleur sauvegarder à (SP + 1)

	CALL GRAPH_PUT_PIXEL_2		; Affichage du point en 2 couleurs
	POP DE
	
	; NEXT i
	OR A
	LD BC, 1
	PUSH HL
	LD HL, (LINE_2_COUNT)
	SBC HL, BC
	LD (LINE_2_COUNT), HL
	POP HL
	POP BC
	JP nz, _GRAPH_LINE_2_7

GRAPH_LINE_2_END

	POP AF	; Destruction de la pile de travail

	POP IY	; Restauration des registres
	POP IX	;
	POP DE	;
	POP HL	;
	POP BC	;
	POP AF	;
	RET



;**********************************************************************
; Affichage d'une ligne en mode 1 (4 couleurs, 4 pixels par octet)
;
; En entrée
;	BC <=> X1
;	HL <=> X2
;	D  <=> Y1
;	E  <=> Y2
;	A  <=> Couleur de la ligne (de 0 à 3)
; En sortie
;	néant
; Registres affectés
;	aucun
; Remarques
;	Zone d'affichage x1 = 0, x2 = 319, y1 = 0, y2 = 199
;
LINE_4_COUNT DW 0

GRAPH_LINE_4:

	PUSH AF
	PUSH BC
	PUSH HL
	PUSH DE
	PUSH IX
	PUSH IY

	; Création de la pile de travail
	AND 3		; Préservation des deux premiers bitd de A de manière à ne permettre que les couleurs de 0 à 15
	PUSH AF		; (SP) 	   <=> Y1
			; (SP + 1) <=> Couleur du point

	; Calcul de la position de la pile de travail
	PUSH HL
	LD HL, 0
	ADD HL, SP
	INC HL
	INC HL
	PUSH HL
	POP IY		; IY Contient l'adresse de base de la pile de travail
	POP HL


	; Test des valeurs en entrée
	; Echange des valeurs si X1 > à X2 ou Y1 > Y2
	;
	; IF X1 > X2 THEN X1 <=> X2
	; IF Y1 > Y2 THEN Y1 <=> Y2
	;

	;Y
	LD A, D		; Comparaison Y1 avec Y2
	CP E		; (D = Y1, E = Y2)
	JP c, _GRAPH_LINE_4_1
	LD D, E		; Echange Y1 avec Y2
	LD E, A		;
	 	
_GRAPH_LINE_4_1

	;X
	OR A		; On efface Carry
	PUSH HL
	SBC HL, BC	; Si inférieur à 0 Carry = 1
	JP nc, _GRAPH_LINE_4_2
	LD H, B
	LD L, C
	POP BC
	JP _GRAPH_LINE_4_3

_GRAPH_LINE_4_2

	POP HL

_GRAPH_LINE_4_3

	; -----------------------------------------------
	; Affichage du premier pixel
	;
	; Paramètres en entrée de la procédure GRAPH_PIXEL
	;
	; En entrée
	;	BC <=> X sur 16 bits
	;	D  <=> Y sur 8 bits
	;	E  <=> Couleur du pixel sur 8 bits
	;
	;	CALL Pixel (X1, Y1, Couleur) (BC, D, E)
	;
	PUSH DE
	LD E, (IY + 1)	; Chargement de E avec la couleur sauvegarder à (SP + 1)

	CALL GRAPH_PUT_PIXEL_4		; Affichage du point en 4 couleurs
	POP DE



	; Stockage de X1 et de Y1
	PUSH BC		; Récupération de X1 dans IX
	POP IX		;
	LD (IY), D	; Récupération de Y1 dans (IY)

	
	; -----------------------------------------------
	; Calcul de dx et de dy
	;
	; dx = X2 - X1
	; dy = Y2 - Y1
	;
	; HL <=> dx
	; BC <=> dy

	; dx
	OR A		; On efface Carry
	SBC HL, BC
	
	; dy
	LD A, E
	SUB D
	LD B, 0
	LD C, A

	; IF dy > dx THEN
	OR A		; On efface Carry
	PUSH HL
	SBC HL, BC
	POP DE		; DE <=> dx
	JP nc, _GRAPH_LINE_4_6


	; -----------------------------------------------
	;  	Tracé de la ligne (dy > dx)
	;
	; Rappel de l'affectation des registres
	;
	; HL  <=> Cumul
	; DE  <=> dx
	; BC  <=> dy
	; IX  <=> X1
	; A   <=> Compteur dy
	; (IY)<=> Y1

	; Cumul = dy \ 2
	; SRL -> RRA
	LD H, B
	LD A, C
	SRL H
	RRA
	LD L, A	; HL <=> Cumul

	; FOR i = dy TO 1
	LD (LINE_4_COUNT), BC
	LD A, (IY)

_GRAPH_LINE_4_4

	; 	Y1 = Y1 + 1
	INC A
	;	Cumul = cumul + dx
	ADD HL, DE
	;	IF cumul >= dy THEN
	PUSH HL
	SBC HL, BC
	POP HL
	JP c, _GRAPH_LINE_4_5
	;		Cumul = cumul - dy
	OR A
	SBC HL, BC
	;		X1 = X1 + 1
	INC IX
	;	END
_GRAPH_LINE_4_5

	; -----------------------------------------------
	; Affichage du pixel courant
	;
	; Paramètres en entrée de la procédure GRAPH_PIXEL
	;
	; En entrée
	;	BC <=> X sur 16 bits
	;	D  <=> Y sur 8 bits
	;	E  <=> Couleur du pixel sur 8 bits
	;
	;	CALL Pixel (X1, Y1, Couleur) (BC, D, E)
	;
	
	PUSH BC
	PUSH DE
	PUSH IX
	POP BC
	LD D, A
	LD E, (IY + 1)	; Chargement de E avec la couleur sauvegarder à (SP + 1)

	CALL GRAPH_PUT_PIXEL_4		; Affichage du point en 4 couleurs
	POP DE
	
	; NEXT i
	OR A
	PUSH HL
	LD BC, 1
	LD HL, (LINE_4_COUNT)
	SBC HL, BC
	LD (LINE_4_COUNT), HL
	POP HL
	POP BC
	JP nz, _GRAPH_LINE_4_4
	JP GRAPH_LINE_4_END

_GRAPH_LINE_4_6

	; -----------------------------------------------
	;  	Tracé de la ligne (dy <= dx)
	;
	; Rappel de l'affectation des registres
	;
	; HL  <=> Cumul
	; DE  <=> dx
	; BC  <=> dy
	; IX  <=> X1
	; (IY)<=> Y1

	; Cumul = dx \ 2
	; SRL -> RRA
	LD H, D
	LD A, E
	SRL H
	RRA
	LD L, A	; HL <=> Cumul

	; FOR i = dx TO 1
	LD (LINE_4_COUNT), DE
	LD A, (IY)

_GRAPH_LINE_4_7

	; 	X1 = X1 + 1
	INC IX
	;	Cumul = cumul + dy
	ADD HL, BC
	;	IF cumul >= dx THEN
	PUSH HL
	SBC HL, DE
	POP HL
	JP c, _GRAPH_LINE_4_8
	;		Cumul = cumul - dx
	OR A
	SBC HL, DE
	;		Y1 = Y1 + 1
	INC A
	;	END
_GRAPH_LINE_4_8

	; -----------------------------------------------
	; Affichage du pixel courant
	;
	; Paramètres en entrée de la procédure GRAPH_PIXEL
	;
	; En entrée
	;	BC <=> X sur 16 bits
	;	D  <=> Y sur 8 bits
	;	E  <=> Couleur du pixel sur 8 bits
	;
	;	CALL Pixel (X1, Y1, Couleur) (BC, D, E)
	;
	
	PUSH BC
	PUSH DE
	PUSH IX
	POP BC
	LD D, A		; Chargement de D avec Y1
	LD E, (IY + 1)	; Chargement de E avec la couleur sauvegarder à (SP + 1)

	CALL GRAPH_PUT_PIXEL_4		; Affichage du point en 4 couleurs
	POP DE
	
	; NEXT i
	OR A
	LD BC, 1
	PUSH HL
	LD HL, (LINE_4_COUNT)
	SBC HL, BC
	LD (LINE_4_COUNT), HL
	POP HL
	POP BC
	JP nz, _GRAPH_LINE_4_7

GRAPH_LINE_4_END

	POP AF	; Destruction de la pile de travail

	POP IY	; Restauration des registres
	POP IX	;
	POP DE	;
	POP HL	;
	POP BC	;
	POP AF	;
	RET


;**********************************************************************
; Affichage d'une ligne en mode 0 (16 couleurs, 2 pixels par octet)
;
; En entrée
;	BC <=> X1
;	HL <=> X2
;	D  <=> Y1
;	E  <=> Y2
;	A  <=> Couleur de la ligne (de 0 à 15)
; En sortie
;	néant
; Registres affectés
;	aucun
; Remarques
;	Zone d'affichage x1 = 0, x2 = 159, y1 = 0, y2 = 199
;

GRAPH_LINE_16:

	PUSH AF	; Sauvegarde des registres
	PUSH BC	;
	PUSH HL	;
	PUSH DE	;
	PUSH IX	;
	PUSH IY	;

	; Création de la pile de travail
	AND %1111	; Préservation des quatre premiers bits de A de manière à ne permettre que les couleurs de 0 à 15
	PUSH AF		; (SP)     <=> Y1
			; (SP + 1) <=> Couleur du point

	; Calcul de la position de la pile de travail
	PUSH HL
	LD HL, 0
	ADD HL, SP
	INC HL
	INC HL
	PUSH HL
	POP IY		; IY Contient l'adresse de base de la pile de travail
	POP HL


	; Echange des valeurs si X1 > à X2 ou Y1 > Y2
	;
	; IF X1 > X2 THEN X1 <=> X2
	; IF Y1 > Y2 THEN Y1 <=> Y2
	;

	;Y
	LD A, D		; Comparaison Y1 avec Y2
	CP E		; (D = Y1, E = Y2)
	JP c, _GRAPH_LINE_16_1
	LD D, E		; Echange Y1 avec Y2
	LD E, A		;
	 	
_GRAPH_LINE_16_1

	;X
	OR A		; On efface Carry
	PUSH HL
	SBC HL, BC	; Si inférieur à 0 Carry = 1
	JP nc, _GRAPH_LINE_16_2
	LD H, B
	LD L, C
	POP BC
	JP _GRAPH_LINE_16_3

_GRAPH_LINE_16_2

	POP HL

_GRAPH_LINE_16_3

	; -----------------------------------------------
	; Affichage du premier pixel
	;
	; Paramètres en entrée de la procédure GRAPH_PIXEL
	;
	; En entrée
	;	BC <=> X sur 16 bits
	;	D  <=> Y sur 8 bits
	;	E  <=> Couleur du pixel sur 8 bits
	;
	;	CALL Pixel (X1, Y1, Couleur) (BC, D, E)
	;
	PUSH DE
	LD E, (IY + 1)	; Chargement de E avec la couleur sauvegarder à (SP + 3)

	CALL GRAPH_PUT_PIXEL_16		; Affichage du point en 16 couleurs
	POP DE



	; Stockage de X1 et de Y1
	PUSH BC		; Récupération de X1 dans IX
	POP IX		;
	LD (IY), D	; Récupération de Y1 dans (IY)

	
	; -----------------------------------------------
	; Calcul de dx et de dy
	;
	; dx = X2 - X1
	; dy = Y2 - Y1
	;
	; HL <=> dx
	; BC <=> dy

	; dx
	OR A		; On efface Carry
	SBC HL, BC
		
	; dy
	LD A, E
	SUB D
	LD B, 0
	LD C, A

	; IF dy > dx THEN
	OR A		; On efface Carry
	PUSH HL
	SBC HL, BC
	POP DE		; DE <=> dx
	JP nc, _GRAPH_LINE_16_6


	; -----------------------------------------------
	;  	Tracé de la ligne (dy > dx)
	;
	; Rappel de l'affectation des registres
	;
	; HL   <=> Cumul
	; DE   <=> dx
	; BC   <=> dy
	; IX   <=> X1
	; A    <=> Compteur dy
	; (IY) <=> Y1

	; Cumul = dy \ 2
	; SRL -> RRA
	LD H, B
	LD A, C
	SRL H
	RRA
	LD L, A	; HL <=> Cumul

	; FOR i = dy TO 1
	LD A, C

_GRAPH_LINE_16_4

	; 	Y1 = Y1 + 1
	INC (IY)
	;	Cumul = cumul + dx
	ADD HL, DE
	;	IF cumul >= dy THEN
	PUSH HL
	SBC HL, BC
	POP HL
	JP c, _GRAPH_LINE_16_5
	;		Cumul = cumul - dy
	SBC HL, BC
	;		X1 = X1 + 1
	INC IX
	;	END
_GRAPH_LINE_16_5

	; -----------------------------------------------
	; Affichage du pixel courant
	;
	; Paramètres en entrée de la procédure GRAPH_PIXEL
	;
	; En entrée
	;	BC <=> X sur 16 bits
	;	D  <=> Y sur 8 bits
	;	E  <=> Couleur du pixel sur 8 bits
	;
	;	CALL Pixel (X1, Y1, Couleur) (BC, D, E)
	;
	
	PUSH BC
	PUSH DE
	PUSH IX
	POP BC
	LD D, (IY)	; Chargement de D avec Y1 à (SP)
	LD E, (IY + 1)	; Chargement de E avec la couleur sauvegarder à (SP + 1)

	CALL GRAPH_PUT_PIXEL_16		; Affichage du point en 16 couleurs
	POP DE
	POP BC
	
	; NEXT i
	DEC A
	JP nz, _GRAPH_LINE_16_4
	JP GRAPH_LINE_16_END


_GRAPH_LINE_16_6

	; -----------------------------------------------
	;  	Tracé de la ligne (dy <= dx)
	;
	; Rappel de l'affectation des registres
	;
	; HL   <=> Cumul
	; DE   <=> dx
	; BC   <=> dy
	; IX   <=> X1
	; (IY) <=> Y1

	; Cumul = dx \ 2
	; SRL -> RRA
	LD H, D
	LD A, E
	SRL H
	RRA
	LD L, A	; HL <=> Cumul

	; FOR i = dx TO 1
	LD A, E

_GRAPH_LINE_16_7

	; 	X1 = X1 + 1
	INC IX
	;	Cumul = cumul + dy
	ADD HL, BC
	;	IF cumul >= dx THEN
	PUSH HL
	SBC HL, BC
	POP HL
	JP c, _GRAPH_LINE_16_8
	;		Cumul = cumul - dx
	SBC HL, DE
	;		Y1 = Y1 + 1
	INC (IY)
	;	END
_GRAPH_LINE_16_8

	; -----------------------------------------------
	; Affichage du pixel courant
	;
	; Paramètres en entrée de la procédure GRAPH_PIXEL
	;
	; En entrée
	;	BC <=> X sur 16 bits
	;	D  <=> Y sur 8 bits
	;	E  <=> Couleur du pixel sur 8 bits
	;
	;	CALL Pixel (X1, Y1, Couleur) (BC, D, E)
	;
	
	PUSH BC
	PUSH DE
	PUSH IX
	POP BC
	LD D, (IY)	; Chargement de D avec Y1 à (SP)
	LD E, (IY + 1)	; Chargement de E avec la couleur sauvegarder à (SP + 1)

	CALL GRAPH_PUT_PIXEL_16		; Affichage du point en 16 couleurs
	POP DE
	POP BC
	
	; NEXT i
	DEC A
	JP nz, _GRAPH_LINE_16_7
	
GRAPH_LINE_16_END

	POP AF	; Destruction de la pile de travail

	POP IY	; Restauration des registres
	POP IX	;
	POP DE	;
	POP HL	;
	POP BC	;
	POP AF	;
	RET




;*********************************************************************
; Affichage d'une ligne quelque soit le mode graphique
; en effectuant une opération logique XOR sur les données graphiques
;
; En entrée
;	BC <=> X1
;	HL <=> X2
;	D  <=> Y1
;	E  <=> Y2
; En sortie
;	néant
; Registres affectés
;	aucun
; Remarques
;

GRAPH_LINE_XOR:

	PUSH AF

	; Vérification du mode graphique en cours
	LD A, CST_GRAPH_VIDEO_MODE
	CP 2
	JP z, _GRAPH_LINE_2_XOR
	CP 1
	JP z, _GRAPH_LINE_4_XOR
	OR A
	JP z, _GRAPH_LINE_16_XOR

	; Retour si le mode graphique est <> 0,1 ou 2
	POP AF
	RET

_GRAPH_LINE_16_XOR

	; Affichage de la ligne 16 couleurs
	POP AF
	CALL GRAPH_LINE_16_XOR
	RET

_GRAPH_LINE_4_XOR

	; Affichage de la ligne 4 couleurs
	POP AF
	CALL GRAPH_LINE_4_XOR
	RET
	
_GRAPH_LINE_2_XOR

	; Affichage de la ligne 2 couleurs
	POP AF
	CALL GRAPH_LINE_2_XOR
	RET

GRAPH_LINE_XOR_END



;*********************************************************************
; Affichage d'une ligne en mode 2 (2 couleurs, 8 pixels par octet)
; en effectuant une opération logique XOR sur les données graphoqies
;
; En entrée
;	BC <=> X1
;	HL <=> X2
;	D  <=> Y1
;	E  <=> Y2
; En sortie
;	néant
; Registres affectés
;	aucun
; Remarques
;	Zone d'affichage x1 = 0, x2 = 639, y1 = 0, y2 = 199
;
LINE_2_XOR_COUNT DW 0

GRAPH_LINE_2_XOR:

	PUSH AF
	PUSH BC
	PUSH HL
	PUSH DE
	PUSH IX
	PUSH IY

	; Création de la pile de travail
	PUSH AF		; (SP) 	   <=> Y1

	; Calcul de la position de la pile de travail
	PUSH HL
	LD HL, 0
	ADD HL, SP
	INC HL
	INC HL
	PUSH HL
	POP IY		; IY Contient l'adresse de base de la pile de travail
	POP HL


	; Test des valeurs en entrée
	; Echange des valeurs si X1 > à X2 ou Y1 > Y2
	;
	; IF X1 > X2 THEN X1 <=> X2
	; IF Y1 > Y2 THEN Y1 <=> Y2
	;

	;Y
	LD A, D		; Comparaison Y1 avec Y2
	CP E		; (D = Y1, E = Y2)
	JP c, _GRAPH_LINE_2_XOR_1
	LD D, E		; Echange Y1 avec Y2
	LD E, A		;
	 	
_GRAPH_LINE_2_XOR_1

	;X
	OR A		; On efface Carry
	PUSH HL
	SBC HL, BC	; Si inférieur à 0 Carry = 1
	JP nc, _GRAPH_LINE_2_XOR_2
	LD H, B
	LD L, C
	POP BC
	JP _GRAPH_LINE_2_XOR_3

_GRAPH_LINE_2_XOR_2

	POP HL

_GRAPH_LINE_2_XOR_3

	; -----------------------------------------------
	; Affichage du premier pixel
	;
	; Paramètres en entrée de la procédure GRAPH_PIXEL
	;
	; En entrée
	;	BC <=> X sur 16 bits
	;	A  <=> Y sur 8 bits
	;
	;	CALL Pixel (X1, Y1)
	;
	LD A, D
	CALL GRAPH_PUT_PIXEL_2_XOR		; Affichage du point en 2 couleurs
	
	; Stockage de X1 et de Y1
	PUSH BC		; Récupération de X1 dans IX
	POP IX		;
	LD (IY), D	; Récupération de Y1 dans (IY)

	
	; -----------------------------------------------
	; Calcul de dx et de dy
	;
	; dx = X2 - X1
	; dy = Y2 - Y1
	;
	; HL <=> dx
	; BC <=> dy

	; dx
	OR A		; On efface Carry
	SBC HL, BC
		
	; dy
	LD A, E
	SUB D
	LD B, 0
	LD C, A

	; IF dy > dx THEN
	OR A		; On efface Carry
	PUSH HL
	SBC HL, BC
	POP DE		; DE <=> dx
	JP nc, _GRAPH_LINE_2_XOR_6


	; -----------------------------------------------
	;  	Tracé de la ligne (dy > dx)
	;
	; Rappel de l'affectation des registres
	;
	; HL  <=> Cumul
	; DE  <=> dx
	; BC  <=> dy
	; IX  <=> X1
	; A   <=> Compteur dy
	; (IY)<=> Y1

	; Cumul = dy \ 2
	; SRL -> RRA
	LD H, B
	LD A, C
	SRL H
	RRA
	LD L, A	; HL <=> Cumul

	; FOR i = dy TO 1
	LD (LINE_2_XOR_COUNT), BC
	LD A, (IY)

_GRAPH_LINE_2_XOR_4

	; 	Y1 = Y1 + 1
	INC A
	;	Cumul = cumul + dx
	ADD HL, DE
	;	IF cumul >= dy THEN
	PUSH HL
	SBC HL, BC
	POP HL
	JP c, _GRAPH_LINE_2_XOR_5
	;		Cumul = cumul - dy
	OR A
	SBC HL, BC
	;		X1 = X1 + 1
	INC IX
	;	END
_GRAPH_LINE_2_XOR_5

	; -----------------------------------------------
	; Affichage du pixel courant
	;
	; Paramètres en entrée de la procédure GRAPH_PIXEL
	;
	; En entrée
	;	BC <=> X sur 16 bits
	;	A  <=> Y sur 8 bits
	;
	;	CALL Pixel (X1, Y1)
	;
	PUSH BC
	PUSH IX
	POP BC
	
	; A contient déjà la valeur courante de Y
	CALL GRAPH_PUT_PIXEL_2_XOR		; Affichage du point en 2 couleurs
		
	; NEXT i
	OR A
	PUSH HL
	LD BC, 1
	LD HL, (LINE_2_XOR_COUNT)
	SBC HL, BC
	LD (LINE_2_XOR_COUNT), HL
	POP HL
	POP BC
	JP nz, _GRAPH_LINE_2_XOR_4
	JP GRAPH_LINE_2_XOR_END

_GRAPH_LINE_2_XOR_6

	; -----------------------------------------------
	;  	Tracé de la ligne (dy <= dx)
	;
	; Rappel de l'affectation des registres
	;
	; HL  <=> Cumul
	; DE  <=> dx
	; BC  <=> dy
	; IX  <=> X1
	; (IY)<=> Y1

	; Cumul = dx \ 2
	; SRL -> RRA
	LD H, D
	LD A, E
	SRL H
	RRA
	LD L, A	; HL <=> Cumul

	; FOR i = dx TO 1
	LD (LINE_2_XOR_COUNT), DE
	LD A, (IY)

_GRAPH_LINE_2_XOR_7

	; 	X1 = X1 + 1
	INC IX
	;	Cumul = cumul + dy
	ADD HL, BC
	;	IF cumul >= dx THEN
	PUSH HL
	SBC HL, DE
	POP HL
	JP c, _GRAPH_LINE_2_XOR_8
	;		Cumul = cumul - dx
	OR A
	SBC HL, DE
	;		Y1 = Y1 + 1
	INC A
	;	END
_GRAPH_LINE_2_XOR_8

	; -----------------------------------------------
	; Affichage du pixel courant
	;
	; Paramètres en entrée de la procédure GRAPH_PIXEL
	;
	; En entrée
	;	BC <=> X sur 16 bits
	;	A  <=> Y sur 8 bits
	;
	;	CALL Pixel (X1, Y1)
	;
	PUSH BC
	PUSH IX
	POP BC
	
	; A contient déjà la valeur courante de Y
	CALL GRAPH_PUT_PIXEL_2_XOR		; Affichage du point en 2 couleurs
		
	; NEXT i
	OR A
	LD BC, 1
	PUSH HL
	LD HL, (LINE_2_XOR_COUNT)
	SBC HL, BC
	LD (LINE_2_XOR_COUNT), HL
	POP HL
	POP BC
	JP nz, _GRAPH_LINE_2_7

GRAPH_LINE_2_XOR_END

	POP AF	; Destruction de la pile de travail

	POP IY	; Restauration des registres
	POP IX	;
	POP DE	;
	POP HL	;
	POP BC	;
	POP AF	;
	RET



;**********************************************************************
; Affichage d'une ligne en mode 1 (4 couleurs, 4 pixels par octet)
; en effectuant une opération logique XOR sur les données graphoqies
;
; En entrée
;	BC <=> X1
;	HL <=> X2
;	D  <=> Y1
;	E  <=> Y2
; En sortie
;	néant
; Registres affectés
;	aucun
; Remarques
;	Zone d'affichage x1 = 0, x2 = 319, y1 = 0, y2 = 199
;
LINE_4_XOR_COUNT DW 0

GRAPH_LINE_4_XOR:

	PUSH AF
	PUSH BC
	PUSH HL
	PUSH DE
	PUSH IX
	PUSH IY

	; Création de la pile de travail
	PUSH AF		; (SP) 	   <=> Y1
		

	; Calcul de la position de la pile de travail
	PUSH HL
	LD HL, 0
	ADD HL, SP
	INC HL
	INC HL
	PUSH HL
	POP IY		; IY Contient l'adresse de basse de la pile de travail
	POP HL


	; Test des valeurs en entrée
	; Echange des valeurs si X1 > à X2 ou Y1 > Y2
	;
	; IF X1 > X2 THEN X1 <=> X2
	; IF Y1 > Y2 THEN Y1 <=> Y2
	;

	;Y
	LD A, D		; Comparaison Y1 avec Y2
	CP E		; (D = Y1, E = Y2)
	JP c, _GRAPH_LINE_4_XOR_1
	LD D, E		; Echange Y1 avec Y2
	LD E, A		;
	 	
_GRAPH_LINE_4_XOR_1

	;X
	OR A		; On efface Carry
	PUSH HL
	SBC HL, BC	; Si inférieur à 0 Carry = 1
	JP nc, _GRAPH_LINE_4_XOR_2
	LD H, B
	LD L, C
	POP BC
	JP _GRAPH_LINE_4_XOR_3

_GRAPH_LINE_4_XOR_2

	POP HL

_GRAPH_LINE_4_XOR_3

	; -----------------------------------------------
	; Affichage du premier pixel
	;
	; Paramètres en entrée de la procédure GRAPH_PIXEL
	;
	; En entrée
	;	BC <=> X sur 16 bits
	;	A  <=> Y sur 8 bits
	;
	;	CALL Pixel (X1, Y1)
	;
	LD A, D		; Y1 dans A

	CALL GRAPH_PUT_PIXEL_4_XOR		; Affichage du point en 4 couleurs
	


	; Stockage de X1 et de Y1
	PUSH BC		; Récupération de X1 dans IX
	POP IX		;
	LD (IY), D	; Récupération de Y1 dans (IY)

	
	; -----------------------------------------------
	; Calcul de dx et de dy
	;
	; dx = X2 - X1
	; dy = Y2 - Y1
	;
	; HL <=> dx
	; BC <=> dy

	; dx
	OR A		; On efface Carry
	SBC HL, BC
	
	; dy
	LD A, E
	SUB D
	LD B, 0
	LD C, A

	; IF dy > dx THEN
	OR A		; On efface Carry
	PUSH HL
	SBC HL, BC
	POP DE		; DE <=> dx
	JP nc, _GRAPH_LINE_4_XOR_6


	; -----------------------------------------------
	;  	Tracé de la ligne (dy > dx)
	;
	; Rappel de l'affectation des registres
	;
	; HL  <=> Cumul
	; DE  <=> dx
	; BC  <=> dy
	; IX  <=> X1
	; A   <=> Compteur dy
	; (IY)<=> Y1

	; Cumul = dy \ 2
	; SRL -> RRA
	LD H, B
	LD A, C
	SRL H
	RRA
	LD L, A	; HL <=> Cumul

	; FOR i = dy TO 1
	LD (LINE_4_XOR_COUNT), BC
	LD A, (IY)

_GRAPH_LINE_4_XOR_4

	; 	Y1 = Y1 + 1
	INC A
	;	Cumul = cumul + dx
	ADD HL, DE
	;	IF cumul >= dy THEN
	PUSH HL
	SBC HL, BC
	POP HL
	JP c, _GRAPH_LINE_4_XOR_5
	;		Cumul = cumul - dy
	OR A
	SBC HL, BC
	;		X1 = X1 + 1
	INC IX
	;	END
_GRAPH_LINE_4_XOR_5

	; -----------------------------------------------
	; Affichage du pixel courant
	;
	; Paramètres en entrée de la procédure GRAPH_PIXEL
	;
	; En entrée
	;	BC <=> X sur 16 bits
	;	A  <=> Y sur 8 bits
	;
	;	CALL Pixel (X1, Y1)
	;
	PUSH BC
	PUSH IX
	POP BC
	
	; A contient déjà la valeur courante de Y
	CALL GRAPH_PUT_PIXEL_4_XOR		; Affichage du point en 4 couleurs
	
	; NEXT i
	OR A
	PUSH HL
	LD BC, 1
	LD HL, (LINE_4_XOR_COUNT)
	SBC HL, BC
	LD (LINE_4_XOR_COUNT), HL
	POP HL
	POP BC
	JP nz, _GRAPH_LINE_4_XOR_4
	JP GRAPH_LINE_4_XOR_END

_GRAPH_LINE_4_XOR_6

	; -----------------------------------------------
	;  	Tracé de la ligne (dy <= dx)
	;
	; Rappel de l'affectation des registres
	;
	; HL  <=> Cumul
	; DE  <=> dx
	; BC  <=> dy
	; IX  <=> X1
	; (IY)<=> Y1

	; Cumul = dx \ 2
	; SRL -> RRA
	LD H, D
	LD A, E
	SRL H
	RRA
	LD L, A	; HL <=> Cumul

	; FOR i = dx TO 1
	LD (LINE_4_XOR_COUNT), DE
	LD A, (IY)

_GRAPH_LINE_4_XOR_7

	; 	X1 = X1 + 1
	INC IX
	;	Cumul = cumul + dy
	ADD HL, BC
	;	IF cumul >= dx THEN
	PUSH HL
	SBC HL, DE
	POP HL
	JP c, _GRAPH_LINE_4_XOR_8
	;		Cumul = cumul - dx
	OR A
	SBC HL, DE
	;		Y1 = Y1 + 1
	INC A
	;	END
_GRAPH_LINE_4_XOR_8

	; -----------------------------------------------
	; Affichage du pixel courant
	;
	; Paramètres en entrée de la procédure GRAPH_PIXEL
	;
	; En entrée
	;	BC <=> X sur 16 bits
	;	A  <=> Y sur 8 bits
	;
	;	CALL Pixel (X1, Y1)
	;

	PUSH BC
	PUSH IX
	POP BC
	
	; A contient déjà la valeur courante de Y
	CALL GRAPH_PUT_PIXEL_4_XOR		; Affichage du point en 4 couleurs

	; NEXT i
	OR A
	LD BC, 1
	PUSH HL
	LD HL, (LINE_4_XOR_COUNT)
	SBC HL, BC
	LD (LINE_4_XOR_COUNT), HL
	POP HL
	POP BC
	JP nz, _GRAPH_LINE_4_XOR_7

GRAPH_LINE_4_XOR_END

	POP AF	; Destruction de la pile de travail

	POP IY	; Restauration des registres
	POP IX	;
	POP DE	;
	POP HL	;
	POP BC	;
	POP AF	;
	RET



;**********************************************************************
; Affichage d'une ligne en mode 0 (16 couleurs, 2 pixels par octet)
; en effectuant une opération logique XOR sur les données graphiques
;
; En entrée
;	BC <=> X1
;	HL <=> X2
;	D  <=> Y1
;	E  <=> Y2
; En sortie
;	néant
; Registres affectés
;	aucun
; Remarques
;	Zone d'affichage x1 = 0, x2 = 159, y1 = 0, y2 = 199
;

GRAPH_LINE_16_XOR:

	PUSH AF	; Sauvegarde des registres
	PUSH BC	;
	PUSH HL	;
	PUSH DE	;
	PUSH IX	;
	PUSH IY	;

	; Création de la pile de travail
	PUSH AF		; (SP)     <=> Y1


	; Calcul de la position de la pile de travail
	PUSH HL
	LD HL, 0
	ADD HL, SP
	INC HL
	INC HL
	PUSH HL
	POP IY		; IY Contient l'adresse de base de la pile de travail
	POP HL


	; Echange des valeurs si X1 > à X2 ou Y1 > Y2
	;
	; IF X1 > X2 THEN X1 <=> X2
	; IF Y1 > Y2 THEN Y1 <=> Y2
	;

	;Y
	LD A, D		; Comparaison Y1 avec Y2
	CP E		; (D = Y1, E = Y2)
	JP c, _GRAPH_LINE_16_1_XOR
	LD D, E		; Echange Y1 avec Y2
	LD E, A		;
	 	
_GRAPH_LINE_16_1_XOR

	;X
	OR A		; On efface Carry
	PUSH HL
	SBC HL, BC	; Si inférieur à 0 Carry = 1
	JP nc, _GRAPH_LINE_16_2_XOR
	LD H, B
	LD L, C
	POP BC
	JP _GRAPH_LINE_16_3_XOR

_GRAPH_LINE_16_2_XOR

	POP HL

_GRAPH_LINE_16_3_XOR

	; -----------------------------------------------
	; Affichage du premier pixel
	;
	; Paramètres en entrée de la procédure GRAPH_PIXEL
	;
	; En entrée
	;	BC <=> X sur 16 bits
	;	A  <=> Y sur 8 bits
	;
	;	CALL Pixel (X1, Y1)
	;
	LD A, D	
	CALL GRAPH_PUT_PIXEL_16_XOR		; Affichage du point en 16 couleurs
	

	; Stockage de X1 et de Y1
	PUSH BC		; Récupération de X1 dans IX
	POP IX		;
	LD (IY), D	; Récupération de Y1 dans (IY)

	
	; -----------------------------------------------
	; Calcul de dx et de dy
	;
	; dx = X2 - X1
	; dy = Y2 - Y1
	;
	; HL <=> dx
	; BC <=> dy

	; dx
	OR A		; On efface Carry
	SBC HL, BC
		
	; dy
	LD A, E
	SUB D
	LD B, 0
	LD C, A

	; IF dy > dx THEN
	OR A		; On efface Carry
	PUSH HL
	SBC HL, BC
	POP DE		; DE <=> dx
	JP nc, _GRAPH_LINE_16_6_XOR


	; -----------------------------------------------
	;  	Tracé de la ligne (dy > dx)
	;
	; Rappel de l'affectation des registres
	;
	; HL   <=> Cumul
	; DE   <=> dx
	; BC   <=> dy
	; IX   <=> X1
	; A    <=> Compteur dy
	; (IY) <=> Y1

	; Cumul = dy \ 2
	; SRL -> RRA
	LD H, B
	LD A, C
	SRL H
	RRA
	LD L, A	; HL <=> Cumul

	; FOR i = dy TO 1
	LD A, C

_GRAPH_LINE_16_4_XOR

	; 	Y1 = Y1 + 1
	INC (IY)
	;	Cumul = cumul + dx
	ADD HL, DE
	;	IF cumul >= dy THEN
	PUSH HL
	SBC HL, BC
	POP HL
	JP c, _GRAPH_LINE_16_5_XOR
	;		Cumul = cumul - dy
	SBC HL, BC
	;		X1 = X1 + 1
	INC IX
	;	END
_GRAPH_LINE_16_5_XOR

	; -----------------------------------------------
	; Affichage du pixel courant
	;
	; Paramètres en entrée de la procédure GRAPH_PIXEL
	;
	; En entrée
	;	BC <=> X sur 16 bits
	;	A  <=> Y sur 8 bits
	;
	;	CALL Pixel (X1, Y1)
	;
	
	PUSH AF
	PUSH BC
	PUSH IX
	POP BC
	LD A, (IY)	; Chargement de A avec Y1 à (SP)
	
	CALL GRAPH_PUT_PIXEL_16_XOR		; Affichage du point en 16 couleurs
	POP BC
	POP AF
	
	; NEXT i
	DEC A
	JP nz, _GRAPH_LINE_16_4_XOR
	JP GRAPH_LINE_16_XOR_END


_GRAPH_LINE_16_6_XOR

	; -----------------------------------------------
	;  	Tracé de la ligne (dy <= dx)
	;
	; Rappel de l'affectation des registres
	;
	; HL   <=> Cumul
	; DE   <=> dx
	; BC   <=> dy
	; IX   <=> X1
	; (IY) <=> Y1

	; Cumul = dx \ 2
	; SRL -> RRA
	LD H, D
	LD A, E
	SRL H
	RRA
	LD L, A	; HL <=> Cumul

	; FOR i = dx TO 1
	LD A, E

_GRAPH_LINE_16_7_XOR

	; 	X1 = X1 + 1
	INC IX
	;	Cumul = cumul + dy
	ADD HL, BC
	;	IF cumul >= dx THEN
	PUSH HL
	SBC HL, BC
	POP HL
	JP c, _GRAPH_LINE_16_8_XOR
	;		Cumul = cumul - dx
	SBC HL, DE
	;		Y1 = Y1 + 1
	INC (IY)
	;	END
_GRAPH_LINE_16_8_XOR

	; -----------------------------------------------
	; Affichage du pixel courant
	;
	; Paramètres en entrée de la procédure GRAPH_PIXEL
	;
	; En entrée
	;	BC <=> X sur 16 bits
	;	A  <=> Y sur 8 bits
	;
	;	CALL Pixel (X1, Y1)
	;
	PUSH AF	
	PUSH BC
	PUSH IX
	POP BC
	LD A, (IY)	; Chargement de A avec Y1 à (SP)
	
	CALL GRAPH_PUT_PIXEL_16_XOR	; Affichage du point en 16 couleurs

	POP BC
	POP AF
	
	; NEXT i
	DEC A
	JP nz, _GRAPH_LINE_16_7_XOR
	
GRAPH_LINE_16_XOR_END

	POP AF	; Destruction de la pile de travail

	POP IY	; Restauration des registres
	POP IX	;
	POP DE	;
	POP HL	;
	POP BC	;
	POP AF	;
	RET




;***********************************************************
; Affichage d'un rectangle quelque soit le mode graphique
;
; En entrée
;	BC <=> X1
;	HL <=> X2
;	D  <=> Y1
;	E  <=> Y2
;	A  <=> Couleur de la ligne
; En sortie
;	néant
; Registres affectés
;	aucun
; Remarques
;	- Les modes graphiques supportés sont les modes 0,1 et 2
;

GRAPH_RECTANGLE:

	PUSH AF

	; Vérification du mode graphique en cours
	LD A, CST_GRAPH_VIDEO_MODE
	CP 2
	JP z, _GRAPH_RECTANGLE_2
	CP 1
	JP z, _GRAPH_RECTANGLE_4
	OR A
	JP z, _GRAPH_RECTANGLE_16

	; Retour si le mode graphique est <> 0,1 ou 2
	POP AF
	RET

_GRAPH_RECTANGLE_16

	; Affichage de la ligne horizontale 16 couleurs
	POP AF
	CALL GRAPH_RECTANGLE_16
	RET

_GRAPH_RECTANGLE_4

	; Affichage de la ligne horizontale 4 couleurs
	POP AF
	CALL GRAPH_RECTANGLE_4
	RET

_GRAPH_RECTANGLE_2

	; Affichage de la ligne horizontale 2 couleurs
	POP AF
	CALL GRAPH_RECTANGLE_2
	RET

GRAPH_RECTANGLE_END



;**********************************************************************
; Affichage d'un rectangle en mode 0 (16 couleurs, 2 pixels par octet)
;
; En entrée
;	BC <=> X1
;	HL <=> X2
;	D  <=> Y1
;	E  <=> Y2
;	A  <=> Couleur de la ligne
; En sortie
;	néant
; Registres affectés
;	aucun
; Remarques
;

GRAPH_RECTANGLE_16:

	; Affichage d'une ligne verticale
	;
	; En entrée
	;	D  <=> Y1
	;	E  <=> Y2
	;	BC <=> X
	;	A  <=> Couleur de la ligne
	
	; Affichage d'une ligne horizontale
	;
	; En entrée
	;	BC <=> X1
	;	HL <=> X2
	;	D  <=> Y
	;	A  <=> Couleur de la ligne

	CALL GRAPH_LINE_V_16
	CALL GRAPH_LINE_H_16

	PUSH DE
	LD D, E
	CALL GRAPH_LINE_H_16
	POP DE

	PUSH BC
	LD B, H
	LD C, L
	CALL GRAPH_LINE_V_16
	POP BC

GRAPH_RECTANGLE_16_END

	RET



;**********************************************************************
; Affichage d'un rectangle en mode 1 (4 couleurs, 4 pixels par octet)
;
; En entrée
;	BC <=> X1
;	HL <=> X2
;	D  <=> Y1
;	E  <=> Y2
;	A  <=> Couleur de la ligne
; En sortie
;	néant
; Registres affectés
;	aucun
; Remarques
;

GRAPH_RECTANGLE_4:

	; Affichage d'une ligne verticale
	;
	; En entrée
	;	D  <=> Y1
	;	E  <=> Y2
	;	BC <=> X
	;	A  <=> Couleur de la ligne
	
	; Affichage d'une ligne horizontale
	;
	; En entrée
	;	BC <=> X1
	;	HL <=> X2
	;	D  <=> Y
	;	A  <=> Couleur de la ligne

	CALL GRAPH_LINE_V_4
	CALL GRAPH_LINE_H_4

	PUSH DE
	LD D, E
	CALL GRAPH_LINE_H_4
	POP DE

	PUSH BC
	LD B, H
	LD C, L
	CALL GRAPH_LINE_V_4
	POP BC

GRAPH_RECTANGLE_4_END

	RET




;**********************************************************************
; Affichage d'un rectangle en mode 2 (2 couleurs, 8 pixels par octet)
;
; En entrée
;	BC <=> X1
;	HL <=> X2
;	D  <=> Y1
;	E  <=> Y2
;	A  <=> Couleur de la ligne
; En sortie
;	néant
; Registres affectés
;	aucun
; Remarques
;

GRAPH_RECTANGLE_2:

	; Affichage d'une ligne verticale
	;
	; En entrée
	;	D  <=> Y1
	;	E  <=> Y2
	;	BC <=> X
	;	A  <=> Couleur de la ligne
	
	; Affichage d'une ligne horizontale
	;
	; En entrée
	;	BC <=> X1
	;	HL <=> X2
	;	D  <=> Y
	;	A  <=> Couleur de la ligne

	CALL GRAPH_LINE_V_2
	CALL GRAPH_LINE_H_2

	PUSH DE
	LD D, E
	CALL GRAPH_LINE_H_2
	POP DE

	PUSH BC
	LD B, H
	LD C, L
	CALL GRAPH_LINE_V_2
	POP BC

GRAPH_RECTANGLE_2_END

	RET



;*******************************************************************
; Affichage d'une ligne horizontale quelque soit le mode graphique
;
; En entrée
;	BC <=> X1
;	HL <=> X2
;	D  <=> Y
;	A  <=> Couleur de la ligne
; En sortie
;	néant
; Registres affectés
;	aucun
; Remarques
;	- Les modes graphiques supportés sont les modes 0, 1 et 2 
;

GRAPH_LINE_H:

	PUSH AF		; Sauvegarde de AF pour le retour

	; Vérification du mode graphique en cours
	LD A, CST_GRAPH_VIDEO_MODE
	CP 2
	JP z, _GRAPH_LINE_H_2
	CP 1
	JP z, _GRAPH_LINE_H_4
	OR A
	JP z, _GRAPH_LINE_H_16

	; Retour si le mode graphique est <> 0,1 ou 2
	POP AF
	RET


	; Affichage des pixels
	;
	; En entrée les fonctions possèdent les même paramètres
	;	BC <=> X1
	;	HL <=> X2
	;	D  <=> Y
	;	A  <=> Couleur de la ligne

_GRAPH_LINE_H_16

	; Affichage de la ligne horizontale 16 couleurs
	POP AF
	CALL GRAPH_LINE_H_16
	RET

_GRAPH_LINE_H_4

	; Affichage de la ligne horizontale 4 couleurs
	POP AF
	CALL GRAPH_LINE_H_4
	RET

_GRAPH_LINE_H_2

	; Affichage de la ligne horizontale 2 couleurs
	POP AF
	CALL GRAPH_LINE_H_2
	RET

GRAPH_LINE_H_END




;***********************************************************
; Affichage d'un rectangle quelque soit le mode graphique
;
; En entrée
;	BC <=> X1
;	HL <=> X2
;	D  <=> Y1
;	E  <=> Y2
;	A  <=> Couleur de la ligne
; En sortie
;	néant
; Registres affectés
;	aucun
; Remarques
;	- Les modes graphiques supportés sont les modes 0,1 et 2
;

GRAPH_RECTANGLE_FILLED:

	PUSH AF

	; Vérification du mode graphique en cours
	LD A, CST_GRAPH_VIDEO_MODE
	CP 2
	JP z, _GRAPH_RECTANGLE_FILLED_2
	CP 1
	JP z, _GRAPH_RECTANGLE_FILLED_4
	OR A
	JP z, _GRAPH_RECTANGLE_FILLED_16

	; Retour si le mode graphique est <> 0,1 ou 2
	POP AF
	RET

_GRAPH_RECTANGLE_FILLED_16

	; Affichage de la ligne horizontale 16 couleurs
	POP AF
	CALL GRAPH_RECTANGLE_FILLED_16
	RET

_GRAPH_RECTANGLE_FILLED_4

	; Affichage de la ligne horizontale 4 couleurs
	POP AF
	CALL GRAPH_RECTANGLE_FILLED_4
	RET

_GRAPH_RECTANGLE_FILLED_2

	; Affichage de la ligne horizontale 2 couleurs
	POP AF
	CALL GRAPH_RECTANGLE_FILLED_2
	RET

GRAPH_RECTANGLE_FILLED_END



;*********************************************************************
; Affichage d'un rectangle en mode 0 (16 couleurs 2 pixels par octet)
;
; En entrée
;	BC <=> X1
;	HL <=> X2
;	D  <=> Y1
;	E  <=> Y2
;	A  <=> Couleur de la ligne
; En sortie
;	néant
; Registres affectés
;	aucun
; Remarques
;

GRAPH_RECTANGLE_FILLED_16:

	PUSH AF
	PUSH BC
	PUSH DE
	
	; Calcul de dy
	PUSH AF
	LD A, E		; Y2 = > A
	SUB D		; A = Y2 - Y1
	INC A		; dy = A + 1 (nombre de lignes à traiter)
	LD E, A		;
	POP AF


GRAPH_RECTANGLE_FILLED_16_1
	
	; En entrée
	;	BC <=> X1
	;	HL <=> X2
	;	D  <=> Y
	;	A  <=> Couleur de la ligne
	
	CALL GRAPH_LINE_H_16
	
	INC D		; Y1 = Y1 + 1
	DEC E		; dy = dy - 1
	JP nz, GRAPH_RECTANGLE_FILLED_16_1	; Vérification que toutes les lignes ont été traitées

GRAPH_RECTANGLE_FILLED_16_END

	POP DE
	POP BC
	POP AF
	RET



;*********************************************************************
; Affichage d'un rectangle en mode 1 (4 couleurs 4 pixels par octet)
;
; En entrée
;	BC <=> X1
;	HL <=> X2
;	D  <=> Y1
;	E  <=> Y2
;	A  <=> Couleur de la ligne
; En sortie
;	néant
; Registres affectés
;	aucun
; Remarques
;

GRAPH_RECTANGLE_FILLED_4:

	PUSH AF
	PUSH BC
	PUSH DE

	; Calcul de dy
	PUSH AF
	LD A, E		; Y2 = > A
	SUB D		; A = Y2 - Y1
	INC A		; dy = A + 1 (nombre de lignes à traiter)
	LD E, A		;
	POP AF

GRAPH_RECTANGLE_FILLED_4_1

	; En entrée
	;	BC <=> X1
	;	HL <=> X2
	;	D  <=> Y
	;	A  <=> Couleur de la ligne
	CALL GRAPH_LINE_H_4

	INC D		; Y1 = Y1 + 1
	DEC E		; dy = dy - 1
	JP nz, GRAPH_RECTANGLE_FILLED_4_1	; Vérification que toutes les lignes ont été traitées

GRAPH_RECTANGLE_FILLED_4_END

	POP DE
	POP BC
	POP AF
	RET



;*********************************************************************
; Affichage d'un rectangle en mode 2 (2 couleurs 8 pixels par octet)
;
; En entrée
;	BC <=> X1
;	HL <=> X2
;	D  <=> Y1
;	E  <=> Y2
;	A  <=> Couleur de la ligne
; En sortie
;	néant
; Registres affectés
;	aucun
; Remarques
;

GRAPH_RECTANGLE_FILLED_2:

	PUSH AF
	PUSH BC
	PUSH DE

	; Calcul de dy
	PUSH AF
	LD A, E		; Y2 = > A
	SUB D		; A = Y2 - Y1
	INC A		; dy = A + 1 (nombre de lignes à traiter)
	LD E, A		;
	POP AF

GRAPH_RECTANGLE_FILLED_2_1

	; En entrée
	;	BC <=> X1
	;	HL <=> X2
	;	D  <=> Y
	;	A  <=> Couleur de la ligne
	CALL GRAPH_LINE_H_2

	INC D		; Y1 = Y1 + 1
	DEC E		; dy = dy - 1
	JP nz, GRAPH_RECTANGLE_FILLED_2_1	; Vérification que toutes les lignes ont été traitées

GRAPH_RECTANGLE_FILLED_2_END

	POP DE
	POP BC
	POP AF
	RET





;********************************************************
; Affichage d'une ligne horizontale en mode 2 (2 couleurs)
;
; En entrée
;	BC <=> X1
;	HL <=> X2
;	D  <=> Y
;	A  <=> Couleur de la ligne
; En sortie
;	néant
; Registres affectés
;	aucun
; Remarques
;
;

GRAPH_LINE_H_2:

	PUSH AF		; Sauvegarde des registres
	PUSH BC		;
	PUSH DE		;    AF,BC,DE,HL,IX, IY
	PUSH HL		;
	PUSH IX		;
	PUSH IY		;

	
	; Calcul de Dx (nombre de points à traiter)
	AND 1		; Préservation du bit 0 pour ne traiter que les couleur 0 ou 1
	LD E, A		; La couleur dans E
	RLA		; On efface Carry
	SBC HL, BC	; HL = X2 - X1
	PUSH HL		; Sauvegarde du nombre de points restant à traiter


	; Adresse du premier pixel
	;
	; En entrée
	;	BC <=> X1
	;	A  <=> Y
	; En sortie
	;	HL <=> Adresse du point
	;
	; BC est déjà chargé avec sa valeur
	;
	LD A, D		; Y dans D
			;
	CALL GRAPH_ADR_OF_PIXEL
	PUSH HL		; On stocke HL dans IX pour accéder à la mémoire écran
	POP IX		;
	POP HL		; Restauration du nombre de points à traiter dans HL


	; Préparation des masques logiques en fonction du n° de la couleur
	LD D, 0		; On efface D
	LD IY, DEF_GRAPH_TABLE_PIXEL_2	; Référence à la table des masques 16 couleurs
	ADD IY, DE


	; Vérification à partir de quel pixel doit commencer le tracé
	LD A, C		; C contient la partie base de X1
	AND 7		; On ne préserve que les 7 premiers bits qui correspondent au n° du point
	LD C, A		; Calcul du nombre de pixel restant à traiter, inclu le premier pixel
	LD A, 8		;
	SUB C		;	[Nombre de pixele à traiter] = 8 - [n° du pixel]
	LD B, A		;
	LD A, C		; Nombre de déclages a effectuer pour calculer les masques logiques associés au premier pixel


	; Décalages des masques vers le bas en fonction du n° du pixel concerné
	;
	; Paramètres de la fonction MATH_SRL_8
	; 	En entrée
	;		E  <=> Entier de 8 bits
	;		A  <=> Nombre de bits à décaler
	; 	En sortie
	;		E <=> Résultat du décalage des n bits
	;
	; A et E sont chargés avec leur valeur respective
	LD E, (IY)	; Masque logique associé à la couleur entrelacée dans B

	CALL MATH_SRL_8 ; Décalage du masque de la couleur entrelacée, associée à la couleur du pixel
			; En sortie E contient le masque de la valeur entrelacée associé à la couleur du pixel
	LD D, E		; Sauvegarde du masque entrelacé de la couleur dans D

	; A est déjà chargé avec le nombre de décalages
	LD E, 128	; Valeur par défaut du masque logique qui va permettre de préserver
			; le pixel voisin, en Mode 2 = 128 <=> %10000000
	CALL MATH_SRL_8 ; Décalage du masque négatif qui permet de préserver le pixel voisin

	; Inversion du masque logique négatif de manière à préserver les données du pixel voisin
	LD A, E		; Inversion du masque pour la préservations des pixels voisins
	CPL		;
	LD C, A		; C va contenir le masque logique inversé qui permet la préservation les pixels voisins

_GRAPH_LINE_H_2_1

	; Affichage du pixel courant
	LD E, (IX)

_GRAPH_LINE_H_2_2

	LD A, E		; Copie des données de l'octet courant dans A pour taitements
	AND C		; Préservation des données du pixel voisin
	OR D		; Affichage du nouveau pixel
	LD E, A		; Sauvegarde des données de l'octet graphique courant
	
	LD A, L		; On teste si tous les points on été traités
	OR H		;
	JP z, _GRAPH_LINE_H_2_END
	DEC HL		; On décrémente le nombre de points restant à traiter
	DJNZ _GRAPH_LINE_H_2_3

	LD (IX), E	; Affichage de l'octet courant
	LD B, 8
	INC IX		; Points suivant

	RRC D
	RRC C

	JP _GRAPH_LINE_H_2_1

_GRAPH_LINE_H_2_3

	RRC D
	RRC C

	JP _GRAPH_LINE_H_2_2

_GRAPH_LINE_H_2_END

	LD (IX), E	; Affichage du dernier octet traité

	POP IY		; Restauration des registres
	POP IX		;
	POP HL		;     AF,BC,DE,HL,IX,IY
	POP DE		;
	POP BC		;
	POP AF		;
	RET




;********************************************************
; Affichage d'une ligne horizontale en mode 1 (4 couleurs)
;
; En entrée
;	BC <=> X1
;	HL <=> X2
;	D  <=> Y
;	A  <=> Couleur de la ligne
; En sortie
;	néant
; Registres affectés
;	aucun
; Remarques
;
;

GRAPH_LINE_H_4:

	PUSH AF		; Sauvegarde des registres
	PUSH BC		;
	PUSH DE		;    AF,BC,DE,HL,IX, IY
	PUSH HL		;
	PUSH IX		;
	PUSH IY		;

	
	; Calcul de Dx (nombre de points à traiter)
	AND 3		; Préservation des deux premiers bits de A de manière à ne permettre que les couleurs de 0 à 3
	LD E, A		; La couleur dans E
	RLA		; On efface Carry
	SBC HL, BC	; HL = X2 - X1
	PUSH HL		; Sauvegarde du nombre de points restant à traiter


	; Adresse du premier pixel
	;
	; En entrée
	;	BC <=> X1
	;	A  <=> Y
	; En sortie
	;	HL <=> Adresse du point
	;
	; BC est déjà chargé avec sa valeur
	;
	LD A, D		; Y dans D
			;
	CALL GRAPH_ADR_OF_PIXEL
	PUSH HL		; On stocke HL dans IX pour accéder à la mémoire écran
	POP IX		;
	POP HL		; Restauration du nombre de points à traiter dans HL


	; Préparation des masques logiques en fonction du n° de la couleur
	LD D, 0		; On efface D
	LD IY, DEF_GRAPH_TABLE_PIXEL_4	; Référence à la table des masques 16 couleurs
	ADD IY, DE


	; Vérification à partir de quel pixel doit commencer le tracé
	LD A, C		; C contient la partie base de X1
	AND 3		; On ne préserve que les 3 premiers bits qui correspondent au n° du point
	LD C, A		; Calcul du nombre de pixel restant à traiter, inclu le premier pixel
	LD A, 4		;
	SUB C		;	[Nombre de pixele à traiter] = 4 - [n° du pixel]
	LD B, A		;
	LD A, C		; Nombre de déclages a effectuer pour calculer les masques logiques associés au premier pixel


	; Décalages des masques vers le bas en fonction du n° du pixel concerné
	;
	; Paramètres de la fonction MATH_SRL_8
	; 	En entrée
	;		E  <=> Entier de 8 bits
	;		A  <=> Nombre de bits à décaler
	; 	En sortie
	;		E <=> Résultat du décalage des n bits
	;
	; A et E sont chargés avec leur valeur respective
	LD E, (IY)	; Masque logique associé à la couleur entrelacée dans B

	CALL MATH_SRL_8 ; Décalage du masque de la couleur entrelacée, associée à la couleur du pixel
			; En sortie E contient le masque de la valeur entrelacée associé à la couleur du pixel
	LD D, E		; Sauvegarde du masque entrelacé E

	; A est déjà chargé avec le nombre de décalages
	LD E, 136	; Valeur par défaut du masque logique qui va permettre de préserver
			; le pixel voisin, en Mode 1 = 136 <=> %10001000
	CALL MATH_SRL_8 ; Décalage du masque négatif qui permet de préserver le pixel voisin

	; Inversion du masque logique négatif de manière à préserver les données du pixel voisin
	LD A, E		; Inversion du masque pour la préservations des pixels voisins
	CPL		;
	LD C, A		;

_GRAPH_LINE_H_4_1

	; Affichage du pixel courant
	LD E, (IX)

_GRAPH_LINE_H_4_2

	LD A, E
	AND C		; Préservation des données du pixel voisin
	OR D		; Affichage du nouveau pixel
	LD E, A

	LD A, L		; On teste si tous les points on été traités
	OR H		;
	JP z, _GRAPH_LINE_H_4_END
	DEC HL		; On décrémente le nombre de points restant à traiter
	DJNZ _GRAPH_LINE_H_4_3

	LD (IX), E	; Affichage de l'octet courant 
	INC IX		; Point suivant
	LD B, 4		; Points suivants

	LD D, (IY)	; Masque logique associé à la couleur entrelacée dans B
	RRC C		; Déclage du masque logique qui permet la préservation des données des pixels voisins
	JP _GRAPH_LINE_H_4_1

_GRAPH_LINE_H_4_3

	RRC C		; Décalages des masques logiques pour traiter les points suivants
	RRC D		;
	JP _GRAPH_LINE_H_4_2

_GRAPH_LINE_H_4_END

	LD (IX), E	; Affichage du dernier octet traité

	POP IY		; Restauration des registres
	POP IX		;
	POP HL		;     AF,BC,DE,HL,IX,IY
	POP DE		;
	POP BC		;
	POP AF		;
	RET




;********************************************************
; Affichage d'une ligne horizontale en mode 0 (16 couleurs)
;
; En entrée
;	BC <=> X1
;	HL <=> X2
;	D  <=> Y
;	A  <=> Couleur de la ligne
; En sortie
;	néant
; Registres affectés
;	aucun
; Remarques
;
;

GRAPH_LINE_H_16:

	PUSH AF		; Sauvegarde des registres
	PUSH BC		;
	PUSH DE		;     AF,BC,DE,HL,IX,IY
	PUSH HL		;
	PUSH IX		;
	PUSH IY		;

	; Calcul de Dx (nombre de points à traiter)
	AND %1111	; Préservation des 4 premiers bits de A de manière à ne permettre que les couleurs de 0 à 15
	LD E, A		; La couleur dans E
	RLA		; On efface Carry
	SBC HL, BC	; HL = X2 - X1
	PUSH HL		; Sauvegarde du nombre de points restant à traiter

	; Adresse du premier pixel
	;
	; En entrée
	;	BC <=> X1
	;	A  <=> Y
	; En sortie
	;	HL <=> Adresse du point
	;
	LD A, D		; Y (D) dans A
			; BC contient déjà X1
	CALL GRAPH_ADR_OF_PIXEL

	PUSH HL
	POP IX
	POP HL
	

	; Préparation des masques logiques en fonction du n° de la couleur
	LD A, D		; Sauvegarde de Y dans A
	LD D, 0		; On efface D
	LD IY, DEF_GRAPH_TABLE_PIXEL_16	; Référence à la table des masques 16 couleurs
	ADD IY, DE
	LD E, (IY)	; Masque logique associé à la couleur entrelacée dans B
	LD D, 85	; Masque logique permettant de préserver le pixel voisin dans D (%01010101
			; (voir affichage d'un pixel en mode 0)

	; Décalage des masques en fonction du nombre de points déjà traités
	LD B, 2
	LD A, C
	AND 1
	OR A
	JP z, _GRAPH_LINE_H_16_1

	DEC B
	SRL E
	RLC D

_GRAPH_LINE_H_16_1

	; Affichage du pixel courant
	LD C, (IX)

_GRAPH_LINE_H_16_2

	LD A, C
	AND D		; Préservation des données du pixel voisin
	OR E		; Affichage du nouveau pixel
	LD C, A
	
	LD A, L		; On teste si tous les points on été traités
	OR H		;
	JP z, _GRAPH_LINE_H_16_END
	DEC HL		; On décrémente le nombre de points restant à traiter
	DJNZ _GRAPH_LINE_H_16_3

	LD (IX), C	; Affichage de l'octet graphique courant
	INC IX		; Point suivant
	LD B, 2		;

	LD E, (IY)	; Masque logique associé à la couleur entrelacée dans B
	RLC D		; Déclage du masque logique qui permet la préservation des données voisines du point courant
	JP _GRAPH_LINE_H_16_1

_GRAPH_LINE_H_16_3

	SRL E		; Décalage du masque de la couleur
	RLC D		; Décalage du masque de préservation des données voisines
	JP _GRAPH_LINE_H_16_2

_GRAPH_LINE_H_16_END

	LD (IX), C	; Affichage du dernier octet

	POP IY		; Restauration des registres
	POP IX		;
	POP HL		;     AF,BC,DE,HL,IX,IY
	POP DE		;
	POP BC		;
	POP AF		;
	RET






;*******************************************************************
; Affichage d'une ligne horizontale quelque soit le mode graphique
; en effectuant une opération logique XOR sur les données graphiques
;
; En entrée
;	BC <=> X1
;	HL <=> X2
;	D  <=> Y
; En sortie
;	néant
; Registres affectés
;	aucun
; Remarques
;	- Les modes graphiques supportés sont les modes 0, 1 et 2 
;

GRAPH_LINE_H_XOR:

	PUSH AF		; Sauvegarde de AF pour le retour

	; Vérification du mode graphique en cours
	LD A, CST_GRAPH_VIDEO_MODE
	CP 2
	JP z, _GRAPH_LINE_H_2_XOR
	CP 1
	JP z, _GRAPH_LINE_H_4_XOR
	OR A
	JP z, _GRAPH_LINE_H_16_xOR

	; Retour si le mode graphique est <> 0,1 ou 2
	POP AF
	RET


	; Affichage des pixels
	;
	; En entrée les fonctions possèdent les même paramètres
	;	BC <=> X1
	;	HL <=> X2
	;	D  <=> Y

_GRAPH_LINE_H_16_XOR

	; Affichage de la ligne horizontale 16 couleurs
	POP AF
	CALL GRAPH_LINE_H_16_XOR
	RET

_GRAPH_LINE_H_4_XOR

	; Affichage de la ligne horizontale 4 couleurs
	POP AF
	CALL GRAPH_LINE_H_4_XOR
	RET

_GRAPH_LINE_H_2_XOR

	; Affichage de la ligne horizontale 2 couleurs
	POP AF
	CALL GRAPH_LINE_H_2_XOR
	RET

GRAPH_LINE_H_XOR_END



;********************************************************
; Affichage d'une ligne horizontale en mode 2 (2 couleurs)
; et d'effectuer un OU exclusif sur les données graphique
; déjà présentes
;
; En entrée
;	BC <=> X1
;	HL <=> X2
;	D  <=> Y
; En sortie
;	néant
; Registres affectés
;	aucun
; Remarques
;
;

GRAPH_LINE_H_2_XOR:

	PUSH AF		; Sauvegarde des registres
	PUSH BC		;
	PUSH DE		;    AF,BC,DE,HL,IX, IY
	PUSH HL		;
	PUSH IX		;


	; Calcul de Dx (nombre de points à traiter)
	RLA		; On efface Carry
	SBC HL, BC	; HL = X2 - X1
	PUSH HL		; Sauvegarde du nombre de points restant à traiter


	; Adresse du premier pixel
	;
	; En entrée
	;	BC <=> X1
	;	A  <=> Y
	; En sortie
	;	HL <=> Adresse du point
	;
	; BC est déjà chargé avec sa valeur
	;
	LD A, D		; Y dans D
			;
	CALL GRAPH_ADR_OF_PIXEL
	PUSH HL		; On stocke HL dans IX pour accéder à la mémoire écran
	POP IX		;
	POP HL		; Restauration du nombre de points à traiter dans HL


	; Vérification à partir de quel pixel doit commencer le tracé
	LD A, C		; C contient la partie base de X1
	AND 7		; On ne préserve que les 7 premiers bits qui correspondent au n° du point
	LD C, A		; Calcul du nombre de pixel restant à traiter, inclu le premier pixel
	LD A, 8		;
	SUB C		;	[Nombre de pixele à traiter] = 8 - [n° du pixel]
	LD B, A		;
	LD A, C		; Nombre de déclages a effectuer pour calculer les masques logiques associés au premier pixel


	; Décalages des masques vers le bas en fonction du n° du pixel concerné
	;
	; Paramètres de la fonction MATH_SRL_8
	; 	En entrée
	;		E  <=> Entier de 8 bits
	;		A  <=> Nombre de bits à décaler
	; 	En sortie
	;		E <=> Résultat du décalage des n bits
	;
	; A est déjà chargé avec le nombre de décalages
	LD E, 128	; Valeur par défaut du masque logique qui va permettre de préserver
			; le pixel voisin, en Mode 2 = 128 <=> %10000000
	CALL MATH_SRL_8 ; Décalage du masque négatif qui permet de préserver le pixel voisin

_GRAPH_LINE_H_2_XOR_1

	; Affichage du pixel courant
	LD D, (IX)

_GRAPH_LINE_H_2_XOR_2

	LD A, D		; Copie des données de l'octet courant dans A pour taitements
	XOR E		; On applique le OU exclusif sur le point de l'octet graphique courant
	LD D, A		; Sauvegarde des données de l'octet graphique courant
	
	LD A, L		; On teste si tous les points on été traités
	OR H		;
	JP z, _GRAPH_LINE_H_2_XOR_END
	DEC HL		; On décrémente le nombre de points restant à traiter
	DJNZ _GRAPH_LINE_H_2_XOR_3

	LD (IX), D	; Affichage de l'octet courant
	LD B, 8
	INC IX		; Points suivant

	RRC E		; Déclage du masque logique du point courant
	JP _GRAPH_LINE_H_2_XOR_1

_GRAPH_LINE_H_2_XOR_3

	RRC E		; Décalage du masque logique du point courant
	JP _GRAPH_LINE_H_2_XOR_2

_GRAPH_LINE_H_2_XOR_END

	LD (IX), D	; Affichage du dernier octet traité

	POP IX		;
	POP HL		;     AF,BC,DE,HL,IX,IY
	POP DE		;
	POP BC		;
	POP AF		;
	RET






;********************************************************
; Affichage d'une ligne horizontale en mode 1 (4 couleurs)
; et d'effectuer un OU exclusif sur les données
;
; En entrée
;	BC <=> X1
;	HL <=> X2
;	D  <=> Y
; En sortie
;	néant
; Registres affectés
;	aucun
; Remarques
;
;

GRAPH_LINE_H_4_XOR:

	PUSH AF		; Sauvegarde des registres
	PUSH BC		;
	PUSH DE		;    AF,BC,DE,HL,IX
	PUSH HL		;
	PUSH IX		;
	
	; Calcul de Dx (nombre de points à traiter)
	RLA		; On efface Carry
	SBC HL, BC	; HL = X2 - X1
	PUSH HL		; Sauvegarde du nombre de points restant à traiter


	; Adresse du premier pixel
	;
	; En entrée
	;	BC <=> X1
	;	A  <=> Y
	; En sortie
	;	HL <=> Adresse du point
	;
	; BC est déjà chargé avec sa valeur
	;
	LD A, D		; Y dans D
			;
	CALL GRAPH_ADR_OF_PIXEL
	PUSH HL		; On stocke HL dans IX pour accéder à la mémoire écran
	POP IX		;
	POP HL		; Restauration du nombre de points à traiter dans HL


	; Vérification à partir de quel pixel doit commencer le tracé
	LD A, C		; C contient la partie base de X1
	AND 3		; On ne préserve que les 3 premiers bits qui correspondent au n° du point
	LD C, A		; Calcul du nombre de pixel restant à traiter, inclu le premier pixel
	LD A, 4		;
	SUB C		;	[Nombre de pixele à traiter] = 4 - [n° du pixel]
	LD B, A		;
	LD A, C		; Nombre de déclages a effectuer pour calculer les masques logiques associés au premier pixel


	; Décalages des masques vers le bas en fonction du n° du pixel concerné
	;
	; Paramètres de la fonction MATH_SRL_8
	; 	En entrée
	;		E  <=> Entier de 8 bits
	;		A  <=> Nombre de bits à décaler
	; 	En sortie
	;		E <=> Résultat du décalage des n bits
	;
	; A et E sont chargés avec leur valeur respective
	LD E, 136	; Valeur par défaut du masque logique qui va permettre de préserver
			; le pixel voisin, en Mode 1 = 136 <=> %10001000
	CALL MATH_SRL_8 ; Décalage du masque négatif qui permet de préserver le pixel voisin

_GRAPH_LINE_H_4_XOR_1

	; Affichage du pixel courant
	LD D, (IX)

_GRAPH_LINE_H_4_XOR_2

	LD A, D		; D dans A pour traitements sur l'octet graphique courant
	XOR E		; Notre OU esclusif
	LD D, A		; Sauvegarde des modifications dans D

	LD A, L		; On teste si tous les points on été traités
	OR H		;
	JP z, _GRAPH_LINE_H_4_XOR_END
	DEC HL		; On décrémente le nombre de points restant à traiter
	DJNZ _GRAPH_LINE_H_4_XOR_3

	LD (IX), D	; Affichage de l'octet courant 
	INC IX		; Point suivant
	LD B, 4		;

	RRC E		; Déclage du masque logique associé aux données du pixel courant
	JP _GRAPH_LINE_H_4_XOR_1

_GRAPH_LINE_H_4_XOR_3

	RRC E		; Déclage du masque logique associé aux données du pixel courant
	JP _GRAPH_LINE_H_4_XOR_2

_GRAPH_LINE_H_4_XOR_END

	LD (IX), D	; Affichage du dernier octet traité

	POP IX		;
	POP HL		;     AF,BC,DE,HL,IX
	POP DE		;
	POP BC		;
	POP AF		;
	RET






;********************************************************
; Affichage d'une ligne horizontale en mode 0 (16 couleurs)
; en effectuant un OU exclusif sur les données graphiques
;
; En entrée
;	BC <=> X1
;	HL <=> X2
;	D  <=> Y
; En sortie
;	néant
; Registres affectés
;	aucun
; Remarques
;
;

GRAPH_LINE_H_16_XOR:

	PUSH AF		; Sauvegarde des registres
	PUSH BC		;
	PUSH DE		;     AF,BC,DE,HL,IX
	PUSH HL		;
	PUSH IX		;
	
	; Calcul de Dx (nombre de points à traiter)
	RLA		; On efface Carry
	SBC HL, BC	; HL = X2 - X1
	PUSH HL		; Sauvegarde du nombre de points restant à traiter

	; Adresse du premier pixel
	;
	; En entrée
	;	BC <=> X1
	;	A  <=> Y
	; En sortie
	;	HL <=> Adresse du point
	;
	LD A, D		; Y (D) dans A
			; BC contient déjà X1
	CALL GRAPH_ADR_OF_PIXEL

	PUSH HL
	POP IX
	POP HL
	
	; Masque utilisé pour effectuer le XOR
	LD D, 170	; Masque logisque de préservation des données du point courant (%10101010)

	; Décalage des masques en fonction du nombre de points déjà traités
	LD B, 2 
	LD A, C
	AND 1
	OR A
	JP z, _GRAPH_LINE_H_16_1_XOR

	DEC B	; Déclémentation du nombre de point à traiter
	RRC D	; Rotation du masque logique de préservation des données

_GRAPH_LINE_H_16_1_XOR

	LD C, (IX)	; Sauvegarde de données de l'octet graphique courant

_GRAPH_LINE_H_16_2_XOR

	LD A, C		; Transfert de l'octet graphoque pour taitement
	XOR D		; Notre OU exclusif via le masque logique
	LD C, A		; Sauvegarde du résultat dans C
	
	LD A, L		; On teste si tous les points on été traités
	OR H		;
	JP z, _GRAPH_LINE_H_16_XOR_END
	DEC HL		; On décrémente le nombre de points restant à traiter
	DJNZ _GRAPH_LINE_H_16_3_XOR

	LD (IX), C	; Affichage de l'octet graphique courant
	INC IX		; Point suivant
	LD B, 2		;

	RRC D		; Déclage du masque logique qui permet d'effectuer un OU exclusif sur les données graphiques
	JP _GRAPH_LINE_H_16_1_XOR

_GRAPH_LINE_H_16_3_XOR

	RRC D		; Déclage du masque logique qui permet d'effectuer un OU exclusif sur les données graphiques
	JP _GRAPH_LINE_H_16_2_XOR

_GRAPH_LINE_H_16_XOR_END

	LD (IX), C	; Affichage du dernier octet

	POP IX		;
	POP HL		;     AF,BC,DE,HL,IX
	POP DE		;
	POP BC		;
	POP AF		;
	RET









;*****************************************************************
; Affichage d'une ligne verticale quelque soit le mode graphique
;
; En entrée
;	D  <=> Y1
;	E  <=> Y2
;	BC <=> X
;	A  <=> Couleur de la ligne
; En sortie
;	néant
; Registres affectés
;	aucun
; Remarques
;	- Les modes graphiques supportés sont les 0,1 et 2
;

GRAPH_LINE_V:

	PUSH AF		; Sauvegarde de AF pour le retour

	; Vérification du mode graphique en cours
	LD A, CST_GRAPH_VIDEO_MODE
	CP 2
	JP z, _GRAPH_LINE_V_2
	CP 1
	JP z, _GRAPH_LINE_V_4
	OR A
	JP z, _GRAPH_LINE_V_16

	; Retour si le mode graphique est <> 0,1 ou 2
	POP AF
	RET


	; Affichage des pixels
	;
	; En entrée les fonctions possèdent les même paramètres
	;	D  <=> Y1
	;	E  <=> Y2
	;	BC <=> X
	;	A  <=> Couleur de la ligne

_GRAPH_LINE_V_16

	; Affichage de la ligne horizontale 16 couleurs
	POP AF
	CALL GRAPH_LINE_V_16
	RET

_GRAPH_LINE_V_4

	; Affichage de la ligne horizontale 4 couleurs
	POP AF
	CALL GRAPH_LINE_V_4
	RET

_GRAPH_LINE_V_2

	; Affichage de la ligne horizontale 2 couleurs
	POP AF
	CALL GRAPH_LINE_V_2
	RET

GRAPH_LINE_V_END






;********************************************************
; Affichage d'une ligne verticale en mode 2 (2 couleurs)
;
; En entrée
;	D  <=> Y1
;	E  <=> Y2
;	BC <=> X
;	A  <=> Couleur de la ligne
; En sortie
;	néant
; Registres affectés
;	aucun
; Remarques
;
;

GRAPH_LINE_V_2:

	PUSH AF		; Sauvegarde des registres
	PUSH BC		;
	PUSH DE		;	AF,BC,DE,HL,IX
	PUSH HL		;
	PUSH IX		;


	; Adresse du premier pixel
	;
	; En entrée
	;	BC <=> X
	;	A  <=> Y1
	; En sortie
	;	HL <=> Adresse du point
	;
	PUSH DE		; On préserve Y1 et Y2
	AND 1		; Préservation du bit 0 pour ne permettre que les couleurs 0 ou 1
	LD E, A		; La couleur dans E
	LD A, D		; Y1 dans A

	CALL GRAPH_ADR_OF_PIXEL
	LD A, C		; La partie basse de X dans A
	POP BC		; Restauration de Y1 et Y2 dans BC

	; Préparation des masques logiques en fonction du n° de la couleur
	LD D, 0
	LD IX, DEF_GRAPH_TABLE_PIXEL_2		; Référence à la table des masques 4 couleurs
	ADD IX, DE
	LD E, (IX)	; Masque logique associé à la couleur entrelacée dans B


	; X se trouve actuellement dans A, on ne préserve que les 3 premiers bits de manière à savoir de combien de bits
	; doivent être déclalés les masques logiques
	AND 7


	; Décalages des masques vers le bas en fonction du n° du pixel concerné
	;
	; Paramètres de la fonction MATH_SRL_8
	; 	En entrée
	;		E  <=> Entier de 8 bits
	;		A  <=> Nombre de bits à décaler
	; 	En sortie
	;		E <=> Résultat du décalage des n bits
	;
	; A et E sont déjà chargés avec leur valeur respective

	CALL MATH_SRL_8 ; Décalage du masque de la couleur entrelacée, associée à la couleur du pixel
			; En sortie E contient le masque de la valeur entrelacée associé à la couleur du pixel
	LD D, E		; Sauvegarde de E

	; A est déjà chargé avec le nombre de décalages
	LD E, 128	; X AND 7 = n° du pixel courant, A contient donc le nombre de bits à décaler.
			; en Mode 2 le masque = 128 <=> %10001000
	CALL MATH_SRL_8 ; Décalage du masque négatif qui permet de préserver le pixel voisin


	; Inversion du masque logique négatif de manière à préserver les données du pixel voisin
	LD A, E
	CPL
	LD E, D		; Restauration de E qui doit contenir le masque entrelacé lié à la couleur du pixel
	LD D, A		; D va contenir le masque logique permettant la préservation du pixel voisin


_GRAPH_LINE_V_2_1:

	; Calcul du nombre de points à traiter
	;
	; En entrée
	;	B <=> Y1
	;	C <=> Y2
	;
	LD A, C
	SUB B
	LD C, A		; Le nombre de points à traiter dans C

	; Calcul du nombre de lignes restant à traiter dans la série courante (Une série = 8 lignes)
	LD A, B		; B = Y1
	AND 7		; On ne garde que les 3 derniers bits
	LD B, A		;
	LD A, 8		; Le nombre de lignes restantes à traiter dans la série courante
	SUB B		;    = 8 - le nombre de lignes déjà traitées
	LD B, A		; Le nombre de lignes restant à traiter dans B

	; Valeur par défaut pour l'incrémentation de l'adresse mémoire contenue dans HL
	;	&800  <=> Permet de passer à la ligne suivante
	;	&50   <=> Permet de passer à la série de lignes suivante
	;	&4000 <=> Permet d'ajuster HL en fonction d'une série complète de lignes
	; 		  = [nombre de lignes dans une série] * &800
	; 	&3FB0 <=> = Espace d'adressage d'une série complète de lignes - Offset pour la série de lignes suivantes
	;		  = &4000 - &50
	; 	       => HL = HL - &4000 + &50
	;	
	LD IX, 0	; Sauvegarde de l'adresse de la pile
	ADD IX, SP	;
	
	
_GRAPH_LINE_V_2_2

	; Affichage du pixel
	LD A, (HL)
	AND D		; Préservation des données du pixel voisin
	OR E		; Affichage du nouveau pixel
	LD (HL), A
	
	; Test pour voir si tous les points ont été traités
	LD A, C
	OR A
	JP z, _GRAPH_LINE_V_2_END

	; Vérification si l'on a atteint une fin de série de lignes (série toutes les 8 lignes)
	DJNZ _GRAPH_LINE_V_2_3

	LD SP, &3FB0	; &3FB0 = &4000 - &50 = Espace d'adressage d'une série complète de lignes - Offset pour la série de lignes suivantes
	SBC HL, SP	;       => HL = HL - &4000 + &50
			;
	LD B, 8 	; On va traiter une nouvelle série de 8 lignes

_GRAPH_LINE_V_2_3

	LD SP, &800	; Passage à la ligne suivante (HL = HL + &800)
	ADD HL, SP	;
	DEC C		; Décrémentation de C qui contient le nombre de points à traiter
	JP _GRAPH_LINE_V_2_2

_GRAPH_LINE_V_2_END

	LD SP, IX	; Restauration de l'adresse de la pile

	POP IX		; Restauration des registres
	POP HL		; 
	POP DE		;	AF,BC,DE,HL,IX
	POP BC		;
	POP AF		;
	RET





;********************************************************
; Affichage d'une ligne verticale en mode 1 (4 couleurs)
;
; En entrée
;	D  <=> Y1
;	E  <=> Y2
;	BC <=> X
;	A  <=> Couleur de la ligne
; En sortie
;	néant
; Registres affectés
;	aucun
; Remarques
;
;

GRAPH_LINE_V_4:

	PUSH AF		; Sauvegarde des registres
	PUSH BC		;
	PUSH DE		;	AF,BC,DE,HL,IX
	PUSH HL		;
	PUSH IX		;


	; Adresse du premier pixel
	;
	; En entrée
	;	BC <=> X
	;	A  <=> Y1
	; En sortie
	;	HL <=> Adresse du point
	;
	PUSH DE		; On préserve Y1 et Y2
	AND 3		; Préservation des trois premiers bits de A  pour ne permettre que les couleurs de 0 à 3
	LD E, A
	LD A, D		; Y1 dans A

	CALL GRAPH_ADR_OF_PIXEL
	LD A, C		; La partie basse de X dans A
	POP BC		; Restauration de Y1 et Y2 dans BC

	; Préparation des masques logiques en fonction du n° de la couleur
	LD D, 0
	LD IX, DEF_GRAPH_TABLE_PIXEL_4		; Référence à la table des masques 4 couleurs
	ADD IX, DE
	LD E, (IX)	; Masque logique associé à la couleur entrelacée dans B


	; X se trouve actuellement dans A, on ne préserve que les 2 premiers bits de manière à savoir de combien de bits
	; doivent être déclalés les masques logiques
	AND 3


	; Décalages des masques vers le bas en fonction du n° du pixel concerné
	;
	; Paramètres de la fonction MATH_SRL_8
	; 	En entrée
	;		E  <=> Entier de 8 bits
	;		A  <=> Nombre de bits à décaler
	; 	En sortie
	;		E <=> Résultat du décalage des n bits
	;
	; A et E sont déjà chargés avec leur valeur respective

	CALL MATH_SRL_8 ; Décalage du masque de la couleur entrelacée, associée à la couleur du pixel
			; En sortie E contient le masque de la valeur entrelacée associé à la couleur du pixel
	LD D, E		; Sauvegarde de E

	; A est déjà chargé avec le nombre de décalages
	LD E, 136	; Valeur par défaut du masque logique qui va permettre de préserver
			; le pixel voisin, en Mode 1 = 136 <=> %10001000
	CALL MATH_SRL_8 ; Décalage du masque négatif qui permet de préserver le pixel voisin


	; Inversion du masque logique négatif de manière à préserver les données du pixel voisin
	LD A, E
	CPL
	LD E, D		; Restauration de E qui doit contenir le masque entrelacé lié à la couleur du pixel
	LD D, A		; D va contenir le masque logique permettant la préservation du pixel voisin


_GRAPH_LINE_V_4_1:

	; Calcul du nombre de points à traiter
	;
	; En entrée
	;	B <=> Y1
	;	C <=> Y2
	;
	LD A, C
	SUB B
	LD C, A		; Le nombre de points à traiter dans C

	; Calcul du nombre de lignes restant à traiter dans la série courante (Une série = 8 lignes)
	LD A, B		; B = Y1
	AND 7		; On ne garde que les 3 derniers bits
	LD B, A		;
	LD A, 8		; Le nombre de lignes restantes à traiter dans la série courante
	SUB B		;    = 8 - le nombre de lignes déjà traitées
	LD B, A		; Le nombre de lignes restant à traiter dans B

	; Valeur par défaut pour l'incrémentation de l'adresse mémoire contenue dans HL
	;	&800  <=> Permet de passer à la ligne suivante
	;	&50   <=> Permet de passer à la série de lignes suivante
	;	&4000 <=> Permet d'ajuster HL en fonction d'une série complète de lignes
	; 		  = [nombre de lignes dans une série] * &800
	; 	&3FB0 <=> = Espace d'adressage d'une série complète de lignes - Offset pour la série de lignes suivantes
	;		  = &4000 - &50
	; 	       => HL = HL - &4000 + &50
	;	
	LD IX, 0	; Sauvegarde de l'adresse de la pile
	ADD IX, SP	;
	
	
_GRAPH_LINE_V_4_2

	; Affichage du pixel
	LD A, (HL)
	AND D		; Préservation des données du pixel voisin
	OR E		; Affichage du nouveau pixel
	LD (HL), A
	
	; Test pour voir si tous les points ont été traités
	LD A, C
	OR A
	JP z, _GRAPH_LINE_V_4_END

	; Vérification si l'on a atteint une fin de série de lignes (série toutes les 8 lignes)
	DJNZ _GRAPH_LINE_V_4_3

	LD SP, &3FB0	; &3FB0 = &4000 - &50 = Espace d'adressage d'une série complète de lignes - Offset pour la série de lignes suivantes
	SBC HL, SP	;       => HL = HL - &4000 + &50
			;
	LD B, 8 	; On va traiter une nouvelle série de 8 lignes

_GRAPH_LINE_V_4_3

	LD SP, &800	; Passage à la ligne suivante (HL = HL + &800)
	ADD HL, SP	;
	DEC C		; Décrémentation de C qui contient le nombre de points à traiter
	JP _GRAPH_LINE_V_4_2

_GRAPH_LINE_V_4_END

	LD SP, IX	; Restauration de l'adresse de la pile

	POP IX		; Restauration des registres
	POP HL		; 
	POP DE		;	AF,BC,DE,HL,IX
	POP BC		;
	POP AF		;
	RET







;********************************************************
; Affichage d'une ligne verticale en mode 0 (16 couleurs)
;
; En entrée
;	D  <=> Y1
;	E  <=> Y2
;	BC <=> X
;	A  <=> Couleur de la ligne
; En sortie
;	néant
; Registres affectés
;	aucun
; Remarques
;
;

GRAPH_LINE_V_16:

	PUSH AF		; Sauvegarde des registres
	PUSH BC		;
	PUSH DE		;	AF,BC,DE,HL,IX
	PUSH HL		;
	PUSH IX		;


	; Adresse du premier pixel
	;
	; En entrée
	;	BC <=> X
	;	A  <=> Y1
	; En sortie
	;	HL <=> Adresse du point
	;
	PUSH DE		; On préserve Y1 et Y2
	AND %1111	; Préservation des 4 premiers bits de A pour ne permettre que les couleurs de 0 à 15
	LD E, A
	LD A, D		; Y1 dans A
	
	CALL GRAPH_ADR_OF_PIXEL
	LD A, C		; La partie basse de X dans A
	POP BC		; Restauration de Y1 et Y2 dans BC

	; Préparation des masques logiques en fonction du n° de la couleur
	LD D, 0
	LD IX, DEF_GRAPH_TABLE_PIXEL_16	; Référence à la table des masques 16 couleurs
	ADD IX, DE
	LD E, (IX)	; Masque logique associé à la couleur entrelacée dans B
	LD D, 85	; Masque logique permettant de préserver le pixel voisin dans D (voir affichage d'un pixel en mode 0)

		
	; Vérification si le premier pixel est pair ou impair
	; Dans le cas où le pixel est impair, on décale le masque associé à la couleur entrelacée, d'un bit vers le bas
	; et l'on décale le masque logique permettant de préserver le pixel voisin d'un bit vers le haut
	AND 1
	OR A
	JP z, _GRAPH_LINE_V_16_1

	SRL E
	SLA D

_GRAPH_LINE_V_16_1:

	; Calcul du nombre de points à traiter
	;
	; En entrée
	;	B <=> Y1
	;	C <=> Y2
	;
	LD A, C
	SUB B
	LD C, A		; Le nombre de points à traiter dans C

	; Calcul du nombre de lignes restant à traiter dans la série courante (Une série = 8 lignes)
	LD A, B		; B = Y1
	AND 7		; On ne garde que les 3 derniers bits
	LD B, A		;
	LD A, 8		; Le nombre de lignes restantes à traiter dans la série courante
	SUB B		;    = 8 - le nombre de lignes déjà traitées
	LD B, A		; Le nombre de lignes restant à traiter dans B
	 
	; Valeur par défaut pour l'incrémentation de l'adresse mémoire contenue dans HL
	;	&800  <=> Permet de passer à la ligne suivante
	;	&50   <=> Permet de passer à la série de lignes suivante
	;	&4000 <=> Permet d'ajuster HL en fonction d'une série complète de lignes
	; 		  = [nombre de lignes dans une série] * &800
	; 	&3FB0 <=> = Espace d'adressage d'une série complète de lignes - Offset pour la série de lignes suivantes
	;		  = &4000 - &50
	; 	       => HL = HL - &4000 + &50
	;	
	LD IX, 0	; Sauvegarde de l'adresse de la pile
	ADD IX, SP	;
		
_GRAPH_LINE_V_16_2

	; Affichage du pixel
	LD A, (HL)
	AND D		; Préservation des données du pixel voisin
	OR E		; Affichage du nouveau pixel
	LD (HL), A
	
	; Test pour voir si tous les points ont été traités
	LD A, C
	OR A
	JP z, _GRAPH_LINE_V_16_END

	; Vérification si l'on a atteint une fin de série de lignes (série toutes les 8 lignes)
	DJNZ _GRAPH_LINE_V_16_3

	LD SP, &3FB0	; &3FB0 = &4000 - &50 = Espace d'adressage d'une série complète de lignes - Offset pour la série de lignes suivantes
	SBC HL, SP	;       => HL = HL - &4000 + &50
			;
	LD B, 8 	; On va traiter une nouvelle série de 8 lignes

_GRAPH_LINE_V_16_3

	LD SP, &800	; Passage à la ligne suivante (HL = HL + &800)
	ADD HL, SP	;
	DEC C		; Décrémentation de C qui contient le nombre de points à traiter
	JP _GRAPH_LINE_V_16_2

_GRAPH_LINE_V_16_END

	LD SP, IX	; Restauration de l'adresse de la pile

	POP IX		; Restauration des registres
	POP HL		; 
	POP DE		;	AF,BC,DE,HL,IX
	POP BC		;
	POP AF		;
	RET







;*****************************************************************
; Affichage d'une ligne verticale quelque soit le mode graphique
;
; En entrée
;	D  <=> Y1
;	E  <=> Y2
;	BC <=> X
; En sortie
;	néant
; Registres affectés
;	aucun
; Remarques
;	- Les modes graphiques supportés sont les 0,1 et 2
;

GRAPH_LINE_V_XOR:

	PUSH AF		; Sauvegarde de AF pour le retour

	; Vérification du mode graphique en cours
	LD A, CST_GRAPH_VIDEO_MODE
	CP 2
	JP z, _GRAPH_LINE_V_2_XOR
	CP 1
	JP z, _GRAPH_LINE_V_4_XOR
	OR A
	JP z, _GRAPH_LINE_V_16_XOR

	; Retour si le mode graphique est <> 0,1 ou 2
	POP AF
	RET


	; Affichage des pixels
	;
	; En entrée les fonctions possèdent les même paramètres
	;	D  <=> Y1
	;	E  <=> Y2
	;	BC <=> X

_GRAPH_LINE_V_16_XOR

	; Affichage de la ligne horizontale 16 couleurs
	POP AF
	CALL GRAPH_LINE_V_16_XOR
	RET

_GRAPH_LINE_V_4_XOR

	; Affichage de la ligne horizontale 4 couleurs
	POP AF
	CALL GRAPH_LINE_V_4_XOR
	RET

_GRAPH_LINE_V_2_XOR

	; Affichage de la ligne horizontale 2 couleurs
	POP AF
	CALL GRAPH_LINE_V_2_XOR
	RET

GRAPH_LINE_V_XOR_END



;********************************************************
; Affichage d'une ligne verticale en mode 2 (2 couleurs)
; et d'effectuer un OU exclusif sur les données graphique
; déjà présentes
;
; En entrée
;	D  <=> Y1
;	E  <=> Y2
;	BC <=> X
; En sortie
;	néant
; Registres affectés
;	aucun
; Remarques
;
;

GRAPH_LINE_V_2_XOR:

	PUSH AF		; Sauvegarde des registres
	PUSH BC		;
	PUSH DE		;	AF,BC,DE,HL,IX
	PUSH HL		;
	PUSH IX		;


	; Adresse du premier pixel
	;
	; En entrée
	;	BC <=> X
	;	A  <=> Y1
	; En sortie
	;	HL <=> Adresse du point
	;
	PUSH DE		; On préserve Y1 et Y2
	LD E, A		; La couleur dans E
	LD A, D		; Y1 dans A

	CALL GRAPH_ADR_OF_PIXEL
	LD A, C		; La partie basse de X dans A
	POP BC		; Restauration de Y1 et Y2 dans BC

	; Préparation des masques logiques en fonction du n° de la couleur
	LD D, 0
	LD IX, DEF_GRAPH_TABLE_PIXEL_2		; Référence à la table des masques 4 couleurs
	ADD IX, DE
	LD E, (IX)	; Masque logique associé à la couleur entrelacée dans B


	; X se trouve actuellement dans A, on ne préserve que les 3 premiers bits de manière à savoir de combien de bits
	; doivent être déclalés les masques logiques
	AND 7


	; Décalages des masques vers le bas en fonction du n° du pixel concerné
	;
	; Paramètres de la fonction MATH_SRL_8
	; 	En entrée
	;		E  <=> Entier de 8 bits
	;		A  <=> Nombre de bits à décaler
	; 	En sortie
	;		E <=> Résultat du décalage des n bits
	;
	; A et E sont déjà chargés avec leur valeur respective

	CALL MATH_SRL_8 ; Décalage du masque de la couleur entrelacée, associée à la couleur du pixel
			; En sortie E contient le masque de la valeur entrelacée associé à la couleur du pixel

_GRAPH_LINE_V_2_XOR_1:

	; Calcul du nombre de points à traiter
	;
	; En entrée
	;	B <=> Y1
	;	C <=> Y2
	;
	LD A, C
	SUB B
	LD C, A		; Le nombre de points à traiter dans C

	; Calcul du nombre de lignes restant à traiter dans la série courante (Une série = 8 lignes)
	LD A, B		; B = Y1
	AND 7		; On ne garde que les 3 derniers bits
	LD B, A		;
	LD A, 8		; Le nombre de lignes restantes à traiter dans la série courante
	SUB B		;    = 8 - le nombre de lignes déjà traitées
	LD B, A		; Le nombre de lignes restant à traiter dans B

	; Valeur par défaut pour l'incrémentation de l'adresse mémoire contenue dans HL
	;	&800  <=> Permet de passer à la ligne suivante
	;	&50   <=> Permet de passer à la série de lignes suivante
	;	&4000 <=> Permet d'ajuster HL en fonction d'une série complète de lignes
	; 		  = [nombre de lignes dans une série] * &800
	; 	&3FB0 <=> = Espace d'adressage d'une série complète de lignes - Offset pour la série de lignes suivantes
	;		  = &4000 - &50
	; 	       => HL = HL - &4000 + &50
	;	
	LD IX, 0	; Sauvegarde de l'adresse de la pile
	ADD IX, SP	;
	
	
_GRAPH_LINE_V_2_XOR_2

	; Affichage du pixel
	LD A, (HL)	; Récupération de l'octet graphique courant
	XOR E		; On applique le OU exclusif sur les données du pixel courant
	LD (HL), A	; On affiche les nouvelles données
	
	; Test pour voir si tous les points ont été traités
	LD A, C
	OR A
	JP z, _GRAPH_LINE_V_2_XOR_END

	; Vérification si l'on a atteint une fin de série de lignes (série toutes les 8 lignes)
	DJNZ _GRAPH_LINE_V_2_XOR_3

	LD SP, &3FB0	; &3FB0 = &4000 - &50 = Espace d'adressage d'une série complète de lignes - Offset pour la série de lignes suivantes
	SBC HL, SP	;       => HL = HL - &4000 + &50
			;
	LD B, 8 	; On va traiter une nouvelle série de 8 lignes

_GRAPH_LINE_V_2_XOR_3

	LD SP, &800	; Passage à la ligne suivante (HL = HL + &800)
	ADD HL, SP	;
	DEC C		; Décrémentation de C qui contient le nombre de points à traiter
	JP _GRAPH_LINE_V_2_XOR_2

_GRAPH_LINE_V_2_XOR_END

	LD SP, IX	; Restauration de l'adresse de la pile

	POP IX		; Restauration des registres
	POP HL		; 
	POP DE		;	AF,BC,DE,HL,IX
	POP BC		;
	POP AF		;
	RET



;********************************************************
; Affichage d'une ligne verticale en mode 1 (4 couleurs)
; et d'effectuer un OU exclusif sur les données graphique
; déjà présentes
;
; En entrée
;	D  <=> Y1
;	E  <=> Y2
;	BC <=> X
; En sortie
;	néant
; Registres affectés
;	aucun
; Remarques
;
;

GRAPH_LINE_V_4_XOR:

	PUSH AF		; Sauvegarde des registres
	PUSH BC		;
	PUSH DE		;	AF,BC,DE,HL,IX
	PUSH HL		;
	PUSH IX		;


	; Adresse du premier pixel
	;
	; En entrée
	;	BC <=> X
	;	A  <=> Y1
	; En sortie
	;	HL <=> Adresse du point
	;
	PUSH DE		; On préserve Y1 et Y2
	LD E, A
	LD A, D		; Y1 dans A

	CALL GRAPH_ADR_OF_PIXEL
	LD A, C		; La partie basse de X dans A
	POP BC		; Restauration de Y1 et Y2 dans BC

	; Préparation des masques logiques en fonction du n° de la couleur
	LD D, 0
	LD IX, DEF_GRAPH_TABLE_PIXEL_4		; Référence à la table des masques 4 couleurs
	ADD IX, DE
	LD E, (IX)	; Masque logique associé à la couleur entrelacée dans B


	; X se trouve actuellement dans A, on ne préserve que les 2 premiers bits de manière à savoir de combien de bits
	; doivent être déclalés les masques logiques
	AND 3


	; Décalages des masques vers le bas en fonction du n° du pixel concerné
	;
	; Paramètres de la fonction MATH_SRL_8
	; 	En entrée
	;		E  <=> Entier de 8 bits
	;		A  <=> Nombre de bits à décaler
	; 	En sortie
	;		E <=> Résultat du décalage des n bits
	;
	; A et E sont déjà chargés avec leur valeur respective
	LD E, 136	; Valeur par défaut du masque logique qui va permettre de préserver
			; le pixel voisin, en Mode 1 = 136 <=> %10001000
	CALL MATH_SRL_8 ; Décalage du masque négatif qui permet de préserver le pixel voisin

_GRAPH_LINE_V_4_XOR_1:

	; Calcul du nombre de points à traiter
	;
	; En entrée
	;	B <=> Y1
	;	C <=> Y2
	;
	LD A, C
	SUB B
	LD C, A		; Le nombre de points à traiter dans C

	; Calcul du nombre de lignes restant à traiter dans la série courante (Une série = 8 lignes)
	LD A, B		; B = Y1
	AND 7		; On ne garde que les 3 derniers bits
	LD B, A		;
	LD A, 8		; Le nombre de lignes restantes à traiter dans la série courante
	SUB B		;    = 8 - le nombre de lignes déjà traitées
	LD B, A		; Le nombre de lignes restant à traiter dans B

	; Valeur par défaut pour l'incrémentation de l'adresse mémoire contenue dans HL
	;	&800  <=> Permet de passer à la ligne suivante
	;	&50   <=> Permet de passer à la série de lignes suivante
	;	&4000 <=> Permet d'ajuster HL en fonction d'une série complète de lignes
	; 		  = [nombre de lignes dans une série] * &800
	; 	&3FB0 <=> = Espace d'adressage d'une série complète de lignes - Offset pour la série de lignes suivantes
	;		  = &4000 - &50
	; 	       => HL = HL - &4000 + &50
	;	
	LD IX, 0	; Sauvegarde de l'adresse de la pile
	ADD IX, SP	;
	
	
_GRAPH_LINE_V_4_XOR_2

	; Affichage du pixel
	LD A, (HL)
	XOR E		; Affichage du nouveau pixel
	LD (HL), A
	
	; Test pour voir si tous les points ont été traités
	LD A, C
	OR A
	JP z, _GRAPH_LINE_V_4_XOR_END

	; Vérification si l'on a atteint une fin de série de lignes (série toutes les 8 lignes)
	DJNZ _GRAPH_LINE_V_4_XOR_3

	LD SP, &3FB0	; &3FB0 = &4000 - &50 = Espace d'adressage d'une série complète de lignes - Offset pour la série de lignes suivantes
	SBC HL, SP	;       => HL = HL - &4000 + &50
			;
	LD B, 8 	; On va traiter une nouvelle série de 8 lignes

_GRAPH_LINE_V_4_XOR_3

	LD SP, &800	; Passage à la ligne suivante (HL = HL + &800)
	ADD HL, SP	;
	DEC C		; Décrémentation de C qui contient le nombre de points à traiter
	JP _GRAPH_LINE_V_4_XOR_2

_GRAPH_LINE_V_4_XOR_END

	LD SP, IX	; Restauration de l'adresse de la pile

	POP IX		; Restauration des registres
	POP HL		; 
	POP DE		;	AF,BC,DE,HL,IX
	POP BC		;
	POP AF		;
	RET



;********************************************************
; Affichage d'une ligne verticale en mode 0 (16 couleurs)
; et d'effectuer un OU exclusif sur les données graphiques
;
; En entrée
;	D  <=> Y1
;	E  <=> Y2
;	BC <=> X
; En sortie
;	néant
; Registres affectés
;	aucun
; Remarques
;
;

GRAPH_LINE_V_16_XOR:

	PUSH AF		; Sauvegarde des registres
	PUSH BC		;
	PUSH DE		;	AF,BC,DE,HL,IX
	PUSH HL		;
	PUSH IX		;


	; Adresse du premier pixel
	;
	; En entrée
	;	BC <=> X
	;	A  <=> Y1
	; En sortie
	;	HL <=> Adresse du point
	;
	PUSH DE		; On préserve Y1 et Y2
	LD A, D		; Y1 dans A
	
	CALL GRAPH_ADR_OF_PIXEL
	LD A, C		; La partie basse de X dans A
	POP BC		; Restauration de Y1 et Y2 dans BC

	; Masque utilisé pour calculer le XOR avec les données du point courant
	LD D, 170	; Masque logique permettant de préservation des données (%10101010)

		
	; Vérification si le premier pixel est pair ou impair
	; Dans le cas où le pixel est impair, on décale le masque associé à la couleur entrelacée, d'un bit vers le bas
	; et l'on décale le masque logique permettant de préserver le pixel voisin d'un bit vers le haut
	AND 1
	OR A
	JP z, _GRAPH_LINE_V_16_1_XOR

	RRC D		; Décalage du masque logique

_GRAPH_LINE_V_16_1_XOR:

	; Calcul du nombre de points à traiter
	;
	; En entrée
	;	B <=> Y1
	;	C <=> Y2
	;
	LD A, C
	SUB B
	LD C, A		; Le nombre de points à traiter dans C

	; Calcul du nombre de lignes restant à traiter dans la série courante (Une série = 8 lignes)
	LD A, B		; B = Y1
	AND 7		; On ne garde que les 3 derniers bits
	LD B, A		;
	LD A, 8		; Le nombre de lignes restantes à traiter dans la série courante
	SUB B		;    = 8 - le nombre de lignes déjà traitées
	LD B, A		; Le nombre de lignes restant à traiter dans B
	 
	; Valeur par défaut pour l'incrémentation de l'adresse mémoire contenue dans HL
	;	&800  <=> Permet de passer à la ligne suivante
	;	&50   <=> Permet de passer à la série de lignes suivante
	;	&4000 <=> Permet d'ajuster HL en fonction d'une série complète de lignes
	; 		  = [nombre de lignes dans une série] * &800
	; 	&3FB0 <=> = Espace d'adressage d'une série complète de lignes - Offset pour la série de lignes suivantes
	;		  = &4000 - &50
	; 	       => HL = HL - &4000 + &50
	;	
	LD IX, 0	; Sauvegarde de l'adresse de la pile
	ADD IX, SP	;
		
_GRAPH_LINE_V_16_2_XOR

	; Affichage du pixel
	LD A, (HL)
	XOR D		; Notre OU exclusif
	LD (HL), A
	
	; Test pour voir si tous les points ont été traités
	LD A, C
	OR A
	JP z, _GRAPH_LINE_V_16_XOR_END

	; Vérification si l'on a atteint une fin de série de lignes (série toutes les 8 lignes)
	DJNZ _GRAPH_LINE_V_16_3_XOR

	LD SP, &3FB0	; &3FB0 = &4000 - &50 = Espace d'adressage d'une série complète de lignes - Offset pour la série de lignes suivantes
	SBC HL, SP	;       => HL = HL - &4000 + &50
			;
	LD B, 8 	; On va traiter une nouvelle série de 8 lignes

_GRAPH_LINE_V_16_3_XOR

	LD SP, &800	; Passage à la ligne suivante (HL = HL + &800)
	ADD HL, SP	;
	DEC C		; Décrémentation de C qui contient le nombre de points à traiter
	JP _GRAPH_LINE_V_16_2_XOR

_GRAPH_LINE_V_16_XOR_END

	LD SP, IX	; Restauration de l'adresse de la pile

	POP IX
	POP HL		; 
	POP DE		;	AF,BC,DE,HL,IX
	POP BC		;
	POP AF		;
	RET












;******************************************************
; Affichage d'un pixel indépendamment du mode graphique
;
; En entrée
;	BC <=> X sur 16 bits
;	D  <=> Y sur 8 bits
;	E  <=> Couleur du pixel sur 8 bits
; En sortie
;	néant
; Registres impactés
;	aucun
; Remarques
;	- Cette fonction n'utilise pas la pile pour les paramètres en entrée
;

GRAPH_PUT_PIXEL:

	PUSH AF	; Sauvegarde de AF
	
	; Affichage d'un pixel en fonction du mode graphique courant
	LD A, CST_GRAPH_VIDEO_MODE
	OR A
	JP z, _GRAPH_PUT_PIXEL_16
	CP 1
	JP z, _GRAPH_PUT_PIXEL_4
	CP 2
	JP z, _GRAPH_PUT_PIXEL_2

	POP AF
	RET

	; Affichage des pixels
	;
	; En entrée les fonctions possèdent les même paramètres
	;	BC <=> X sur 16 bits
	;	D  <=> Y sur 8 bits
	;	E  <=> Couleur du pixel sur 8 bits

_GRAPH_PUT_PIXEL_16

	; Affichage d'un pixel 16 couleurs
	CALL GRAPH_PUT_PIXEL_16
	POP AF	; Restauration de AF
	RET

_GRAPH_PUT_PIXEL_4

	; Affichage d'un pixel 4 couleurs
	CALL GRAPH_PUT_PIXEL_4
	POP AF	; Restauration de AF
	RET

_GRAPH_PUT_PIXEL_2

	; Affichage d'un pixel 2 couleurs
	CALL GRAPH_PUT_PIXEL_2
	POP AF
	RET

_GRAPH_PUT_PIXEL_END





;*****************************************************
; Affichage d'un pixel en mode 2 (2 couleurs)
;
; En entrée
;	BC <=> X sur 16 bits
;	D  <=> Y sur 8 bits
;	E  <=> Couleur du pixel sur 8 bits
; En sortie
;	néant
; Registres impactés
;	aucun
; Remarques
;	- Cette fonction n'utilise pas la pile pour les paramètres en entrée
;	- E peut prendre les valeurs de 0 à 1
;

GRAPH_PUT_PIXEL_2:

	PUSH AF
	PUSH DE
	PUSH HL

	; Calcul de l'adresse de base du point
	; BC et D contiennent les valeurs X et Y du point
	LD A, D		; Sauvegarde D (Y)


	; Récupération de la couleur entrelacée correspondant à la couleur du pixel
	LD HL, DEF_GRAPH_TABLE_PIXEL_2
	LD D, 0		; D à 0 pour ne garder que E (la couleur). D contenait Y, on en a plus besoin
	ADD HL, DE	; Ajout du décalage en fonction du n° de la couleur
	LD E, (HL)	; Le masque associé à la couleur entrelacée correspondant à la couleur E se trouve en (HL)

	; Appel de la fonction qui calcul l'adresse de base du point
	;
	; En entrée
	;	BC <=> X
	;	A  <=> Y
	; En sortie
	;	HL <=> Adresse graphique du point
	; Remarques
	;	Les registres d'entrée sont préservés
	CALL GRAPH_ADR_OF_PIXEL

	; Vérification si le pixel est pair ou impair
	LD A, C		; Test du bit 0 de C. BC contient le position X du pixel
	AND 7		; Dans le cas où le pixel est un pixel impair ( X AND 1 = 1 ), on décale de 1 pixel le masque logique
			; vers le haut et la couleur entrelacée vers le bas. Si le pixel a allumé est pair => A = 0

	; Décalages des masques vers le bas en fonction du n° du pixel concerné
	;
	; Paramètres de la fonction MATH_SRL_8
	; 	En entrée
	;		E  <=> Entier de 8 bits
	;		A  <=> Nombre de bits à décaler
	; 	En sortie
	;		E <=> Résultat du décalage des n bits
	;
	; A et E sont déjà chargés avec leur valeur respective

	CALL MATH_SRL_8 ; Décalage du masque de la couleur entrelacée, associée à la couleur du pixel.
			; En sortie E contient le masque de la couleur
	LD D, E		; Sauvegarde de E

	; A est déjà chargé avec le nombre de décalages
	LD E, 128	; X AND 7 = n° du pixel courant, A contient donc le nombre de bits à décaler.
	CALL MATH_SRL_8 ; Décalage du masque négatif qui permet de préserver le pixel voisin

	; Inversion du masque logique négatif de manière à préserver les données du pixel voisin
	LD A, E
	CPL
	LD E, D		; Restauration de E qui doit contenir le masque entrelacé lié à la couleur du pixel
	LD D, A		; D va contenir le masque logique permettant la préservation du pixel voisin

	; Affichage du pixel
	LD A, (HL)	; Récupération de l'octet associé au pixel
	AND D		; Préservation des données du pixel voisin
	OR E		; Ajout des données du nouveau pixel
	LD (HL), A	; Affichage à l'écran
	
_GRAPH_PUT_PIXEL_2_END

	POP HL	; Restauration de HL
	POP DE	; Restauration de DE
	POP AF	; Restauration de AF
	RET




;*****************************************************
; Affichage d'un pixel en mode 1 (4 couleurs)
;
; En entrée
;	BC <=> X sur 16 bits
;	D  <=> Y sur 8 bits
;	E  <=> Couleur du pixel sur 8 bits
; En sortie
;	néant
; Registres impactés
;	aucun
; Remarques
;	- Cette fonction n'utilise pas la pile pour les paramètres en entrée
;	- E peut prendre les valeurs de 0 à 3
;

GRAPH_PUT_PIXEL_4:

	PUSH AF
	PUSH DE
	PUSH HL

	; Calcul de l'adresse de base du point
	; BC et D contiennent les valeurs X et Y du point
	LD A, D		; Sauvegarde D (Y)


	; Récupération de la couleur entrelacée correspondant à la couleur du pixel
	LD HL, DEF_GRAPH_TABLE_PIXEL_4
	LD D, 0		; D à 0 pour ne garder que E (la couleur). D contenait Y, on en a plus besoin
	ADD HL, DE	; Ajout du décalage en fonction du n° de la couleur
	LD E, (HL)	; Le masque associé à la couleur entrelacée correspondant à la couleur E se trouve en (HL)


	; Appel de la fonction qui calcul l'adresse de base du point
	;
	; En entrée
	;	BC <=> X
	;	A  <=> Y
	; En sortie
	;	HL <=> Adresse graphique du point
	; Remarques
	;	Les registres d'entrée sont préservés
	CALL GRAPH_ADR_OF_PIXEL

	; Vérification si le pixel est pair ou impair
	LD A, C		; Test du bit 0 de C. BC contient le position X du pixel
	AND 3		; X AND 3 = n° du pixel courant, A contient donc le nombre de bits à décaler.


	; Décalages des masques vers le bas en fonction du n° du pixel concerné
	;
	; Paramètres de la fonction MATH_SRL_8
	; 	En entrée
	;		E  <=> Entier de 8 bits
	;		A  <=> Nombre de bits à décaler
	; 	En sortie
	;		E <=> Résultat du décalage des n bits
	;
	; A et E sont déjà chargés avec leur valeur respective

	CALL MATH_SRL_8 ; Décalage du masque de la couleur entrelacée, associée à la couleur du pixel
			; En sortie E contient le masque de la valeur entrelacée associé à la couleur du pixel
	LD D, E		; Sauvegarde de E

	; A est déjà chargé avec le nombre de décalages
	LD E, 136	; Valeur par défaut du masque logique qui va permettre de préserver
			; le pixel voisin, en Mode 1 = 136 <=> %10001000
	CALL MATH_SRL_8 ; Décalage du masque négatif qui permet de préserver le pixel voisin


	; Inversion du masque logique négatif de manière à préserver les données du pixel voisin
	LD A, E
	CPL
	LD E, D		; Restauration de E qui doit contenir le masque entrelacé lié à la couleur du pixel
	LD D, A		; D va contenir le masque logique permettant la préservation du pixel voisin

	; Affichage du pixel
	LD A, (HL)	; Récupération de l'octet associé au pixel
	AND D		; Préservation des données du pixel voisin
	OR E		; Ajout des données du nouveau pixel
	LD (HL), A	; Affichage à l'écran
	
_GRAPH_PUT_PIXEL_4_END

	POP HL	; Restauration de HL
	POP DE	; Restauration de DE
	POP AF	; Restauration de AF
	RET




;*****************************************************
; Affichage d'un pixel en mode 0 (16 couleurs)
;
; En entrée
;	BC <=> X sur 16 bits
;	D  <=> Y sur 8 bits
;	E  <=> Couleur du pixel sur 8 bits
; En sortie
;	néant
; Registres impactés
;	aucun
; Remarques
;	- Cette fonction n'utilise pas la pile pour les paramètres en entrée
;	- E peut prendre les valeurs de 0 à 15
;

GRAPH_PUT_PIXEL_16:

	PUSH AF
	PUSH DE
	PUSH HL	

	; Calcul de l'adresse de base du point
	; BC et D contiennent les valeurs X et Y du point
	LD A, D		; Sauvegarde D (Y)


	; Récupération de la couleur entrelacée correspondant à la couleur du pixel
	LD HL, DEF_GRAPH_TABLE_PIXEL_16
	LD D, 0		; D à 0 pour ne garder que E (la couleur). D contenait Y, on en a plus besoin
	ADD HL, DE	; Ajout du déclage en fonction du n° de la couleur
	LD E, (HL)	; Le masque associé à la couleur entrelacée correspondant à la couleur E se trouve en (HL)
	LD D, 85	; Valeur par défaut du masque logique qui va permettre de préserver le pixel voisin,
			; en Mode 0 = 85 <=> %01010101


	; Appel de la fonction qui calcul l'adresse de base du point
	;
	; En entrée
	;	BC <=> X
	;	A  <=> Y
	; En sortie
	;	HL <=> Adresse graphique du point
	; Remarques
	;	Les registres d'entrée sont préservés
	CALL GRAPH_ADR_OF_PIXEL
	
	; Vérification si le pixel est pair ou impair
	LD A, C		; Test du bit 0 de C. BC contient le position X du pixel
	AND 1		; Dans le cas où le pixel est un pixel impair ( X AND 1 = 1 ), on décale de 1 pixel
			; le masque logique vers le haut et la couleur entrelacée vers le bas
			; Si le pixel a allumé est pair => A = 0
	JP z, _GRAPH_PUT_PIXEL_16_1

	SRL E		; Décalage vers le bas du masque associé à la couleur entrelacée du pixel
	SLA D		; Décalage vers le haut du masque logique permettant de préserver le pixel voisin

_GRAPH_PUT_PIXEL_16_1:

	; Affichage du pixel
	LD A, (HL)	; Récupération de l'octet associé au pixel
	AND D		; Préservation des données du pixel voisin
	OR E		; Ajout des données du nouveau pixel
	LD (HL), A	; Affichage à l'écran
	
_GRAPH_PUT_PIXEL_16_END

	POP HL	; Restauration de HL
	POP DE	; Restauration de DE
	POP AF	; Restauration de AF
	RET



;******************************************************
; Affichage d'un pixel indépendamment du mode graphique
; en effectuant un OU exclusif sur les données graphiques
;
; En entrée
;	BC <=> X sur 16 bits
;	A  <=> Y sur 8 bits
; En sortie
;	néant
; Registres impactés
;	aucun
; Remarques
;	- Cette fonction n'utilise pas la pile pour les paramètres en entrée
;

GRAPH_PUT_PIXEL_XOR:

	PUSH AF	; Sauvegarde de AF
	
	; Affichage d'un pixel en fonction du mode graphique courant
	LD A, CST_GRAPH_VIDEO_MODE
	OR A
	JP z, _GRAPH_PUT_PIXEL_16_XOR
	CP 1
	JP z, _GRAPH_PUT_PIXEL_4_XOR
	CP 2
	JP z, _GRAPH_PUT_PIXEL_2_XOR

	POP AF
	RET

	; Affichage des pixels
	;
	; En entrée les fonctions possèdent les même paramètres
	;	BC <=> X sur 16 bits
	;	D  <=> Y sur 8 bits
	;	E  <=> Couleur du pixel sur 8 bits

_GRAPH_PUT_PIXEL_16_XOR

	; Affichage d'un pixel 16 couleurs
	POP AF	; Restauration de AF
	CALL GRAPH_PUT_PIXEL_16_XOR
	RET

_GRAPH_PUT_PIXEL_4_XOR

	; Affichage d'un pixel 4 couleurs
	POP AF	; Restauration de AF
	CALL GRAPH_PUT_PIXEL_4_XOR
	RET

_GRAPH_PUT_PIXEL_2_XOR

	; Affichage d'un pixel 2 couleurs
	POP AF	; Restauration de AF
	CALL GRAPH_PUT_PIXEL_2_XOR
	RET

_GRAPH_PUT_PIXEL_XOR_END




;*****************************************************
; Affichage d'un pixel en mode 2 (2 couleurs)
; en effectuant un OU exclusif sur les données grahiques
; En entrée
;	BC <=> X sur 16 bits
;	A  <=> Y sur 8 bits
; En sortie
;	néant
; Registres impactés
;	aucun
; Remarques
;	- Cette fonction n'utilise pas la pile pour les paramètres en entrée
;	- E peut prendre les valeurs de 0 à 1
;

GRAPH_PUT_PIXEL_2_XOR:

	PUSH AF
	PUSH BC
	PUSH HL

	; Appel de la fonction qui calcul l'adresse de base du point
	;
	; En entrée
	;	BC <=> X
	;	A  <=> Y
	; En sortie
	;	HL <=> Adresse graphique du point
	;
	CALL GRAPH_ADR_OF_PIXEL

	; Vérification si le pixel est pair ou impair
	LD A, C		; Test du bit 0 de C. BC contient le position X du pixel
	AND 7		; Dans le cas où le pixel est un pixel impair ( X AND 1 = 1 ), on décale de 1 pixel le masque logique
			; vers le haut et la couleur entrelacée vers le bas. Si le pixel a allumé est pair => A = 0

	; Décalages des masques vers le bas en fonction du n° du pixel concerné
	;
	; Paramètres de la fonction MATH_SRL_8
	; 	En entrée
	;		E  <=> Entier de 8 bits
	;		A  <=> Nombre de bits à décaler
	; 	En sortie
	;		E <=> Résultat du décalage des n bits
	;
	; A est déjà chargé avec le nombre de décalages
	LD B, E		; Sauvegarde de E
	LD E, 128	; A contient donc le nombre de bits à décaler. E le masque permettant le OU exclusif
	CALL MATH_SRL_8 ; Décalage du masque qui permet d'effectuer le OU exclusif

	; Affichage du pixel
	LD A, (HL)	; Récupération de l'octet associé au pixel
	XOR E		; Notre OU exclusif
	LD (HL), A	; Affichage à l'écran
	LD E, B		; Restauration de E
	
_GRAPH_PUT_PIXEL_2_XOR_END

	POP HL	; Restauration de HL,BC,AF
	POP BC	;
	POP AF	;
	RET



;*****************************************************
; Affichage d'un pixel en mode 1 (4 couleurs)
;
; En entrée
;	BC <=> X sur 16 bits
;	A  <=> Y sur 8 bits
; En sortie
;	néant
; Registres impactés
;	aucun
; Remarques
;	- Cette fonction n'utilise pas la pile pour les paramètres en entrée
;	- E peut prendre les valeurs de 0 à 3
;

GRAPH_PUT_PIXEL_4_XOR:

	PUSH AF
	PUSH BC
	PUSH HL

	; Appel de la fonction qui calcul l'adresse de base du point
	;
	; En entrée
	;	BC <=> X
	;	A  <=> Y
	; En sortie
	;	HL <=> Adresse graphique du point
	;
	CALL GRAPH_ADR_OF_PIXEL

	; Vérification si le pixel est pair ou impair
	LD A, C		; Test du bit 0 de C. BC contient le position X du pixel
	AND 3		; X AND 3 = n° du pixel courant, A contient donc le nombre de bits à décaler.


	; Décalages des masques vers le bas en fonction du n° du pixel concerné
	;
	; Paramètres de la fonction MATH_SRL_8
	; 	En entrée
	;		E  <=> Entier de 8 bits
	;		A  <=> Nombre de bits à décaler
	; 	En sortie
	;		E <=> Résultat du décalage des n bits
	;
	; A est déjà chargé avec le nombre de décalages
	LD B, E		; Sauvegarde de E
	LD E, 136	; Valeur par défaut du masque logique qui va permettre d'effectuer le OU exclusif
			; les données du pixel, en Mode 1 = 136 <=> %10001000
	CALL MATH_SRL_8 ; Décalage du masque négatif qui permet de préserver le pixel voisin

	; Affichage du pixel
	LD A, (HL)	; Récupération de l'octet associé au pixel
	XOR E		; Notre OU exclusif
	LD (HL), A	; Affichage à l'écran
	LD E, B		; Restauration de E
	
_GRAPH_PUT_PIXEL_4_XOR_END

	POP HL	; Restauration de HL, BC,AF
	POP BC	;
	POP AF	;
	RET



;*****************************************************
; Affichage d'un pixel en mode 0 (16 couleurs)
; en effectuant un OU logique sur les données graphique
;
; En entrée
;	BC <=> X sur 16 bits
;	A  <=> Y sur 8 bits
; En sortie
;	néant
; Registres impactés
;	aucun
; Remarques
;	- Cette fonction n'utilise pas la pile pour les paramètres en entrée
;	- E peut prendre les valeurs de 0 à 15
;

GRAPH_PUT_PIXEL_16_XOR:

	PUSH AF
	PUSH BC
	PUSH HL	

	; Appel de la fonction qui calcul l'adresse de base du point
	;
	; En entrée
	;	BC <=> X
	;	A  <=> Y
	; En sortie
	;	HL <=> Adresse graphique du point
	;
	CALL GRAPH_ADR_OF_PIXEL

	; Masque logique utilisé pour effectuer le OU exclusif
	LD B, 170	; Masque de préservation des données de la couleur (%10101010)
	
	; Vérification si le pixel est pair ou impair
	LD A, C		; Test du bit 0 de C. BC contient le position X du pixel
	AND 1		; Dans le cas où le pixel est un pixel impair ( X AND 1 = 1 ), on décale de 1 pixel
			; le masque logique vers le haut et la couleur entrelacée vers le bas
			; Si le pixel a allumé est pair => A = 0
	JP z, _GRAPH_PUT_PIXEL_16_XOR_1

	SRL B		; Décalage vers le haut du masque logique permettant de préserver le pixel voisin

_GRAPH_PUT_PIXEL_16_XOR_1:

	; Affichage du pixel
	LD A, (HL)	; Récupération de l'octet associé au pixel
	XOR B		; Notre OU exclusif
	LD (HL), A	; Affichage à l'écran
	
_GRAPH_PUT_PIXEL_16_XOR_END

	POP HL	; Restauration de HL, BC, AF
	POP BC	;
	POP AF	;
	RET







;######################################################################################
;				Fonctions mathématiques
;######################################################################################



;***************************************************************
; Routine de décalage vers la droite d'un entier de 8 bits
;
; En entrée
;	E  <=> Entier de 8 bits
;	A  <=> Nombre de bits à décaler
; En sortie
;	E <=> Résultat du décalage des n bits
; Registres affectés
;	F, E
; Remarques
;	- Cette fonction n'utilise pas la pile pour le passage de paramètres
;

MATH_SRL_8:

	OR A		; Si A = 0 on sort
	JP z, _MATH_SRL_8_END
	PUSH BC		; Sauvegarde de BC
	LD B, A		; Le nombre d'itération est transféré dans B pour le décompte

_MATH_SRL_8_1

	SRL E		; Rotation
	DJNZ _MATH_SRL_8_1
	POP BC		; Restauration de BC

_MATH_SRL_8_END

	RET


;***************************************************************
; Routine de décalage vers la gauche d'un entier de 8 bits
;
; En entrée
;	E  <=> Entier de 8 bits
;	A  <=> Nombre de bits à décaler
; En sortie
;	E <=> Résultat du décalage des n bits
; Registres affectés
;	F,E
; Remarques
;

MATH_SLA_8:

	OR A		; Si A = 0 on sort
	JP z, _MATH_SLA_8_END
	PUSH BC		; Sauvegarde de BC pour le retour
	LD B, A		; B va contenir le nombre d'itération

_MATH_SLA_8_1

	SLA E
	DJNZ _MATH_SLA_8_1
	POP BC
	
_MATH_SLA_8_END

	RET



;***************************************************************
; Routine de décalage vers la droite d'un entier de 8 bits
; carry est ré-injecté vers la gauche
;
; En entrée
;	E  <=> Entier de 8 bits
;	A  <=> Nombre de bits à décaler
; En sortie
;	E <=> Résultat du décalage des n bits
; Registres affectés
;	F, E
; Remarques
;	- Cette fonction n'utilise pas la pile pour le passage de paramètres
;

MATH_RRC_8:

	OR A		; Si B = 0 on sort
	JP z, _MATH_RRC_8_END
	PUSH BC		; Sauvegarde de BC pour le retour
	LD B, A		; Le nombre d'itération est transféré dans B pour le décompte
	LD C, A		; Sauvegarde de A
	LD A, E		; Valeur à décaler

_MATH_RRC_8_1

	RRCA
	DJNZ _MATH_RRC_8_1
	LD E, A
	LD A, C
	POP BC		; Restauration de BC

_MATH_RRC_8_END

	RET



;***************************************************************
; Routine de décalage vers la gauche d'un entier de 8 bits
; carry est ré-injecté vers la droite
;
; En entrée
;	E  <=> Entier de 8 bits
;	A  <=> Nombre de bits à décaler
; En sortie
;	E <=> Résultat du décalage des n bits
; Registres affectés
;	F, E
; Remarques
;	- Cette fonction n'utilise pas la pile pour le passage de paramètres
;

MATH_RLC_8:

	OR A		; Si A = 0 on sort
	JP z, _MATH_RLC_8_END
	PUSH BC		; Sauvegarde de BC pour le retour
	LD B, A		; Le nombre d'itération est transféré dans B pour le décompte

_MATH_RLC_8_1

	RLC E
	DJNZ _MATH_RLC_8_1
	POP BC		; Restauration de BC

_MATH_RLC_8_END

	RET


;***************************************************************
; Routine de décalage vers la droite d'un entier de 16 bits
;
; En entrée
;	DE <=> Entier non signé de 16 bits
;	A  <=> Nombre de bits à décaler
; En sortie
;	DE <=> Résultat du décalage des n bits
; Registres affectés
;	F,DE
; Remarques
;	- Cette fonction n'utilise pas la pile pour le passage de paramètres
;

MATH_SRL_16:

	OR A		; Si A = 0 on sort
	JP z, _MATH_SRL_16_END
	PUSH BC
	LD B, A		; B va contenir le nombre d'étérations
	LD C, A		; Sauvegarde de A
	LD A, E

_MATH_SRL_16_1

	SRL D
	RRA
	DJNZ _MATH_SRL_16_1
	LD E, A
	LD A, C		; Restauration de A
	POP BC		; Restauration de BC

_MATH_SRL_16_END

	RET




;***************************************************************
; Routine de décalage vers la gauche d'un entier de 16 bits
;
; En entrée
;	DE <=> Entier de 16 bits
;	A  <=> Nombre de bits à décaler
; En sortie
;	DE <=> Résultat du décalage des n bits
; Registres affectés
;	F, DE
; Remarques
;	- Cette fonction n'utilise pas la pile pour le passage de paramètres
;

MATH_SLA_16:

	OR A		; Si A = 0 on sort
	JP z, _MATH_SLA_16_END
	PUSH BC		; Sauvegarde de BC pour le retour
	LD B, A		; B va contenir le nombre de décalages
	LD C, A		; Sauvegarde de A
	LD A, D

_MATH_SLA_16_1

	SLA E
	RLA
	DJNZ _MATH_SLA_16_1
	LD D, A
	LD A, C		; Restauration de A
	POP BC		; Restauration de BC

_MATH_SLA_16_END

	RET



;***************************************************************
; Routine de multiplication de 2 entiers non signés, de 8 bits
; avec un résultat sur 16 bits
;
; En entrée :
;	D  <=> Multiplicande (A)
;	E  <=> Multiplicateur (B)
; En sortie :
;	DE   Produit de A par B
; Registres affectés
;	DE
; Remarques
;	- Si A ou B = 0 => DE = 0 en sortie
;	
; 	- Exemple de méthode d'appel
;
;		LD D, 5
;		LD E, 2
;		CALL MATH_MUL_8x8
;		.
;

MATH_MUL_8x8:
		
	PUSH AF		; Sauvegarde des registres
	PUSH BC		;
	PUSH HL		;
	; Récupération des paramètres
	LD B, D		; Transfert des deux paramètres stockés dans DE, dans BC
	LD C, E		;

	; Initialisation des registres pour le calcul	
	LD HL, 0	; Valeur de retour
	LD A, B		; Transfert du multiplicande dans A
			; Le multiplicateur se trouve dans C

	; Vérification des valeurs en entrée
	OR A		; Test de A
			; Si A = 0 on sort
	JP z, _MATH_MUL_8x8_END
	LD L, A		; Sauvegarde de A pour le test de C
	LD A, C		; c est transféré dans A pour le test
	OR A		; Test de C via A
	LD A, L		; On restore A
	LD L, H		; On efface L via H
			; Si A(C) = 0 on sort
	JP z, _MATH_MUL_8x8_END

	; Début de code lié à la multiplication
	LD D, L		; D est effacer par L
	LD E, A		; Le multiplicande va dans E
	LD H, C		; Le multiplicateur va dans H
	LD B, 8		; Traitement des 8 bits
	
_MATH_MUL_8x8_1

	; Multiplication par 2 de HL (décalage d'1 bit vers le haut)
	ADD HL, HL
	JR nc, _MATH_MUL_8x8_2

	; Remplacement du bit de débordement par le multiplicateur
	ADD HL, DE	

_MATH_MUL_8x8_2

	DJNZ _MATH_MUL_8x8_1

_MATH_MUL_8x8_END
	
	EX HL,DE	; Récupération du résultat dans DE (à changer éventuellement)
	POP HL		; Restauration de registres
	POP BC		; 
	POP AF		;
	RET





;######################################################################################
;				Fonctions sytème
;######################################################################################


;********************************************************************
; Emet un bip
;
; En entrée
;	aucun
; En sortie
;	aucun
; Registres affectés
;	aucun
; Remarques
;	- Cette fonction correspond à la commande PRINT CHR$(7)
;	  Le BEL du CPC
;

SYS_BEEP:

	PUSH AF
	LD A, 7
	CALL CALLBACK_TEXT_PRINT_CHAR
	POP AF
	RET

_SYS_BEEP_END




;********************************************************************
; Permet de réserver une zone mémoire
;
; En entrée
;	BC <=> Taille en octet
; En sortie
;       HL <=> Adresse de la nouvelle zone mémoire
; Registres affectés
;	HL
; Remarques
;	- La mémoire max allouée dépend de la taille de la table virtuelle
;	- Lorsque l'obtention de mémoire n'est plus possible, deux beep sont
;	  émis.
;

SYS_GET_MEMORY:

	PUSH AF
	PUSH DE

	; Vérification que l'on a pas atteind la fin de la table virtuelle
	LD HL, (VIRTUAL_TABLE_OFFSET)
	LD DE, VIRTUAL_TABLE_SIZE
	ADD HL, BC
	EX HL, DE
	SBC HL, DE
	; Si HL >= 0 c'est que l'obtention de mémoire est possible dans le cas contraire
	; c'est que l'on a atteind ou dépassé la capacité de la table virtuelle, deux beep et l'on sort
	JP nc, _SYS_GET_MEMORY_1
	CALL SYS_BEEP	; Pass assez de mémoire dispo
	LD HL, 0	; Adresse de retour = null
	JP _SYS_GET_MEMORY_END

_SYS_GET_MEMORY_1

	LD HL, VIRTUAL_TABLE
	LD DE, (VIRTUAL_TABLE_OFFSET)
	ADD HL, DE
	PUSH HL		; Sauvegarde l'adresse de la nouvelle zone mémoire pour le retour

	; Calcul du nouvel offset
	EX HL, DE
	ADD HL, BC
	LD (VIRTUAL_TABLE_OFFSET), HL

	POP HL		; Retauration de l'adresse de la nouvelle zone mémoire pour le retour

_SYS_GET_MEMORY_END:

	POP DE
	POP AF
	RET



;********************************************************************
; Permet de libérer une zone mémoire
;
; En entrée
;       HL <=> Adresse du pointeur de la zone mémoire
;	BC <=> Taille en octet
; En sortie
;       HL <=> 0 si la zone mémoire a été libérée
; Registres affectés
;	HL
; Remarques
;	- Lorsque la libération de la mémoire n'est pas possible, deux
;	  beep sont émis.
;

SYS_FREE_MEMORY:

	PUSH HL

	; Vérification si la table virtuelle n'est pas complètement vide
	LD HL, (VIRTUAL_TABLE_OFFSET)
	SBC HL, BC
	; Si HL >= 0 c'est que la libération d'une zone mémoire est possible
	JP nc, _SYS_FREE_MEMORY_1
	CALL SYS_BEEP
	CALL SYS_BEEP
	POP HL
	RET

_SYS_FREE_MEMORY_1

	LD (VIRTUAL_TABLE_OFFSET), HL
	POP HL
	LD HL, 0

_SYS_FREE_MEMORY_END:

	RET





;********************************************************************
; Affichage de la démo graphique
;
DEMO:

	PUSH AF
	PUSH BC
	PUSH DE
	PUSH HL

	;------------------------
	; Rectangle
	LD BC, 0
	LD HL, 159
	LD D, 0
	LD E, 199
	LD A, 1	; Couleurs
			;	en mode 0 de 0 à 15
			;	en mode 1 de 0 à 4
			;	en mode 2 de 0 à 1
	CALL GRAPH_RECTANGLE

	;------------------------
	; Rectangle
	LD BC, 10
	LD HL, 100
	LD D, 10
	LD E, 50
	LD A, 3		; Couleurs
			;	en mode 0 de 0 à 15
			;	en mode 1 de 0 à 4
			;	en mode 2 de 0 à 1
	CALL GRAPH_RECTANGLE

	;------------------------
	; Rectangle plein
	LD BC, 11
	LD HL, 99
	LD D, 11
	LD E, 49
	LD A, 2		; Couleurs
			;	en mode 0 de 0 à 15
			;	en mode 1 de 0 à 4
			;	en mode 2 de 0 à 1
	CALL GRAPH_RECTANGLE_FILLED

	;------------------------
	; Les OU exclusifs
	LD BC, 0
	LD HL, 159
	LD D, 20
	CALL GRAPH_LINE_H_XOR
		     
	LD D, 0
	LD E, 199
	LD BC, 90
	CALL GRAPH_LINE_V_XOR



	;------------------------------
	; Affichage de lignes obliques
	LD A, 3	; Couleurs
			;	en mode 0 de 0 à 15
			;	en mode 1 de 0 à 4
			;	en mode 2 de 0 à 1
	LD HL, 0

_DEMO_1

	LD BC, 0
	LD DE, 10
	ADD HL, DE
	LD D, 0
	LD E, 199

	CALL GRAPH_LINE

	DEC A	; Couleur suivante
	JP nz, _DEMO_1


	;-----------------------------------------------------------
	; Affichage de lignes obliques en appliquant un OU exclusif
	LD A, 5		; Tracé de 5 Lignes
	LD HL, 35

_DEMO_2

	LD BC, 35
	LD DE, 10
	ADD HL, DE
	LD D, 0
	LD E, 199

	CALL GRAPH_LINE_XOR

	DEC A	; Couleur suivante
	JP nz, _DEMO_2



	; Affichage d'un rectangle plein bleu
	LD BC, 0
	LD HL, 40
	LD D, 0
	LD E, 50
	LD A, 1		; Couleurs
			;	en mode 0 de 0 à 15
			;	en mode 1 de 0 à 4
			;	en mode 2 de 0 à 1
	CALL GRAPH_RECTANGLE_FILLED

_DEMO_END

	POP HL
	POP DE
	POP BC
	POP AF

	RET


