BITS 	32
org 	0x06000

%define RAM_VIDEO 	0xb8000
%define INTGATE  	0x8E00	
%define IDTBASE  	0x800	;addr. physique où doit resider la IDT
%define IDTSIZE  	0xFF	;nombre max. de descripteurs dans la table
%define INTERRUPTION_PIC_MAITRE 0x20
%define INTERRUPTION_PIC_ESCLAVE 0x70

;On va copier les infos VESA du chargeur d'amorçage dans nos données
	mov esi, 512 + (0x07c0<<4)
	mov edi, VESASignature
	mov ecx, 512/4
	rep movsd

;	mov ax, 8*2
;	mov es, ax
;	mov ds, ax
	xor eax, eax
	mov esi, 1024 + (0x07c0<<4)
	mov edi, NbEntreesMemoire
	movsw
	xor ecx, ecx
	mov cx, word[NbEntreesMemoire]
	mov eax, ecx
	shl ecx, 1
	add ecx, eax
	shl ecx, 1
	rep movsd

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Initialisation du PIC				;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
init_pic:
	mov al, 0x11	; Initialisation de ICW1
	out 0x20, al	; maître
	out 0xA0, al	; esclave

	mov al, INTERRUPTION_PIC_MAITRE  ; Initialisation de ICW2
	out 0x21, al	; maître, vecteur de départ = 32
	mov al, INTERRUPTION_PIC_ESCLAVE  
	out 0xA1, al	; esclave, vecteur de départ = 96

	mov al, 0x04	; initialisation de ICW3
	out 0x21, al
	mov al, 0x02	; esclave
	out 0xA1, al

	mov al, 0x05	; initialisation de ICW4
	out 0x21, al
	mov al, 0x01
	out 0xA1, al

	xor al, al		; masquage des interruptions
	out 0x21, al
	out 0xA1, al
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Fin de l'initialisation du PIC		;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Création d'une table des vecteurs d'interruption pointant sur un simple EOI (End Of Interrupt)	;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; IDT : Interrupt Descriptor Table
;;
;; Structure : http://fr.wikipedia.org/wiki/Interrupt_Descriptor_Table
;; mot : les 16 bits les plus faibles de l'offset de la fonction (gestionnaire d'interruption ou d'exception) associée à l'interruption
;; mot : le sélecteur du segment de code, donc l'adresse du descripteur de code dans la GDT
;; 1 bit : drapeau IF (sur "1" pour activer le masquage des interruptions masquables)
;; 2 bits : DPL, de 0 à 3 inclus, qui indique le niveau de privilèges requis pour appeler l'interruption (0 est le plus élevé)
;; 1 bit : doit être mis à 0
;; 4 bits : le type d'interruption (porte d'interruption, de trappe ou de tâche)
;; 8 bits : réservé pour un futur usage (doit être à 0)
;; mot : les 16 bits les plus hauts de l'offset de la fonction associée à l'interruption
;;
;;   7                           0
;;+---+---+---+---+---+---+---+---+
;;| P |  DPL  | S |    GateType   |
;;+---+---+---+---+---+---+---+---+
;;P 	7	 Present 	 can be set to 0 for unused interrupts or for Paging.
;;DPL 	6,5 	Descriptor Privilege Level 	Gate call protection. Specifies which privilege Level the calling Descriptor minimum should have. So hardware and CPU interrupts can be protected from beeing called out of userspace.
;;S 	4 	Storage Segment 	= 0 for interrupt gates.
;;Typ 	0..3 	Gate Type 0..3 	Possible IDT gate types :
;;0b0101 	0x5 	5 	80386 32 bit Task gate
;;0b0110 	0x6 	6 	80286 16-bit interrupt gate
;;0b0111 	0x7 	7 	80286 16-bit trap gate
;;0b1110 	0xE 	14 	80386 32-bit interrupt gate
;;0b1111 	0xF 	15 	80386 32-bit trap gate
;; Pour nous : les bits indiqués seront 00000000(forcément)10001110, à passer en bigendian
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
	mov eax, IDTBASE 				; Adresse de l'IDT
	mov ebx, interruptionParDefaut 	; On va remplir toute la table avec l'interruption par défaut : bx contient les bits de poids faible
	mov ecx, IDTSIZE				; Nombre de vecteurs d'interruption
	call metInterruptionNFois

; On remplace les vecteurs qui nous intéressent par leur vraie adresse de fonction.
	mov eax, IDTBASE + (INTERRUPTION_PIC_MAITRE * 8) ; L'adresse dans la table est égale à AdresseDeBase + NuméroDeL'interruption * TailleD'unDescripteur.
	mov ebx, interruptionPICMaitreParDefaut
	mov ecx, 8
	call metInterruptionNFois
	mov eax, IDTBASE + (INTERRUPTION_PIC_ESCLAVE * 8) ; L'adresse dans la table est égale à AdresseDeBase + NuméroDeL'interruption * TailleD'unDescripteur.
	mov ebx, interruptionPICEsclaveParDefaut
	mov ecx, 8
	call metInterruptionNFois

; On remplace les vecteurs qui nous intéressent par leur vraie adresse de fonction.
	mov eax, IDTBASE + 0x21*8;(INTERRUPTION_PIC_MAITRE + 1) * 8 ; Le clavier a l'IRQ1.
	mov ebx, interruptionClavier
	mov ecx, 1
	call metInterruptionNFois

	mov eax, IDTBASE + INTERRUPTION_PIC_MAITRE * 8 ; L'IRQ0, un timer.
	mov ebx, interruptionTimer
	mov ecx, 1
	call metInterruptionNFois
	
	lidt [idtptr]	; charge l'idt
	sti

;	mov edi, chaine
;	xor eax, eax
;	mov eax, dword[FlatMemory]
;	mov ebx, 16
;	mov cl, 1
;	mov ch, 0
;	call nombreVersChaine
	
;	mov esi, chaine
;	call afficheChaine
;	jmp $
;	mov edi, clavier
;	call litChaine
	mov cx, 8*3		;En route pour le 3ème segment
	mov es, cx
	call nettoyageEcran

;	mov dword [couleurPoint], 0x0F0F0F0F
;	xor ecx, ecx
;	mov cx, [XResolution]
;toutEcran:
;	push ecx
;	mov ebx, ecx
;	dec ebx
;	shl ebx, 16
;	xor ecx, ecx
;	mov cx, [YResolution]
;ligneVerticale:
;	mov eax, ecx
;	dec eax
;	add eax, ebx
;	call metPixel
;	loop ligneVerticale
;	pop ecx
;	loop toutEcran

	mov dword [couleurPoint], 0xFFFFFFFF
	mov eax, 0x00100000
	mov ebx, 0x001A0000
    call afficheLigne
	mov eax, 0x000C0000
	mov ebx, 0x000C000A
	call afficheLigne
	mov eax, 0x000E000A
	mov ebx, 0x000E0000
	call afficheLigne
	mov eax, 0x001A000A
	mov ebx, 0x0010000A
	call afficheLigne
	mov eax, 0x01000100
	mov ebx, 0x01800130
	call afficheLigne
	mov ebx, 0x018000D0
	call afficheLigne
	mov ebx, 0x01300180
	call afficheLigne
	mov ebx, 0x01300080
	call afficheLigne
	mov ebx, 0x00800130
	call afficheLigne
	mov ebx, 0x008000D0
	call afficheLigne
	mov ebx, 0x00D00180
	call afficheLigne
	mov ebx, 0x00D00080
	call afficheLigne

	mov cx, 8*2		;En route pour le 2e segment
	mov es, cx
	mov dword [curseur], 0
	mov esi, chaine
	call afficheChaine
	mov edi, chaine
	xor eax, eax
	mov ax, word [NbEntreesMemoire]
	mov ebx, 10
	mov cl, 1
	mov ch, 8
	call nombreVersChaine
	mov esi, chaine
	call afficheChaine
	mov esi, DonneesMemoire
	mov dword [curseur], 16
	mov cx, word [NbEntreesMemoire]
	mov ebx, 16
s5:
	push ecx
	mov ecx, 6
s1:
	push ecx
	lodsd
	push esi
	mov edi, chaine
	mov cl, 1
	mov ch, 8
	call nombreVersChaine
	mov esi, chaine
	call afficheChaine
	pop esi
	pop ecx
	loop s1
;	lodsd
;	push esi
;	mov edi, chaine
;	call nombreVersChaine
;	mov esi, chaine
;	call afficheChaine
;	pop esi

	add word [curseur], 8
	mov word [curseur+2], 0
	pop ecx
;	add esi, 16
	loop s5
	
	mov ecx, 100
	add word [curseur], 8
	mov word [curseur+2], 0
	xor eax, eax
afficheAlphabet:
	call afficheCaractere
	inc al
	loop afficheAlphabet

	add word [curseur], 8
	mov word [curseur+2], 0
princ:
	mov bx, 8*2		;En route pour le 2ème segment
	mov es, bx
	mov edi, chaine
	call litChaine
	
	mov esi, chaine
suivant:
	lodsb
	or al, al
	jz fin
	
	call afficheCaractere
	jmp suivant

fin:
	jmp princ;$

;;Met l'interruption n fois dans l'idt
metInterruptionNFois:
	mov edx, ebx
	shr edx, 16
	mov [descripteurInterruption], bx	;bx contient les bits de poids faible
	mov [descripteurInterruption + 6], dx; et dx ceux de poids fort
	mov edi, eax
.remplitIDTPIC:
	mov esi, descripteurInterruption
	movsd
	movsd
	loop .remplitIDTPIC
	ret
	
interruptionPICMaitreParDefaut:
	mov al,0x20	; EOI (End Of Interrupt)
	out 0x20,al	; qu'on envoie au PIC
interruptionParDefaut:
	iret

interruptionPICEsclaveParDefaut:
	mov al,0x20	; EOI (End Of Interrupt)
	out 0xA0,al	; qu'on envoie au PIC
	iret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Gestion des interruptions clavier	;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
interruptionClavier:
	cli
	push ecx
	xor eax, eax
	xor ebx, ebx
.attendBuffer:
	in		al,		0x64	; lire statut
	test	byte al,1		; bus de sortie prêt ?
	jz		.attendBuffer	; non => boucler

	in		al, 	0x60	;Lit la touche pressée
	cmp		al, 	224		;224 est un code spécial, ça veut dire qu'il y a autre chose derrière, mais pour l'instant on s'en fiche
	je		.attendBuffer	;On va donc lire la suite

	mov bl, al
	shr bl, 3; On divise le code par 8 pour savoir dans quel octet il se situe
	push eax	; On sauve le caractère dans la pile
	mov cl, 8
	div cl		; On le divise par 8
	mov cl, ah	; Pour une division par 8 bits, le reste est dans AH
	pop eax
	mov edx, 1
	shl dl, cl
	add ebx, touchesActives ;C'est l'adresse de l'octet contenant ce qui nous intéresse
	cmp		al,		128		;Les touches appuyées ont un code inférieur à 128, les touches relâchées, c'est le même code qu'appuyées plus 128
	jb		.stockeActif
	sub		al,		128
	sub		ebx,	128/8
	not dl
	and byte[ebx], dl
	jmp .suite
.stockeActif:
	or byte[ebx], dl	; Un OU met le bit à 1, un NOT AND le mettra à 0
	mov [derniereTouche], al

.suite:
	in 		al, 	0x61
	or		al, 	130
	out 	0x61, 	al		;Dit à l'ordi qu'une touche a été pressée

	and 	al,		127
	out 	0x61,	al		;Reinitialisation terminée
 
    sti
	pop ecx
	jmp 	interruptionPICMaitreParDefaut

touchesActives: ;Il me faut 128 bits (à la louche) pour stocker les touches actives, soit, 128/8 = 16 octets, soit 4 doubles mots
	dd 0, 0, 0, 0
derniereTouche:
	db 0
traductionASCII:
;	db Inconnu,Echap,'1','2','3','4','5','6','7','8','9','0','.','+',Espace arrière,Tab
;	db 'a','z','e','r','t','y','u','i','o','p','^','$',Entrée,Ctrl,'q','s'
;	db 'd','f','g','h','j','k','l','m','%','²',demiShiftGauche,'*','w','x','c','v'
;	db 'b','n',',',';',':','!',demiShiftDroit,ImprEcran,Alt&AltGr,' ',Verr.Maj.,F1,F2,F3,F4,F5
;	db F6,F7,F8,F9,F10,Verr.Num.&Pause,Arretdéfil,home,Haut,PgUp,-,Gauche,5,Droite,+,Fin
;	db Bas,PgDw,Inser,Suppr,Inconnu,Inconnu,'<',F11,F12; 89 caractères gérés
	db  00, 48, 02, 03, 04, 05, 06, 07, 08, 09, 10, 01, 37, 38,100,101
	db  11, 36, 15, 28, 30, 35, 31, 19, 25, 26, 39, 40,102,103, 27, 29
	db  14, 16, 17, 18, 20, 21, 22, 23, 41, 47,104, 42, 33, 34, 13, 32
	db  12, 24, 43, 44, 45, 46,105, 70, 50, 51,107, 52, 49, 53, 54, 55
	db  56, 57, 58, 59, 60, 61, 62, 63,108, 65, 64,109, 66,110, 67, 68
	db 111, 69,112,113, 00, 00, 71, 72, 73;89
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Fin gestion interruptions clavier	;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

interruptionTimer:
	push eax
	push ecx
	push ebx
	push es

	mov 	bl, 	[.courant]
	dec 	bl
	or 		bl, 	bl
	jnz .depile
	mov 	ax, 	8*3		;En route pour le 3ème segment
	mov 	es, 	ax
	;clignotement curseur
	xor 	eax, 	eax
	mov 	al, 	[.prochainCaractere]
	mov 	ecx, 	[curseur]
	call afficheCaractere
	mov 	[curseur], ecx
	mov 	bl, 	[.vitesse]
	or 		al, 	al
	jnz .plein
	mov 	byte [.prochainCaractere], 51
	jmp .depile
.plein:
	mov 	byte [.prochainCaractere], 0
.depile:
	mov 	[.courant], bl
	pop es
	pop ebx
	pop ecx
	pop eax
	jmp		interruptionPICMaitreParDefaut
.prochainCaractere: db 0
.vitesse: db 5
.courant: db 5

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Synopsis: Affiche une chaîne de caractères se terminant par NULL	;;
; Entree:   SI -> pointe sur la chaîne à afficher					;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
afficheChaine:
	push	eax
;	push	ebx
;	push	ecx
	xor		eax, eax
;	xor		ebx, ebx
;	mov 	cx, [curseurX]
;	mov		al, ch
;	shl		al, 2
;	add		al, ch
;	shl		ax, 5	;	On vient de faire une multiplication par 160.
;	mov		bl, cl
;	shl		bl, 1
;	add		ax, bx
;	mov		bx, ax
;	add		ebx, RAM_VIDEO
.caractereSuivant:
	lodsb			; ds:esi -> al
	or		al, al	; fin chaine ?
	jz		.fin
;	cmp 	cl, 80	; Le curseur est en fin de chaîne
;	jne		.continuer
;	xor		cl, cl
;	inc		ch
;.continuer:
	cmp		al, 102
	jne 	.ligneOK
	add		dword [curseur], 8
	mov		dword [curseur + 2], 0
;	mov 	al, cl
;	shl		al, 1
;	sub		ebx, eax
;	mov		cl, 0
;	inc		ch
;	add		ebx, 160
	jmp		.caractereSuivant
.ligneOK:
;	cmp		ch, 25
;	jb		.scrollOK
;	push	esi
;	mov		esi, RAM_VIDEO + 160;On décale tout d'une ligne
;	mov		edi, RAM_VIDEO
;	push 	ecx
;	mov		ecx, 160*24/4
;	rep		movsd
;	mov 	ecx, 40;On vide la dernière ligne
;	push 	eax
;	xor 	eax, eax
;	rep		stosd
;	pop		eax
;	pop		ecx
;	pop		esi
;	dec		ch
;	sub 	ebx, 160
;	jmp .ligneOK
	call afficheCaractere
;.scrollOK:
;	mov 	byte [ebx], al
;	inc 	ebx
;	mov 	byte [ebx], 0x07
;	inc 	ebx
;	inc 	cl
	jmp 	.caractereSuivant
.fin:
;	mov		[curseurX], cx; Sauvegarde de la position du curseur
;	pop 	ecx
;	pop 	ebx
	pop 	eax
	ret
;curseurX:
;	db 0
;curseurY:
;	db 0

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; nombreVersChaine													;;
;;------------------------------------------------------------------;;
;; Ecrit dans la chaîne pointée par EDI le nombre contenu dans EAX	;;
;; si CL est à un, on écrit un caractère terminal					;;
;; CH contient le nombre minimal de caractères à utiliser			;;
;; EBX contient la base												;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
nombreVersChaine:
	push 	edx
	push 	ecx
	xor		cl, cl
.stocke_digit:
	xor 	edx, edx
	div 	ebx
	push 	edx 			; Sauve le reste dans la pile
	inc 	cl
	or 		eax, eax		; Si le quotient n'est pas nul
	jne 	.stocke_digit	; on recommence
;Les digits sont stockés dans la pile
.ajout_zero:
	cmp 	ch, cl
	jbe		.clearCH
	push 	0;51-74+10		; Nombre magique permettant de remplir avec des espaces
	inc 	cl
	jmp 	.ajout_zero
.clearCH:
	xor 	ch, ch
;Affichage du chiffre : On en affiche au moins un : zéro
.affiche_digit:
	pop 	eax
;	cmp 	al, 10
;	jae 	.dixPlus
	add 	al, 1
	stosb 					; met AL dans l'octet pointé par EDI et incrémente EDI
;	jmp 	.boucle_digit
;.dixPlus:					; Pour les bases à plus de 10 chiffres, on utilise l'alphabet
;	add 	al, 74 - 10
;	stosb
;	jmp 	.boucle_digit
;.boucle_digit:
	loop 	.affiche_digit
	pop 	ecx 			; on récupère le paramètre cx
	test 	cl, 0b1 		; s'il est à 1, on écrit un caractère terminal
	jz 		.depile
	mov 	byte [edi], 0
.depile:
	pop 	edx
ret

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;	Fin nombreVersChaine											;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; litChaine														;;
;;------------------------------------------------------------------;;
;; Ecrit dans la chaîne pointée par EDI les caractères écrits au 	;;
;; clavier, jusqu'à un retour chariot. 								;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
litChaine:
	push 	eax
	push 	ebx

	mov 	byte [derniereTouche], 0
.attend_clavier:
	xor 	eax, eax
	cmp 	byte [derniereTouche], 0
	jz .attend_clavier
	mov 	al, [derniereTouche]
	mov 	byte [derniereTouche], 0

	mov 	ebx, traductionASCII
	add 	ebx, eax
	mov 	al, [ebx]

	cmp 	al, 100			;Traitement de l'espace arrière
	jne .testTab
	dec 	edi
	mov al, 51
	call afficheCaractere
	sub	dword [curseur], 0x100000
	jmp .attend_clavier

.testTab:
	cmp 	al, 101			;Traitement de la tabulation avant
	jne .testEntree
	dec		edi
	mov 	eax, (51<<24)+(51<<16)+(51<<8)+51
	stosd
	add		word [curseur+2], 3

.testEntree:
	cmp 	al, 102
	je .fin_attend_clavier

	test byte[touchesActives + 5], 0b100 ;On teste le shift gauche enfoncé
	jnz .shift
	test byte[touchesActives + 6], 0b1000000 ;On teste le shift droit enfoncé
	jz .RAS
.shift:
	cmp al, 104			;On ne stocke pas un Shift gauche comme touche
	je .attend_clavier
	cmp al, 105			;On ne stocke pas un Shift droit comme touche
	je .attend_clavier

	add al, 73
.RAS:
	stosb

	call afficheCaractere

	jmp .attend_clavier
.fin_attend_clavier:
	mov 	al, 0
	stosb
	mov al, 51
	call afficheCaractere
	add		word [curseur], 7
	mov		word [curseur+2], 0
	dec 	edi

    pop 	ebx
    pop 	eax
    ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Fin litChaine													;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; nettoyageEcran													;;
;;------------------------------------------------------------------;;
;; Colorie tout l'écran avec la couleur stockée dans couleurDefaut.	;;
;; ES doit contenir le descripteur de segment de l'écran.			;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
nettoyageEcran:
	push edi
	push eax
	push ecx
	
	xor eax, eax
	xor ecx, ecx
	xor edi, edi
	mov cx, [YResolution]
	mov ax, [XResolution]
	mul ecx	; Nombre de points total
	mov ecx, eax
	mov eax, [couleurDefaut]
	rep stosd

	pop ecx
	pop eax
	pop edi
	ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Fin nettoyageEcran												;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; metPixel															;;
;;------------------------------------------------------------------;;
;; Colorie le pixel dont la position est dans EAX (mot haut : X,	;;
;; mot bas : Y) avec la couleur contenue dans couleurPoint			;;
;; ES doit contenir le descripteur de segment de l'écran.			;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
metPixel:
	push edi
	push ecx
	push eax
	push ebx
	push edx
	
	mov ebx, eax
	and eax, 0xFFFF
	shr ebx, 16
	xor ecx, ecx
	mov cx, [XResolution]
	mul ecx					; On fait une multiplication 32 bits à partir de valeurs de 16 bits.
	add eax, ebx
	shl eax, 2
	mov edi, eax
	mov eax, [couleurPoint]
	stosd

.retour:
	pop edx
	pop ebx
	pop eax
	pop ecx
	pop edi
	ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Fin metPixel														;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; afficheLigne														;;
;;------------------------------------------------------------------;;
;; Dessine un segment de droite entre le point stocké dans EAX et 	;;
;; celui stocké dans EBX (mot haut : X,	mot bas : Y) avec la 		;;
;; couleur contenue dans couleurPoint								;;
;; ES doit contenir le descripteur de segment de l'écran.			;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Y2: dd 0
afficheLigne:
	push esi
	push eax
	push ebx
	push ecx
	push edx
	push edi

	cmp 	eax, ebx	;On travaille dans le sens de abscisses positives
	jbe .ordreOK
	xchg 	eax, ebx	;On inverse si ce n'est pas le cas
.ordreOK:
	mov 	[Y2], ebx	;On stocke le point d'arrivée
	sub 	ebx, eax	;On calcule les longueur à parcourir en X et Y
	mov 	cx, bx		;deltaY
	shr 	ebx, 16		;deltaX
	or 		bx, bx		;Si deltaX est nul, on sera sur une ligne verticale
	jz .ligneVerticale
	or		cx, cx		;Si deltaY est nul, on sera sur une ligne horizontale
	jnz .test_deltaY
	mov 	cx, bx		;CX contient le nombre de pixels à afficher
	mov 	ebx, 0x10000;Incrément de 1 pixel vers la droite
	jmp .avance_H_V
.ligneVerticale:
	mov 	ebx, 0x00001;Incrément de 1 pixel vers le bas
.avance_H_V:
	call metPixel		;Affichage du pixel
	add eax, ebx		;Incrément
	loop .avance_H_V
.fin_afficheLigne:
	call metPixel		;Affichage du dernier pixel
	pop edi
	pop edx
	pop ecx
	pop ebx
	pop eax
	pop esi
	ret

.test_deltaY:
	push 0x10000		;Incrément de 1 pixel vers la droite
	push 1				;Incrément de 1 pixel vers le bas
	jns .suite			;Si deltaY est positif, on est standard
	neg cx				;Sinon, on l'oppose, ainsi que l'incrément en Y
	neg dword[esp]
.suite:
	cmp bx, cx			;Si deltaY>deltaX
	jae .principal
	xchg bx, cx			;On échange deltaY et deltaX
	mov edx, [esp + 4]	;Ainsi que les incréments
	xchg edx, [esp]
	mov [esp + 4], edx
.principal:				;Et on continue normalement
	mov dx, bx			;DX contient l'écart
.boucle:
	call metPixel
	sub dx, cx			;On enlève deltaY
	cmp dx, cx			;Si on est inférieur ou égal à deltaY
	ja .affichage
	add eax, [esp]		;On applique l'incrément en Y
	add dx, bx			;On ajoute deltaX à l'écart
.affichage:
	add eax, [esp + 4]	;On applique l'incrément en X
	cmp eax, [Y2]		;Sommes-nous arrivés ?
	jb .boucle
	pop edx				;On s'en va proprement
	pop edx
	jmp .fin_afficheLigne
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Fin afficheLigne													;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; afficheCaractere													;;
;;------------------------------------------------------------------;;
;; Dessine un caractère au point stocké dans EAX (mot haut : X,		;;
;; mot bas : Y) avec la couleur contenue dans couleurPoint.			;;
;; ES doit contenir le descripteur de segment de l'écran.			;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
afficheCaractere:
	push es
	push edx
	push esi
	push edi
	push eax
	push ebx
	push ecx

	mov ecx, 7			;7 lignes par caractère
	mul ecx
	mov esi, Alphabet	; adresse de la lettre
	add esi, eax		; si contient l'adresse de la lettre

	mov eax, [curseur]
	mov bx, 8*3		;En route pour le 2ème segment
	mov es, bx
	mov ebx, eax		;EBX stocke le pixel courant
	and eax, 0xFFFF
	shr ebx, 16
;	xor ecx, ecx
	mov cx, [XResolution]
	mul ecx					; On fait une multiplication 32 bits à partir de valeurs de 16 bits.
	add eax, ebx
	shl eax, 2
	mov edi, eax
	mov ecx, 7

.colonne:
	push ecx
	mov dl, 0b10000000
	mov ecx, 8; On affiche 8 colonnes
	lodsb
	mov bl, al
.ligne:
	test bl, dl
	jnz .point
	mov eax, [couleurDefaut]
	jz .suite
.point:
	mov eax, [couleurPoint]
.suite:
	stosd
	shr dl, 1
	loop .ligne
	pop ecx
	xor eax, eax
	mov ax, [XResolution]
	shl eax, 2
	add edi, eax
	sub edi, 32
	loop .colonne
	add dword [curseur], 0x80000

	pop ecx
	pop ebx
	pop eax
	pop edi
	pop esi
	pop edx
	pop es
	ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Fin afficheCaractere												;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;--------------------------------------------------------------------
idtptr:
	dw	IDTSIZE << 3			; limite
	dd	IDTBASE					; base

descripteurInterruption:
	dw 0, 1 * 8, INTGATE, 0

%include "alphabet.asm"

chaine:
	db 	83,51,11,19,51,19,13,19,51,31,24,15,51,29,31,26,15,28,12,15,51,16,25,24,13,30,19,25,24,51,14,51,11,16,16,19,13,18,11,17,15,51,14,15,51,30,15,34,30,15,51,27,31,19,51,102,0
	;"J'ai ici une superbe fonction d'affichage de texte qui ne saurait planter sur un malheureux saut ", 13, "de ligne", 13, 0
clavier:
	db	"12345678 ", 0

;mode_souhaite: dw 0x0013
;maxResol: dw 0
couleurDefaut: db 0x00, 0x1F, 0x2F, 0x2F; ARBG
couleurPoint: db 0x00, 0x00, 0x7F, 0x00; BGRA
;octetsParPixel: db 4
;bloc_courant: db 0
curseur: dw 0
;Informations du pilote VESA
VESASignature: times 4 db 0; 'VESA', signature de 4 octets
VESAVersion: dw 0; numéro de version de VBE
OEMStringPtr: dd 0; Pointeur vers le nom de l'OEM
Capabilities: dd 0; Possibilités de la carte graphique
VideoModePtr: dd 0; Pointeur vers les modes accessibles
TotalMemory: dw 0; Nombre de blocs mémoire de 64ko
reserved: times 236 db 0; Complément à 256 octets, taille du bloc
;Informations d'un mode vidéo
ModeAttributes: dw 0; Attributs du mode
WinAAttributes: db 0; Attibuts de la fenêtre A
WinBAttributes: db 0; Attibuts de la fenêtre B
WinGranularity: dw 0; Granularité de la fenêtre en ko
WinSize: dw 0; Taille de la fenêtre en ko
WinASegment: dw 0; Segment de la fenêtre A
WinBSegment: dw 0; Segment de la fenêtre B
WinFuncPtr: dd 0; Pointeur vers la fonction "de fenêtrage"
BytesPerScanLine: dw 0; Octets par "scanline"
XResolution: dw 0; Résolution horizontale
YResolution: dw 0; Résolution vertical
XCharSize: db 0; Largeur d'un caractère
YCharSize: db 0; Hauteur d'un caractère
NumberOfPlanes: db 0; Nombre de plans mémoire
BitsPerPixel: db 0; Bits par pixel
NumberOfBanks: db 0; Nombre de banques de style CGA
MemoryModel: db 0; Type de modèle mémoire
BankSize: db 0; Taille des banques de style CGA
NumberOfImagePages: db 0; Nombre de pages image
res1: db 0; Reservé
RedMaskSize: db 0; Taille du masque rouge en couleur directe
RedFieldPosition: db 0; Position du bit faible du masque rouge
GreenMaskSize: db 0; Taille du masque vert en couleur directe
GreenFieldPosition: db 0; Position du bit faible du masque vert
BlueMaskSize: db 0; Taille du masque bleu en couleur directe
BlueFieldPosition: db 0; Position du bit faible du masque bleu
RsvdMaskSize: db 0; Taille du masque réservé en couleur directe
RsvdFieldPosition: db 0;  Position du bit faible du masque réservé
DirectColorModeInfo: db 0; Attributs du mode de couleur directe
FlatMemory: dd 0
res2: times 212 db 0; Complément à 256 octets, taille du bloc
NbEntreesMemoire: dw 0
DonneesMemoire: 
dw 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF
dw 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF
dw 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF
dw 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF
dw 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF
times 4*1024-($-$$) db 0
