From ed1e0cf4c8f1b3abd22e3148c4f298b8be39bd41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Georges=20Dup=C3=A9ron?= Date: Fri, 15 Apr 2011 01:14:48 +0200 Subject: [PATCH] Initial commit. --- .gitignore | 2 + Makefile | 12 + src/demarrage/grub/menu.lst | 5 + src/demarrage/grub/stage1 | Bin 0 -> 512 bytes src/demarrage/grub/stage2 | Bin 0 -> 99838 bytes src/demarrage/grub/stage2_eltorito | Bin 0 -> 99942 bytes src/demarrage/grub/stage2_eltorito_vbe | Bin 0 -> 106940 bytes src/inclusions/algo/math/math.h | 36 +++ .../demarrage/multiboot/multiboot.h | 244 +++++++++++++++ .../interfaceUtilisateur/clavier/clavier.h | 7 + .../interfaceUtilisateur/console/console.h | 116 ++++++++ .../interfaceUtilisateur/demo/demo.h | 6 + .../interfaceUtilisateur/police/police.h | 10 + src/inclusions/math.h | 6 + src/inclusions/modeleModule.h | 7 + src/inclusions/module.h | 62 ++++ src/inclusions/pc/gdt/gdt.h | 96 ++++++ src/inclusions/pc/idt/idt.h | 64 ++++ src/inclusions/pc/io/io.h | 20 ++ src/inclusions/pc/irq/irq.h | 107 +++++++ src/inclusions/pc/kbc/kbc.h | 35 +++ src/inclusions/pc/pit/pit.h | 84 ++++++ src/inclusions/pc/sourisPS2/sourisPS2.h | 146 +++++++++ .../pc/vesaGraphique/vesaGraphique.h | 22 ++ src/inclusions/pc/vgaTexte/vgaTexte.h | 38 +++ .../recherche/dichotomique/dichotomique.h | 9 + src/inclusions/stockage/ata/ata.h | 53 ++++ src/inclusions/string.h | 23 ++ src/inclusions/temps/temps/temps.h | 26 ++ src/inclusions/tri/tas/tas.h | 8 + src/inclusions/types.h | 59 ++++ src/makefiles/affichage.makefile | 42 +++ src/makefiles/commandes.makefile | 37 +++ src/makefiles/fichiersDossiers.makefile | 37 +++ src/makefiles/regles.makefile | 53 ++++ src/modules/algo/math/math.c | 39 +++ src/modules/demarrage/multiboot/multiboot.S | 31 ++ src/modules/demarrage/multiboot/multiboot.c | 214 ++++++++++++++ .../interfaceUtilisateur/clavier/clavier.c | 26 ++ .../interfaceUtilisateur/console/console.c | 245 +++++++++++++++ src/modules/interfaceUtilisateur/demo/demo.c | 278 ++++++++++++++++++ .../interfaceUtilisateur/police/8x15/,.png | Bin 0 -> 98 bytes .../interfaceUtilisateur/police/8x15/..png | Bin 0 -> 96 bytes .../interfaceUtilisateur/police/8x15/0.png | Bin 0 -> 113 bytes .../interfaceUtilisateur/police/8x15/1.png | Bin 0 -> 105 bytes .../interfaceUtilisateur/police/8x15/2.png | Bin 0 -> 119 bytes .../interfaceUtilisateur/police/8x15/3.png | Bin 0 -> 114 bytes .../interfaceUtilisateur/police/8x15/4.png | Bin 0 -> 110 bytes .../interfaceUtilisateur/police/8x15/5.png | Bin 0 -> 115 bytes .../interfaceUtilisateur/police/8x15/6.png | Bin 0 -> 118 bytes .../interfaceUtilisateur/police/8x15/7.png | Bin 0 -> 110 bytes .../interfaceUtilisateur/police/8x15/8.png | Bin 0 -> 108 bytes .../interfaceUtilisateur/police/8x15/8x15.fnt | 256 ++++++++++++++++ .../interfaceUtilisateur/police/8x15/9.png | Bin 0 -> 116 bytes .../interfaceUtilisateur/police/8x15/A.png | Bin 0 -> 108 bytes .../interfaceUtilisateur/police/8x15/B.png | Bin 0 -> 113 bytes .../interfaceUtilisateur/police/8x15/C.png | Bin 0 -> 114 bytes .../interfaceUtilisateur/police/8x15/D.png | Bin 0 -> 113 bytes .../interfaceUtilisateur/police/8x15/E.png | Bin 0 -> 109 bytes .../interfaceUtilisateur/police/8x15/F.png | Bin 0 -> 106 bytes .../interfaceUtilisateur/police/8x15/G.png | Bin 0 -> 117 bytes .../interfaceUtilisateur/police/8x15/H.png | Bin 0 -> 101 bytes .../interfaceUtilisateur/police/8x15/I.png | Bin 0 -> 104 bytes .../interfaceUtilisateur/police/8x15/J.png | Bin 0 -> 107 bytes .../interfaceUtilisateur/police/8x15/K.png | Bin 0 -> 116 bytes .../interfaceUtilisateur/police/8x15/L.png | Bin 0 -> 98 bytes .../interfaceUtilisateur/police/8x15/M.png | Bin 0 -> 109 bytes .../interfaceUtilisateur/police/8x15/N.png | Bin 0 -> 109 bytes .../interfaceUtilisateur/police/8x15/O.png | Bin 0 -> 107 bytes .../interfaceUtilisateur/police/8x15/P.png | Bin 0 -> 108 bytes .../interfaceUtilisateur/police/8x15/Q.png | Bin 0 -> 110 bytes .../interfaceUtilisateur/police/8x15/R.png | Bin 0 -> 112 bytes .../interfaceUtilisateur/police/8x15/S.png | Bin 0 -> 117 bytes .../interfaceUtilisateur/police/8x15/T.png | Bin 0 -> 102 bytes .../interfaceUtilisateur/police/8x15/U.png | Bin 0 -> 101 bytes .../interfaceUtilisateur/police/8x15/V.png | Bin 0 -> 105 bytes .../interfaceUtilisateur/police/8x15/W.png | Bin 0 -> 103 bytes .../interfaceUtilisateur/police/8x15/X.png | Bin 0 -> 109 bytes .../interfaceUtilisateur/police/8x15/Y.png | Bin 0 -> 103 bytes .../interfaceUtilisateur/police/8x15/Z.png | Bin 0 -> 112 bytes .../interfaceUtilisateur/police/8x15/a.png | Bin 0 -> 113 bytes .../interfaceUtilisateur/police/8x15/b.png | Bin 0 -> 110 bytes .../interfaceUtilisateur/police/8x15/c.png | Bin 0 -> 107 bytes .../police/8x15/curseur.png | Bin 0 -> 121 bytes .../interfaceUtilisateur/police/8x15/d.png | Bin 0 -> 109 bytes .../interfaceUtilisateur/police/8x15/e.png | Bin 0 -> 110 bytes .../police/8x15/espace.png | Bin 0 -> 90 bytes .../interfaceUtilisateur/police/8x15/f.png | Bin 0 -> 108 bytes .../interfaceUtilisateur/police/8x15/g.png | Bin 0 -> 108 bytes .../interfaceUtilisateur/police/8x15/h.png | Bin 0 -> 104 bytes .../interfaceUtilisateur/police/8x15/i.png | Bin 0 -> 100 bytes .../interfaceUtilisateur/police/8x15/j.png | Bin 0 -> 101 bytes .../interfaceUtilisateur/police/8x15/k.png | Bin 0 -> 109 bytes .../interfaceUtilisateur/police/8x15/l.png | Bin 0 -> 97 bytes .../interfaceUtilisateur/police/8x15/m.png | Bin 0 -> 99 bytes .../police/8x15/magickCPZzva | 0 .../police/8x15/magickILOpac | 0 .../police/8x15/magickNIygPK | 0 .../police/8x15/magickTAbVVp | 0 .../police/8x15/magickUbyoYb | 0 .../police/8x15/magickYmNcu2 | 0 .../police/8x15/magickcylYvt | 0 .../police/8x15/magickdVV9sC | 0 .../police/8x15/magickmas2Rl | 0 .../police/8x15/magicknw0TJ4 | 0 .../police/8x15/magickoVnTPK | 0 .../police/8x15/magickuHXNJE | 0 .../interfaceUtilisateur/police/8x15/n.png | Bin 0 -> 101 bytes .../interfaceUtilisateur/police/8x15/o.png | Bin 0 -> 105 bytes .../interfaceUtilisateur/police/8x15/p.png | Bin 0 -> 108 bytes .../interfaceUtilisateur/police/8x15/q.png | Bin 0 -> 109 bytes .../interfaceUtilisateur/police/8x15/r.png | Bin 0 -> 101 bytes .../interfaceUtilisateur/police/8x15/s.png | Bin 0 -> 109 bytes .../interfaceUtilisateur/police/8x15/t.png | Bin 0 -> 103 bytes .../interfaceUtilisateur/police/8x15/u.png | Bin 0 -> 98 bytes .../interfaceUtilisateur/police/8x15/v.png | Bin 0 -> 99 bytes .../interfaceUtilisateur/police/8x15/w.png | Bin 0 -> 97 bytes .../interfaceUtilisateur/police/8x15/x.png | Bin 0 -> 103 bytes .../interfaceUtilisateur/police/8x15/y.png | Bin 0 -> 106 bytes .../interfaceUtilisateur/police/8x15/z.png | Bin 0 -> 107 bytes .../interfaceUtilisateur/police/police.c | 32 ++ src/modules/modeleModule.c | 18 ++ src/modules/pc/gdt/gdt.c | 39 +++ src/modules/pc/idt/idt.S | 79 +++++ src/modules/pc/idt/idt.c | 90 ++++++ src/modules/pc/io/io.c | 13 + src/modules/pc/irq/irq.S | 53 ++++ src/modules/pc/irq/irq.c | 132 +++++++++ src/modules/pc/kbc/kbc.c | 73 +++++ src/modules/pc/pit/pit.c | 110 +++++++ src/modules/pc/sourisPS2/sourisPS2.c | 265 +++++++++++++++++ src/modules/pc/vesaGraphique/vesaGraphique.c | 109 +++++++ src/modules/pc/vgaTexte/vgaTexte.c | 52 ++++ src/modules/recherche/dichotomique.c | 62 ++++ src/modules/stockage/ata/ata.c | 18 ++ src/modules/temps/temps/temps.c | 49 +++ src/modules/tri/tas/tas.c | 63 ++++ src/scripts/creerImage.lds | 43 +++ src/scripts/creerModule.sh | 35 +++ src/scripts/creerPolice.sh | 6 + src/scripts/liste-chemins.lst | 4 + 141 files changed, 3906 insertions(+) create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 src/demarrage/grub/menu.lst create mode 100644 src/demarrage/grub/stage1 create mode 100644 src/demarrage/grub/stage2 create mode 100644 src/demarrage/grub/stage2_eltorito create mode 100644 src/demarrage/grub/stage2_eltorito_vbe create mode 100644 src/inclusions/algo/math/math.h create mode 100644 src/inclusions/demarrage/multiboot/multiboot.h create mode 100644 src/inclusions/interfaceUtilisateur/clavier/clavier.h create mode 100644 src/inclusions/interfaceUtilisateur/console/console.h create mode 100644 src/inclusions/interfaceUtilisateur/demo/demo.h create mode 100644 src/inclusions/interfaceUtilisateur/police/police.h create mode 100644 src/inclusions/math.h create mode 100644 src/inclusions/modeleModule.h create mode 100644 src/inclusions/module.h create mode 100644 src/inclusions/pc/gdt/gdt.h create mode 100644 src/inclusions/pc/idt/idt.h create mode 100644 src/inclusions/pc/io/io.h create mode 100644 src/inclusions/pc/irq/irq.h create mode 100644 src/inclusions/pc/kbc/kbc.h create mode 100644 src/inclusions/pc/pit/pit.h create mode 100644 src/inclusions/pc/sourisPS2/sourisPS2.h create mode 100644 src/inclusions/pc/vesaGraphique/vesaGraphique.h create mode 100644 src/inclusions/pc/vgaTexte/vgaTexte.h create mode 100644 src/inclusions/recherche/dichotomique/dichotomique.h create mode 100644 src/inclusions/stockage/ata/ata.h create mode 100644 src/inclusions/string.h create mode 100644 src/inclusions/temps/temps/temps.h create mode 100644 src/inclusions/tri/tas/tas.h create mode 100644 src/inclusions/types.h create mode 100644 src/makefiles/affichage.makefile create mode 100644 src/makefiles/commandes.makefile create mode 100644 src/makefiles/fichiersDossiers.makefile create mode 100644 src/makefiles/regles.makefile create mode 100644 src/modules/algo/math/math.c create mode 100644 src/modules/demarrage/multiboot/multiboot.S create mode 100644 src/modules/demarrage/multiboot/multiboot.c create mode 100644 src/modules/interfaceUtilisateur/clavier/clavier.c create mode 100644 src/modules/interfaceUtilisateur/console/console.c create mode 100644 src/modules/interfaceUtilisateur/demo/demo.c create mode 100644 src/modules/interfaceUtilisateur/police/8x15/,.png create mode 100644 src/modules/interfaceUtilisateur/police/8x15/..png create mode 100644 src/modules/interfaceUtilisateur/police/8x15/0.png create mode 100644 src/modules/interfaceUtilisateur/police/8x15/1.png create mode 100644 src/modules/interfaceUtilisateur/police/8x15/2.png create mode 100644 src/modules/interfaceUtilisateur/police/8x15/3.png create mode 100644 src/modules/interfaceUtilisateur/police/8x15/4.png create mode 100644 src/modules/interfaceUtilisateur/police/8x15/5.png create mode 100644 src/modules/interfaceUtilisateur/police/8x15/6.png create mode 100644 src/modules/interfaceUtilisateur/police/8x15/7.png create mode 100644 src/modules/interfaceUtilisateur/police/8x15/8.png create mode 100644 src/modules/interfaceUtilisateur/police/8x15/8x15.fnt create mode 100644 src/modules/interfaceUtilisateur/police/8x15/9.png create mode 100644 src/modules/interfaceUtilisateur/police/8x15/A.png create mode 100644 src/modules/interfaceUtilisateur/police/8x15/B.png create mode 100644 src/modules/interfaceUtilisateur/police/8x15/C.png create mode 100644 src/modules/interfaceUtilisateur/police/8x15/D.png create mode 100644 src/modules/interfaceUtilisateur/police/8x15/E.png create mode 100644 src/modules/interfaceUtilisateur/police/8x15/F.png create mode 100644 src/modules/interfaceUtilisateur/police/8x15/G.png create mode 100644 src/modules/interfaceUtilisateur/police/8x15/H.png create mode 100644 src/modules/interfaceUtilisateur/police/8x15/I.png create mode 100644 src/modules/interfaceUtilisateur/police/8x15/J.png create mode 100644 src/modules/interfaceUtilisateur/police/8x15/K.png create mode 100644 src/modules/interfaceUtilisateur/police/8x15/L.png create mode 100644 src/modules/interfaceUtilisateur/police/8x15/M.png create mode 100644 src/modules/interfaceUtilisateur/police/8x15/N.png create mode 100644 src/modules/interfaceUtilisateur/police/8x15/O.png create mode 100644 src/modules/interfaceUtilisateur/police/8x15/P.png create mode 100644 src/modules/interfaceUtilisateur/police/8x15/Q.png create mode 100644 src/modules/interfaceUtilisateur/police/8x15/R.png create mode 100644 src/modules/interfaceUtilisateur/police/8x15/S.png create mode 100644 src/modules/interfaceUtilisateur/police/8x15/T.png create mode 100644 src/modules/interfaceUtilisateur/police/8x15/U.png create mode 100644 src/modules/interfaceUtilisateur/police/8x15/V.png create mode 100644 src/modules/interfaceUtilisateur/police/8x15/W.png create mode 100644 src/modules/interfaceUtilisateur/police/8x15/X.png create mode 100644 src/modules/interfaceUtilisateur/police/8x15/Y.png create mode 100644 src/modules/interfaceUtilisateur/police/8x15/Z.png create mode 100644 src/modules/interfaceUtilisateur/police/8x15/a.png create mode 100644 src/modules/interfaceUtilisateur/police/8x15/b.png create mode 100644 src/modules/interfaceUtilisateur/police/8x15/c.png create mode 100644 src/modules/interfaceUtilisateur/police/8x15/curseur.png create mode 100644 src/modules/interfaceUtilisateur/police/8x15/d.png create mode 100644 src/modules/interfaceUtilisateur/police/8x15/e.png create mode 100644 src/modules/interfaceUtilisateur/police/8x15/espace.png create mode 100644 src/modules/interfaceUtilisateur/police/8x15/f.png create mode 100644 src/modules/interfaceUtilisateur/police/8x15/g.png create mode 100644 src/modules/interfaceUtilisateur/police/8x15/h.png create mode 100644 src/modules/interfaceUtilisateur/police/8x15/i.png create mode 100644 src/modules/interfaceUtilisateur/police/8x15/j.png create mode 100644 src/modules/interfaceUtilisateur/police/8x15/k.png create mode 100644 src/modules/interfaceUtilisateur/police/8x15/l.png create mode 100644 src/modules/interfaceUtilisateur/police/8x15/m.png create mode 100644 src/modules/interfaceUtilisateur/police/8x15/magickCPZzva create mode 100644 src/modules/interfaceUtilisateur/police/8x15/magickILOpac create mode 100644 src/modules/interfaceUtilisateur/police/8x15/magickNIygPK create mode 100644 src/modules/interfaceUtilisateur/police/8x15/magickTAbVVp create mode 100644 src/modules/interfaceUtilisateur/police/8x15/magickUbyoYb create mode 100644 src/modules/interfaceUtilisateur/police/8x15/magickYmNcu2 create mode 100644 src/modules/interfaceUtilisateur/police/8x15/magickcylYvt create mode 100644 src/modules/interfaceUtilisateur/police/8x15/magickdVV9sC create mode 100644 src/modules/interfaceUtilisateur/police/8x15/magickmas2Rl create mode 100644 src/modules/interfaceUtilisateur/police/8x15/magicknw0TJ4 create mode 100644 src/modules/interfaceUtilisateur/police/8x15/magickoVnTPK create mode 100644 src/modules/interfaceUtilisateur/police/8x15/magickuHXNJE create mode 100644 src/modules/interfaceUtilisateur/police/8x15/n.png create mode 100644 src/modules/interfaceUtilisateur/police/8x15/o.png create mode 100644 src/modules/interfaceUtilisateur/police/8x15/p.png create mode 100644 src/modules/interfaceUtilisateur/police/8x15/q.png create mode 100644 src/modules/interfaceUtilisateur/police/8x15/r.png create mode 100644 src/modules/interfaceUtilisateur/police/8x15/s.png create mode 100644 src/modules/interfaceUtilisateur/police/8x15/t.png create mode 100644 src/modules/interfaceUtilisateur/police/8x15/u.png create mode 100644 src/modules/interfaceUtilisateur/police/8x15/v.png create mode 100644 src/modules/interfaceUtilisateur/police/8x15/w.png create mode 100644 src/modules/interfaceUtilisateur/police/8x15/x.png create mode 100644 src/modules/interfaceUtilisateur/police/8x15/y.png create mode 100644 src/modules/interfaceUtilisateur/police/8x15/z.png create mode 100644 src/modules/interfaceUtilisateur/police/police.c create mode 100644 src/modules/modeleModule.c create mode 100644 src/modules/pc/gdt/gdt.c create mode 100644 src/modules/pc/idt/idt.S create mode 100644 src/modules/pc/idt/idt.c create mode 100644 src/modules/pc/io/io.c create mode 100644 src/modules/pc/irq/irq.S create mode 100644 src/modules/pc/irq/irq.c create mode 100644 src/modules/pc/kbc/kbc.c create mode 100644 src/modules/pc/pit/pit.c create mode 100644 src/modules/pc/sourisPS2/sourisPS2.c create mode 100644 src/modules/pc/vesaGraphique/vesaGraphique.c create mode 100644 src/modules/pc/vgaTexte/vgaTexte.c create mode 100644 src/modules/recherche/dichotomique.c create mode 100644 src/modules/stockage/ata/ata.c create mode 100644 src/modules/temps/temps/temps.c create mode 100644 src/modules/tri/tas/tas.c create mode 100644 src/scripts/creerImage.lds create mode 100644 src/scripts/creerModule.sh create mode 100755 src/scripts/creerPolice.sh create mode 100644 src/scripts/liste-chemins.lst diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1df2044 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +dist +travail diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..3832600 --- /dev/null +++ b/Makefile @@ -0,0 +1,12 @@ +SHELL = /bin/sh + +REP_MAKEFILES := src/makefiles/ + +MAKEFILES := affichage.makefile \ + fichiersDossiers.makefile \ + commandes.makefile \ + regles.makefile + +MAKEFILES := $(patsubst %,$(REP_MAKEFILES)/%,$(MAKEFILES)) + +include $(MAKEFILES) diff --git a/src/demarrage/grub/menu.lst b/src/demarrage/grub/menu.lst new file mode 100644 index 0000000..d8fcdf5 --- /dev/null +++ b/src/demarrage/grub/menu.lst @@ -0,0 +1,5 @@ +default 0 +timeout 0 +title gruntnetwork +kernel /boot/gruntnetwork.elf +module /donnees/police.fnt diff --git a/src/demarrage/grub/stage1 b/src/demarrage/grub/stage1 new file mode 100644 index 0000000000000000000000000000000000000000..c10df8082c735d1d23219b453b6058ff536c9a2b GIT binary patch literal 512 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 rZSu0(d~d*qKQMg#u?`DYF> literal 0 HcmV?d00001 diff --git a/src/demarrage/grub/stage2_eltorito b/src/demarrage/grub/stage2_eltorito new file mode 100644 index 0000000000000000000000000000000000000000..1faa58b51a76b79e71d08c7f74808945f1b89ab6 GIT binary patch literal 99942 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 Z)$SJa&m6dTy!h?aQ)dqRRmEuF{{Rhpe>(sG literal 0 HcmV?d00001 diff --git a/src/demarrage/grub/stage2_eltorito_vbe b/src/demarrage/grub/stage2_eltorito_vbe new file mode 100644 index 0000000000000000000000000000000000000000..6f8d29e48ae9234742b1b42460504e9bfbb35a01 GIT binary patch literal 106940 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%0D=`*KqqLS8p0^d5`I?rYaQ>w~~Er?J-Yu?g% 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%0AT?izE_)qb`w0IKDlB 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 literal 0 HcmV?d00001 diff --git a/src/inclusions/algo/math/math.h b/src/inclusions/algo/math/math.h new file mode 100644 index 0000000..a39da14 --- /dev/null +++ b/src/inclusions/algo/math/math.h @@ -0,0 +1,36 @@ +#ifndef ALGO_MATH_MATH_H +#define ALGO_MATH_MATH_H + +#include + +#define max(a, b) (((a) > (b)) ? (a) : (b)) + +#define min(a, b) (((a) < (b)) ? (a) : (b)) + +#define abs(x) (((x) >= 0) ? (x) : -(x)) + +#define sign(x) (((x) >= 0) \ + ? (((x) == 0) ? 0 : 1) \ + : -1) + +#define sinRapide_(a, sgn) ((((a) * 4) \ + - ((a)*(a) >> 13)) \ + * sgn) + +#define sinRapide(a) sinRapide_(abs((int32)(a)) % 32768, (((a) & 32768) ? 1 : -1)) + +#define cosRapide(a) sinRapide((a)+16384) + +#define clip(x, min_, max_) min(max_, max((x),min_)) + +typedef struct Div64 { + uint64 quotient; + uint64 reste; +} Div64; + +typedef struct EtatMath { +} EtatMath; + +Div64 div64 (uint64 numerateur, uint64 denominateur); + +#endif diff --git a/src/inclusions/demarrage/multiboot/multiboot.h b/src/inclusions/demarrage/multiboot/multiboot.h new file mode 100644 index 0000000..fb50408 --- /dev/null +++ b/src/inclusions/demarrage/multiboot/multiboot.h @@ -0,0 +1,244 @@ +#ifndef DEMARRAGE_MULTIBOOT_MULTIBOOT_H +#define DEMARRAGE_MULTIBOOT_MULTIBOOT_H + +#include + +/** + * @brief Informations récupérées par grub + * + * D'abord les sous-structures, puis la structure principale. + */ + +/* FIXME : De quoi s'agit-il réellement ? */ +typedef uint32 pointeurLointain; + +/** + * @brief Disponibilité des informations. + */ +typedef struct MultibootInfoFlags { + bool mem:1; + bool bootDevice:1; + bool cmdline:1; + bool mods:1; + bool aout:1; + bool elf:1; + bool mmap:1; + bool drives:1; + bool configTable:1; + bool bootLoaderName:1; + bool apmTable:1; + bool vbe:1; + uint32 PADDING:20; +} PACKED MultibootInfoFlags; + +/** + * @brief Média de stockage utilisé lors du démarrage. + */ +typedef struct MultibootInfoBootDevice { + uint8 part1; + uint8 part2; + uint8 part3; + uint8 drive; +} PACKED MultibootInfoBootDevice; + +/** + * @brief Modules chargés par le chargeur de démarrage. + */ +typedef struct MultibootInfoModule { + void* modStart; + void* modEnd; + + StringZ string; + + uint32 reserved; +} PACKED MultibootInfoModule; + +/** + * @brief Table des symboles a.out . + */ +typedef struct MultibootInfoAout { + uint32 aoutTabSize; + uint32 aoutStrSize; + + /* le type de aoutAddr devrait être nlist (cf. standard + * multiboot), mais de quoi s'agit-t-il ? */ + void* aoutAddr; + + uint32 reserved; +} PACKED MultibootInfoAout; + +/** + * @brief Table des en-têtes de section pour ELF. + */ +typedef struct MultibootInfoElf { + uint32 num; + uint32 size; + + void* addr; + + StringZ* shndx; /* Tableau de StringZ ou de String ? */ +} PACKED MultibootInfoElf; + +/** + * @brief Cartographie de la mémoire. + * + * Si type != MultibootInfoMmapRam alors cette mémoire est réservée + * (mémoire vidéo, etc.) + */ +#define MultibootInfoMmapRam = 1; +typedef struct MultibootInfoMmap { + /* Attention, mmapAddr tel que fourni par grub pointe sur le 2e + * champ (baseAddr), il faut donc enlever 4 octets à + * l'adresse. */ + uint32 size; + + /* Avec 32_low suivi de 32_high, je peux en faire 64. Ne me + * seais-je pas trompé dans l'endianisme ? */ + uint64 baseAddr; + uint64 length; + uint32 type; +} PACKED MultibootInfoMmap; + +/** + * @brief Média de stockage. + */ +typedef enum { CHS = 0, LBA = 1 } MultibootInfoDriveMode; +typedef struct MultibootInfoDrive { + uint32 size; + + uint8 driveNumber; + + /* Cela permet-il de contraindre la taille d'un enum ? */ + MultibootInfoDriveMode driveMode:8; + + + uint16 driveCylinders; + uint8 driveHeads; + uint8 driveSectors; + + /* Et comment je gère cette horreur moi ? */ + uint16 drivePorts; +} PACKED MultibootInfoDrive; + +/** + * @brief Fonction GET CONFIGURATION du BIOS. + */ +typedef struct MultibootInfoConfigTable { + /* Chercher le format de retour de l'appel au BIOS nommé + * GET CONFIGURATION */ +} PACKED MultibootInfoConfigTable; + +/** + * @brief Advanced Power Management. + */ +typedef struct MultibootInfoApmTable { + /* Voir le standard apm pour les types... + * http://www.micr.../hwdev/busbios/amp_12.htm + * Soit dit en passant, sympa la référence à micr... dans un + * standard libre (très mal écrit le standard au fait...) */ + uint16 version; + uint16 cseg; + uint32 offset; + uint16 cseg16; + uint16 dseg; + uint16 flags; + uint16 csegLen; + uint16 cseg16Len; + uint16 dsegLen; +} PACKED MultibootInfoApmTable; + +/** + * @brief Contrôleur VESA Bios Extension + */ +typedef struct MultibootInfoVbeControllerInfo{ + char signature[4]; /* == "VESA" */ + union { + uint16 version; + struct { + uint8 versionMajeure; /* 2 pour VBE 2.* */ + uint8 versionMineure; /* 0 pour VBE *.0 */ + }; + }; + /* pointeurLointain ??? */ + uint16 oemString[2]; /* Nom du périphérique, donné par le constructeur */ + uint32 capabilities; /* Fonctionnalités offertes */ + /* pointeurLointain ??? */ + uint16 videomodes[2]; /* Liste de modes vidéo */ + uint16 totalMemory; /* nombre de blocs de 64ko */ +} PACKED MultibootInfoVbeControllerInfo; + +/** + * @brief Mode vidéo VESA Bios Extension + */ +typedef struct MultibootInfoVbeModeInfo { + uint16 attributes; + uint8 winA,winB; + uint16 granularity; + uint16 winsize; + uint16 segmentA, segmentB; + pointeurLointain winFunc; + uint16 pitch; /* octets par scanline */ + + uint16 Xres, Yres; + uint8 Wchar, Ychar, planes, bpp, banks; + uint8 memory_model, bank_size, image_pages; + uint8 reserved; + + struct { + uint8 maskSize; + uint8 fieldPos; + } red, green, blue, reservedChannel; + uint8 directcolor_attributes; + + void* linearAddress; /* L'adresse du framebuffer linéaire :) */ + void* offscreenAddress; + uint16 offscreenSizeKB; +} PACKED MultibootInfoVbeModeInfo; + +/** + * @brief Informations récupérées par grub + */ +typedef struct MultibootInfo { + MultibootInfoFlags flags; + + uint32 memLower; + uint32 memUpper; + + MultibootInfoBootDevice bootDevice; + + StringZ cmdline; + + uint32 modsCount; + MultibootInfoModule* modsAddr; + + union { + MultibootInfoAout aout; + MultibootInfoElf elf; + } PACKED syms; + + uint32 mmapLength; + MultibootInfoMmap* mmapAddr; + + uint32 drivesLength; + MultibootInfoDrive* drivesAddr; + + MultibootInfoConfigTable* configTable; + + StringZ bootLoaderName; + + MultibootInfoApmTable* apmTable; + + MultibootInfoVbeControllerInfo* vbeControlInfo; + MultibootInfoVbeModeInfo* vbeModeInfo; + uint16 vbeMode; + uint16 vbeInterfaceSeg; + uint16 vbeInterfaceOff; + uint16 vbeInterfaceLen; +} PACKED MultibootInfo; + +typedef struct EtatMultiboot { + MultibootInfo* InfoMultiboot; + uint32 magicMultiboot; +} EtatMultiboot; + +#endif diff --git a/src/inclusions/interfaceUtilisateur/clavier/clavier.h b/src/inclusions/interfaceUtilisateur/clavier/clavier.h new file mode 100644 index 0000000..88995d6 --- /dev/null +++ b/src/inclusions/interfaceUtilisateur/clavier/clavier.h @@ -0,0 +1,7 @@ +#ifndef INTERFACE_UTILISATEUR_CLAVIER_CLAVIER_H +#define INTERFACE_UTILISATEUR_CLAVIER_CLAVIER_H + +typedef char EtatClavier; + +#endif + diff --git a/src/inclusions/interfaceUtilisateur/console/console.h b/src/inclusions/interfaceUtilisateur/console/console.h new file mode 100644 index 0000000..7cb858a --- /dev/null +++ b/src/inclusions/interfaceUtilisateur/console/console.h @@ -0,0 +1,116 @@ +#ifndef INTERFACE_UTILISATEUR_CONSOLE_CONSOLE_H +#define INTERFACE_UTILISATEUR_CONSOLE_CONSOLE_H + +#include + +typedef struct CouleurComposantes { + uint8 bleu; + uint8 vert; + uint8 rouge; + uint8 alpha; +} CouleurComposantes; + +typedef uint32 Couleur; + +typedef struct CouleurAvAr { + Couleur av; + Couleur ar; +} CouleurAvAr; + +typedef struct Position { + uint32 x; + uint32 y; +} Position; + +typedef void (*FonctionAffichage) (char caractere, uint32 couleurAv, uint32 couleurAr, uint32 x, uint32 y); + +typedef struct Console { + uint32 x; + uint32 y; + uint32 largeur; + uint32 hauteur; + FonctionAffichage fonctionAffichage; +} Console; + +typedef struct EtatConsole { + Console* consoleActive; + uint32 x; + uint32 y; + uint32 couleurAv; + uint32 couleurAr; + bool consolePrete; +} EtatConsole; + + +Console* definirConsoleActive(Console* console); + +CouleurAvAr getConsoleCouleur(); +CouleurAvAr consoleCouleur(Couleur couleurAv, Couleur couleurAr); + +Position getConsolePosition(); +Position consolePosition(uint32 x, uint32 y); +void consolePositionAvancerX(); +void consolePositionAvancerY(); + +void afficherCaractereCouleurPositionBrut(char caractere, uint32 couleurAv, uint32 couleurAr, uint32 x, uint32 y); +void afficherCaractereCouleurPosition(char caractere, uint32 couleurAv, uint32 couleurAr, uint32 x, uint32 y); +void afficherCaractere(char caractere); +void afficherCaractereBrut(char caractere); +void afficherCaractereCouleur(char caractere, uint32 couleurAv, uint32 couleurAr); +void afficherCaractereCouleurBrut(char caractere, uint32 couleurAv, uint32 couleurAr); +void afficherCaracterePosition(char caractere, uint32 x, uint32 y); +void afficherCaracterePositionBrut(char caractere, uint32 x, uint32 y); + +void effacerConsole(); +void afficherChaineZ(char* chaine); +void afficherChaine(char* chaine, int longueur); +void afficherEntierVirguleEnDecimal(uint32 entier, int32 nbDecimales); +void afficherEntierEnDecimal(uint32 entier); +void afficherEntierEnHexa(uint32 entier); +void afficherEntierEnBinaire(uint32 entier); +void afficherTableCaracteres(); + +bool consolePrete(); + +#define STR_Ccedil "\200" +#define STR_uuml "\201" +#define STR_eacute "\202" +#define STR_acirc "\203" +#define STR_auml "\204" +#define STR_agrave "\205" +#define STR_aring "\206" +#define STR_ccedil "\207" +#define STR_ecirc "\210" +#define STR_euml "\211" +#define STR_egrave "\212" +#define STR_iuml "\213" +#define STR_icirc "\214" +#define STR_igrave "\215" +#define STR_Auml "\216" +#define STR_Aring "\217" +#define STR_Eacute "\220" +#define STR_aelig "\221" +#define STR_AElig "\222" +#define STR_ocirc "\223" +#define STR_ouml "\224" +#define STR_ograve "\225" +#define STR_ucirc "\226" +#define STR_ugrave "\227" +#define STR_yuml "\230" +#define STR_Ouml "\231" +#define STR_Uuml "\232" +#define STR_cent "\233" +#define STR_pound "\234" +#define STR_yen "\235" +#define STR_xxxxxxxx "\236" +#define STR_fonction "\237" +#define STR_aacute "\240" +#define STR_iacute "\241" +#define STR_oacute "\242" +#define STR_uacute "\243" +#define STR_ntilde "\244" +#define STR_Ntilde "\245" +#define STR_ordm "\246" +#define STR_degr "\247" + +#endif diff --git a/src/inclusions/interfaceUtilisateur/demo/demo.h b/src/inclusions/interfaceUtilisateur/demo/demo.h new file mode 100644 index 0000000..2ce9ac3 --- /dev/null +++ b/src/inclusions/interfaceUtilisateur/demo/demo.h @@ -0,0 +1,6 @@ +#ifndef INTERFACE_UTILISATEUR_DEMO_DEMO_H +#define INTERFACE_UTILISATEUR_DEMO_DEMO_H + +typedef char EtatDemo; + +#endif diff --git a/src/inclusions/interfaceUtilisateur/police/police.h b/src/inclusions/interfaceUtilisateur/police/police.h new file mode 100644 index 0000000..9a2e9a3 --- /dev/null +++ b/src/inclusions/interfaceUtilisateur/police/police.h @@ -0,0 +1,10 @@ +#ifndef INTERFACE_UTILISATEUR_POLICE_POLICE_H +#define INTERFACE_UTILISATEUR_POLICE_POLICE_H + +typedef struct EtatPolice { + uint8* tableCaracteres; +} EtatPolice; + +void policeAfficherCaractereCouleurPosition(char caractere, uint32 couleurAv, uint32 couleurAr, uint32 x, uint32 y); + +#endif diff --git a/src/inclusions/math.h b/src/inclusions/math.h new file mode 100644 index 0000000..d2362cb --- /dev/null +++ b/src/inclusions/math.h @@ -0,0 +1,6 @@ +#ifndef MATH_H +#define MATH_H + +#include + +#endif diff --git a/src/inclusions/modeleModule.h b/src/inclusions/modeleModule.h new file mode 100644 index 0000000..ecfe0a9 --- /dev/null +++ b/src/inclusions/modeleModule.h @@ -0,0 +1,7 @@ +#ifndef MODELE_MODULE_H +#define MODELE_MODULE_H + +typedef struct EtatModeleModule { +} EtatModeleModule; + +#endif diff --git a/src/inclusions/module.h b/src/inclusions/module.h new file mode 100644 index 0000000..076ba7f --- /dev/null +++ b/src/inclusions/module.h @@ -0,0 +1,62 @@ +#ifndef MODULE_H +#define MODULE_H + +#include + +typedef enum { + ETAPE_MODULE_CHARGE = 0, + ETAPE_MODULE_INITIALISE = 1, +} EtapeChargementModule; + + +typedef struct InfoModule { + char* nom; + void (*init) (void** etat); + void (*deinit) (void** etat); + EtapeChargementModule etapeChargementModule; + void* etat; + struct DependanceModule* dependances; + struct InfoModule* suivant; + struct InfoModule* suivantRecursionDependances; + int nbDependances; +} PACKED ALIGNED(32) InfoModule; + +typedef struct DependanceModule { + InfoModule* module; + InfoModule* dependance; +} PACKED DependanceModule; + + +#define MODULE(nom) \ + Etat ## nom _etat ## nom USED; \ + Etat ## nom* etat ## nom USED = &_etat ## nom; \ + \ + void (init ## nom) (void** etat); \ + void (deinit ## nom) (void** etat); \ + InfoModule __infoModule_ ## nom \ + SECTION(.modules) \ + USED \ + = { \ + (#nom), \ + (init ## nom), \ + (deinit ## nom), \ + ETAPE_MODULE_CHARGE, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + 0 \ + } + +#define DEPENDANCE_MODULE(module, dependance) \ + extern InfoModule __infoModule_ ## module; \ + extern InfoModule __infoModule_ ## dependance; \ + DependanceModule __dependanceModule ## module ## _ ## dependance \ + __attribute__ ((section(".dependancesModules"))) \ + USED \ + = { \ + & __infoModule_ ## module, \ + & __infoModule_ ## dependance \ + } + +#endif diff --git a/src/inclusions/pc/gdt/gdt.h b/src/inclusions/pc/gdt/gdt.h new file mode 100644 index 0000000..7b3a8ad --- /dev/null +++ b/src/inclusions/pc/gdt/gdt.h @@ -0,0 +1,96 @@ +#ifndef PC_GDT_GDT_H +#define PC_GDT_GDT_H + +#include + +typedef enum { + SEGMENT_DONNEES = 0, + SEGMENT_CODE = 1 +} TypeSegmentCodeDonnees; + +typedef enum { + DESCRIPTEUR_SEGMENT_SYSTEME = 0, + DESCRIPTEUR_SEGMENT_CODE_DONNEES = 1 +} TypeDescripteurSegment; + +typedef enum { + TAILLE_OPERATION_16 = 0, + TAILLE_OPERATION_32 = 1 +} TailleOperationSegment; + +/* Union avec TailleOperationSegment */ +typedef enum { + LIMITE_HAUTE_64Ko = 0, + LIMITE_HAUTE_4Go = 1 +} LimiteHauteSegment; + +typedef enum { + GRANULARITE_1octet = 0, + GRANULARITE_4Ko = 1 +} GranulariteSegment; + +/* x86-doc-vol3.pdf section 3.4.5, fig 3-8 */ +typedef struct DescripteurSegment { + uint16 limite_15_0; + + uint16 base_15_0; + + uint8 base_23_16; + bool accede:1; + bool lecture_ecriture:1; + bool expansionBas_conforme:1; + TypeSegmentCodeDonnees codeDonnees:1; + + TypeDescripteurSegment typeDescripteur:1; + uint8 niveauPrivilegeDescripteur:2; + bool present:1; + + uint8 limite_19_16:4; + uint8 _disponible:1; + uint8 _reserve:1; /* Segment de code 64 bits (IA32 seulement) */ + TailleOperationSegment tailleOperation:1; + /* union avec ci-dessus : LimiteHauteSegment limiteHaute:1; */ + GranulariteSegment granularite:1; + uint8 base_31_24; +} PACKED ALIGNED(8) DescripteurSegment; + +#define descripteurSegmentNULL { \ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 \ +} + +#define descripteurSegmentBasicFlatModel(_codeDonnees) \ + { \ + .limite_15_0 = 0xFFFF, \ + .base_15_0 = 0x0000, \ + .base_23_16 = 0x00, \ + .accede = FALSE, \ + .lecture_ecriture = TRUE, \ + .expansionBas_conforme = FALSE, \ + .codeDonnees = _codeDonnees, \ + .typeDescripteur = DESCRIPTEUR_SEGMENT_CODE_DONNEES, \ + .niveauPrivilegeDescripteur = 0, \ + .present = 1, \ + .limite_19_16 = 0xF, \ + ._disponible = 0, \ + ._reserve = 0, \ + .tailleOperation = TAILLE_OPERATION_32, \ + .granularite = GRANULARITE_4Ko, \ + .base_31_24 = 0 \ + } + + +/* x86-doc-vol3.pdf section 2.4.1, fig 2.5 */ +typedef struct RegistreGDTR { + uint16 limite; + DescripteurSegment* base; +} PACKED ALIGNED (4) RegistreGDTR; +/* TODO : Vérifier le ALIGNED 4 : + * x86-doc-vol3.pdf section 3.5.1, 2e page */ + + +typedef struct EtatGdt { + DescripteurSegment* tableDescripteursSegment; + RegistreGDTR registreGDTR; +} EtatGdt; + +#endif diff --git a/src/inclusions/pc/idt/idt.h b/src/inclusions/pc/idt/idt.h new file mode 100644 index 0000000..24263d4 --- /dev/null +++ b/src/inclusions/pc/idt/idt.h @@ -0,0 +1,64 @@ +#ifndef PC_IDT_IDT_H +#define PC_IDT_IDT_H + +#include + +typedef enum { + DESCRIPTEUR_PORTE_TACHE = 1, + DESCRIPTEUR_PORTE_INTERRUPTION = 2, + DESCRIPTEUR_PORTE_TRAPPE = 3 +} TypeDescripteurInterruption; + +typedef enum { + TAILLE_PORTE_16 = 0, + TAILLE_PORTE_32 = 1 +} TaillePorte; + +/* x86-doc-vol3.pdf section 5.11, fig 5-2 */ +typedef struct DescripteurInterruption { + uint16 offset_15_0; + + uint16 selecteurSegment; + + uint8 _zero_a; + /* TypeDescripteurInterruption type:2; + uint8 _un:1; + TaillePorte taillePorte:1; + uint8 _zero_b:1; */ + uint8 type:5; + + uint8 niveauPrivilegeDescripteur:2; + bool present:1; + + uint16 offset_31_16; +} PACKED ALIGNED(8) DescripteurInterruption; + + +/* x86-doc-vol3.pdf section 2.4.1, fig 2.5 */ +typedef struct RegistreIDTR { + uint16 limite; + DescripteurInterruption* base; +} PACKED ALIGNED (8) RegistreIDTR; +/* TODO : Vérifier le ALIGNED 4 : + * x86-doc-vol3.pdf section 3.5.1, 2e page */ + + +typedef void (*EnregistreurContexteInterruption) (); +typedef void (*GestionnaireInterruption) (); + + +typedef struct EtatIdt { + DescripteurInterruption tableDescripteursInterruption[256]; + int interruptionsDesactivees; + int nombreDescripteursInterruption; + RegistreIDTR registreIDTR; +} EtatIdt; + + +int desactiverInterruptions(); +int activerInterruptions(); +void definirGestionnaireInterruption(int numeroInterruption, GestionnaireInterruption gestionnaire); +void activerInterruption(int numeroInterruption); +void desactiverInterruption(int numeroInterruption); + +#endif diff --git a/src/inclusions/pc/io/io.h b/src/inclusions/pc/io/io.h new file mode 100644 index 0000000..3d7b1ef --- /dev/null +++ b/src/inclusions/pc/io/io.h @@ -0,0 +1,20 @@ +#ifndef PC_IO_IO_H +#define PC_IO_IO_H + +#define inb(port) \ + ({ \ + uint8 ret; \ + asm volatile ("inb %w1,%0" \ + : "=a" (ret) \ + : "i" (port) ); \ + ret; \ + }) + +#define outb(port, val) \ + asm volatile ("outb %b0,%w1" \ + : \ + : "a" (val), "i" (port) ) + +typedef char EtatIo; + +#endif diff --git a/src/inclusions/pc/irq/irq.h b/src/inclusions/pc/irq/irq.h new file mode 100644 index 0000000..3a41058 --- /dev/null +++ b/src/inclusions/pc/irq/irq.h @@ -0,0 +1,107 @@ +#ifndef PC_IRQ_IRQ_H +#define PC_IRQ_IRQ_H + +#define PORT_PIC_MAITRE_COMMANDE 0x0020 +#define PORT_PIC_MAITRE_DONNEES 0x0021 +#define PORT_PIC_ESCLAVE_COMMANDE 0x00A0 +#define PORT_PIC_ESCLAVE_DONNEES 0x00A1 + +/* 8259A page 10-12 (fig 7) */ +typedef enum { + PIC_ICW1_SEUL = 1, + PIC_ICW1_CASCADE = 0 +} PIC_ICW1_SNGL; + +typedef enum { + PIC_ICW1_INTERVALLE_4 = 1, + PIC_ICW1_INTERVALLE_8 = 0 +} PIC_ICW1_ADI; + +typedef enum { + PIC_ICW1_LEVEL_TRIGGERED_MODE = 1, + PIC_ICW1_EDGE_TRIGGERED_MODE = 0 +} PIC_ICW1_LTIM; + +typedef struct PicICW1 { + bool ICW4_present:1; + PIC_ICW1_SNGL single:1; + PIC_ICW1_ADI adi:1; + PIC_ICW1_LTIM ltim:1; + uint8 init:1; + /* MCS-80/85 seulement : + * uint8 adresseVecteurInterruption_7_5:3; */ + uint8 _zero:4; +} PicICW1; + + +typedef struct PicICW2 { + /* MCS-80/85 seulement : + * uint8 adresseVecteurInterruption_15_8; */ + uint8 _zero:3; + uint8 adresseVecteurInterruption_7_3:5; +} PicICW2; +/* typedef uint8 PicICW2; */ + + +#define ESCLAVE_CONNECTE_SUR_MAITRE_PATTE(patteConnexionMaitre) (1<<(patteConnexionMaitre)) +typedef uint8 PicICW3_Maitre; + +typedef struct PicICW3_Esclave { + uint8 patteConnexionMaitre:3; + uint8 _zero:5; +} PicICW3_Esclave; + + +typedef enum { + PIC_ICW4_MODE_8086_8088 = 1, + PIC_ICW4_MODE_MCS_80_85 = 0 +} PIC_ICW4_MICRO_PM; + +typedef enum { + PIC_ICW4_MODE_SANS_TAMPON = (0 | 0), + PIC_ICW4_TAMPON_ESCLAVE = (2 | 0), + PIC_ICW4_TAMPON_MAITRE = (2 | 1) +} PIC_ICW4_BUF_MS; + +typedef struct PicICW4 { + PIC_ICW4_MICRO_PM microPM:1; + bool autoEOI:1; + PIC_ICW4_BUF_MS tampon:2; + bool specialFullyNestedMode:1; + uint8 _zero:3; +} PicICW4; + + +typedef void (*FonctionEnvoiFinInterruption) (); +typedef void (*GestionnaireRequeteInterruption) (); + +typedef struct EtatIrq { + FonctionEnvoiFinInterruption* tableFonctionsEnvoiFinInterruption; + GestionnaireRequeteInterruption* tableGestionnairesRequeteInterruption; + + uint8 adresseVecteurInterruptionMaitre; + uint8 adresseVecteurInterruptionEsclave; + + PicICW1 ICW1_Maitre; + PicICW2 ICW2_Maitre; + PicICW3_Maitre ICW3_Maitre; + PicICW4 ICW4_Maitre; + + PicICW1 ICW1_Esclave; + PicICW2 ICW2_Esclave; + PicICW3_Esclave ICW3_Esclave; + PicICW4 ICW4_Esclave; + + uint8 masqueMaitre; + uint8 masqueEsclave; + + uint8 ancienMasqueMaitre; + uint8 ancienMasqueEsclave; +} EtatIrq; + + +void definirGestionnaireRequeteInterruption(int ligne, GestionnaireRequeteInterruption gestionnaire); +void activerLigneRequeteInterruption(int ligne); +void desactiverLigneRequeteInterruption(int ligne); + +#endif diff --git a/src/inclusions/pc/kbc/kbc.h b/src/inclusions/pc/kbc/kbc.h new file mode 100644 index 0000000..39c1c99 --- /dev/null +++ b/src/inclusions/pc/kbc/kbc.h @@ -0,0 +1,35 @@ +#ifndef PC_KBC_KBC_H +#define PC_KBC_KBC_H + +/* TODO : Vérifier ces informations dans la doc Intel. */ + +#define LIGNE_IRQ_CLAVIER 1 +#define LIGNE_IRQ_SOURIS 12 + +#define PORT_KBC_DONNEES 0x60 +#define PORT_KBC_SCANCODE PORT_KBC_DONNEES +#define PORT_KBC_SOURIS PORT_KBC_DONNEES +#define PORT_KBC_COMMANDE_SOURIS PORT_KBC_DONNEES +#define PORT_KBC_PPI 0x61 +#define PORT_KBC_COMMANDE 0x64 + +#define KBC_DEMMANDE_ECRITURE_CLAVIER 0xd1 +#define KBC_DEMMANDE_ECRITURE_SOURIS 0xd4 +#define KBC_DEMMANDE_LECTURE_COMPAQ_STATUS_BYTE 0x20 +#define KBC_DEMMANDE_ECRITURE_COMPAQ_STATUS_BYTE 0x60 +#define KBC_RESET_CPU 0xfe + +typedef void (*GestionnaireClavier) (uint8 scancode); + +typedef struct EtatKbc { + GestionnaireClavier gestionnaireClavier; +} EtatKbc; + +void attenteKbc(); +void attenteLectureKbc(); +void activerClavier(); +void desactiverClavier(); +void resetCpu(); +void definirGestionnaireClavier(GestionnaireClavier gestionnaireClavier); + +#endif diff --git a/src/inclusions/pc/pit/pit.h b/src/inclusions/pc/pit/pit.h new file mode 100644 index 0000000..0b3cac2 --- /dev/null +++ b/src/inclusions/pc/pit/pit.h @@ -0,0 +1,84 @@ +#ifndef PC_PIT_PIT_H +#define PC_PIT_PIT_H + +#define LIGNE_IRQ_PIT 0 +#define PORT_PIT_CANAUX 0x40 +#define PORT_PIT_CANAL_0 PORT_PIT_CANAUX + 0 +#define PORT_PIT_CANAL_1 PORT_PIT_CANAUX + 1 +#define PORT_PIT_CANAL_2 PORT_PIT_CANAUX + 2 +#define PORT_PIT_COMMANDE 0x43 + +#define FREQUENCE_PIT_MILI_HZ 1193181667 + +typedef enum { + PIT_CANAL_0 = 0, + PIT_CANAL_1 = 1, + PIT_CANAL_2 = 2, + PIT_COMMANDE_LECTURE = 3, +} PitCanal; + +typedef enum { + PIT_COMMANDE_VERROU = 0, + PIT_OCTET_BAS = 1, + PIT_OCTET_HAUT = 2, + PIT_OCTETS_HAUT_BAS = 3, +} PitModeAcces; + +typedef enum { + /* Mauvaises traductions... */ + PIT_MODE_INTERRUPTION_FIN_COMPTEUR = 0, + PIT_MODE_UN_COUP_RE_ACTIVABLE = 1, + PIT_MODE_GENERATEUR_FREQUENCE = 2, + PIT_MODE_GENERATEUR_ONDE_CARREE = 3, + PIT_MODE_SIGNAL_A_DECLENCHEMENT_LOGICIEL = 4, + PIT_MODE_SIGNAL_A_DECLENCHEMENT_MATERIEL = 5, +} PitModeCanal; + +typedef struct PitCommandeMode { + bool bcd:1; + PitModeCanal mode:3; + PitModeAcces acces:2; + PitCanal canal:2; +} PACKED PitCommandeMode; + +typedef struct PitCommandeVerrou { + PitCanal canal:2; + uint8 zero:6; +} PitCommandeVerrou; + +typedef struct PitCommandeLecture { + uint8 un:2; + bool nePasVerouillerCompteur:1; + bool nePasVerouillerEtat:1; + bool lectureCanal0:1; + bool lectureCanal1:1; + bool lectureCanal2:1; + uint8 zero:1; +} PitCommandeLecture; + +typedef struct PitEtatCanal { + bool bcd:1; + PitModeCanal mode:3; + PitModeAcces acces:2; + bool attenteCopieRechargeCompteur:1; + bool etatSortie:1; +} PitEtatCanal; + +typedef void (*GestionnairePit) (); + +typedef struct EtatPit { + PitModeCanal modeCanal0; + PitModeCanal modeCanal1; + PitModeCanal modeCanal2; + PitModeAcces modeAcces; + + GestionnairePit gestionnairePit; +} EtatPit; + +uint32 definirFrequenceCanal(uint32 freq, PitCanal canal); +uint32 definirDelaiCanal(uint32 delai, PitCanal canal); +void definirCompteurCanal(uint16 compteur, PitCanal canal); +void definirModeCanal(PitModeCanal mode, PitCanal canal); +void definirGestionnairePit(GestionnairePit gestionnairePit); + +#endif diff --git a/src/inclusions/pc/sourisPS2/sourisPS2.h b/src/inclusions/pc/sourisPS2/sourisPS2.h new file mode 100644 index 0000000..5b89352 --- /dev/null +++ b/src/inclusions/pc/sourisPS2/sourisPS2.h @@ -0,0 +1,146 @@ +#ifndef PC_SOURIS_PS2_SOURIS_PS2_H +#define PC_SOURIS_PS2_SOURIS_PS2_H + +#include + +#define SOURIS_PS2_DEFINIR_RESOLUTION 0xe8 +#define SOURIS_PS2_DEMANDER_PAQUET 0xeb +#define SOURIS_PS2_OBTENIR_MOUSE_ID 0xf2 +#define SOURIS_PS2_DEFINIR_FREQUENCE 0xf3 +#define SOURIS_PS2_AUTO_PAQUETS 0xf4 +#define SOURIS_PS2_DESACTIVER_PAQUETS 0xf5 +#define SOURIS_PS2_RESET 0xff + +#define SOURIS_PS2_ACK 0xfa +#define SOURIS_PS2_RESET_1 0xaa +#define SOURIS_PS2_RESET_2 0x00 + +#define ENVOYER 1 +#define RECEVOIR 2 +#define ENVOYER_V 3 +#define RECEVOIR_V 4 +#define RECEVOIR_OU_PAS 42 /* Que la force soit avec la souris */ +#define COMMANDE 5 + + + +static const uint8 DialogueDefinirResolution[] = { + ENVOYER, SOURIS_PS2_DEFINIR_RESOLUTION, + RECEVOIR, SOURIS_PS2_ACK, + ENVOYER_V, 0, + RECEVOIR, SOURIS_PS2_ACK +}; + +static const uint8 DialogueDemanderPaquet[] = { + ENVOYER, SOURIS_PS2_DEMANDER_PAQUET, + RECEVOIR, SOURIS_PS2_ACK +}; + +static const uint8 DialogueObtenirMouseID[] = { + ENVOYER, SOURIS_PS2_OBTENIR_MOUSE_ID, + RECEVOIR, SOURIS_PS2_ACK, + RECEVOIR_V, 0 +}; + +static const uint8 DialogueDefinirFrequence[] = { + ENVOYER, SOURIS_PS2_DEFINIR_FREQUENCE, + RECEVOIR, SOURIS_PS2_ACK, + ENVOYER_V, 0, + RECEVOIR, SOURIS_PS2_ACK +}; + +static const uint8 DialogueAutoPaquets[] = { + ENVOYER, SOURIS_PS2_AUTO_PAQUETS, + RECEVOIR, SOURIS_PS2_ACK +}; + +static const uint8 DialogueDesactiverPaquets[] = { + ENVOYER, SOURIS_PS2_DESACTIVER_PAQUETS, + RECEVOIR, SOURIS_PS2_ACK +}; + +static const uint8 DialogueReset[] = { + ENVOYER, SOURIS_PS2_RESET, + RECEVOIR_OU_PAS, SOURIS_PS2_ACK, + RECEVOIR, SOURIS_PS2_RESET_1, + RECEVOIR, SOURIS_PS2_RESET_2 +}; + +static const uint8 DialogueObtenirCompaqStatusByte[] = { + COMMANDE, KBC_DEMMANDE_LECTURE_COMPAQ_STATUS_BYTE, + RECEVOIR_V, 0 + /* RECEVOIR_OU_PAS, 0xd8 Certaines versions de Bochs envoient mystérieusement cet octet. */ +}; + +static const uint8 DialogueDefinirCompaqStatusByte[] = { + COMMANDE, KBC_DEMMANDE_ECRITURE_COMPAQ_STATUS_BYTE, + ENVOYER_V, 0 + /* RECEVOIR_OU_PAS, SOURIS_PS2_ACK */ +}; + + + +typedef struct PaquetSourisPS2_1 { + uint8 boutonGauche:1; + uint8 boutonDroite:1; + uint8 boutonMilieu:1; + uint8 un:1; + uint8 xNegatif:1; + uint8 yNegatif:1; + uint8 xOverflow:1; + uint8 yOverflow:1; +} PaquetSourisPS2_1; + +typedef enum { + MOLETTE_DEFILEMENT_AUCUN = 0, + MOLETTE_DEFILEMENT_HAUT = 1, + MOLETTE_DEFILEMENT_BAS = 0xf, + MOLETTE_DEFILEMENT_GAUCHE = 0xe, + MOLETTE_DEFILEMENT_DROITE = 2 +} ModeDefilementSourisPS2; + +typedef struct PaquetSourisPS2_4 { + uint8 ignorer:2; + uint8 bouton5:1; + uint8 bouton4:1; + ModeDefilementSourisPS2 modeDefilement:4; +} PaquetSourisPS2_4; + + +typedef enum { + ETAT_GESTIONNAIRE_SOURIS_PS2_ATTENTE, + ETAT_GESTIONNAIRE_SOURIS_PS2_PAQUET, + ETAT_GESTIONNAIRE_SOURIS_PS2_DIALOGUE +} EtatGestionnaireSourisPS2; + +typedef void (*FonctionRappelSourisPS2) (bool erreur); + +typedef struct DialogueSourisPS2 { + const uint8* sequence; + int longueur; + uint8* parametre; + FonctionRappelSourisPS2 rappel; +} DialogueSourisPS2; + + +typedef struct EtatSourisPS2 { + uint8 resolution; + uint8 frequence; + uint8 mouseID; + uint8 compaqStatusByte; + bool resetPotentiel; + uint8 paquets[4]; + int paquet; + bool paquetsDoiventEtreZero; + bool debordementXY; + DialogueSourisPS2 dialogue; + int etapeDialogue; + EtatGestionnaireSourisPS2 etatGestionnaireSourisPS2; + + /* DEBUG */ + int32 curseur_x; + int32 curseur_y; + uint32 couleur; +} EtatSourisPS2; + +#endif diff --git a/src/inclusions/pc/vesaGraphique/vesaGraphique.h b/src/inclusions/pc/vesaGraphique/vesaGraphique.h new file mode 100644 index 0000000..1b07cd6 --- /dev/null +++ b/src/inclusions/pc/vesaGraphique/vesaGraphique.h @@ -0,0 +1,22 @@ +#ifndef PC_VESA_GRAPHIQUE_VESA_GRAPHIQUE_H +#define PC_VESA_GRAPHIQUE_VESA_GRAPHIQUE_H + +#include + +typedef struct Pixel { + uint32 rvb:24; +} PACKED Pixel; + +typedef struct EtatVesaGraphique { + Pixel* memoireVideo; + Console console; +} EtatVesaGraphique; + + +void setPixel32 (uint32 x, uint32 y, uint32 couleur); +void ligne (uint32 x1, uint32 y1, uint32 x2, uint32 y2, uint32 couleur); +void rectanglePlein (uint32 x1, uint32 x2, uint32 y1, uint32 y2, uint32 couleur); +void rectangleContour (uint32 x1, uint32 x2, uint32 y1, uint32 y2, uint32 couleur); +void vesaGraphiqueAfficherCaractereCouleurPosition(char caractere, uint32 couleurAv, uint32 couleurAr, uint32 x, uint32 y); + +#endif diff --git a/src/inclusions/pc/vgaTexte/vgaTexte.h b/src/inclusions/pc/vgaTexte/vgaTexte.h new file mode 100644 index 0000000..31d63ef --- /dev/null +++ b/src/inclusions/pc/vgaTexte/vgaTexte.h @@ -0,0 +1,38 @@ +#ifndef PC_VGA_TEXTE_VGA_TEXTE_H +#define PC_VGA_TEXTE_VGA_TEXTE_H + +#include + +typedef struct CouleurVgaTexte { + uint8 avClair:1; + uint8 avRouge:1; + uint8 avVert:1; + uint8 avBleu:1; + uint8 _reserve:1; + uint8 arRouge:1; + uint8 arVert:1; + uint8 arBleu:1; +} CouleurVgaTexte; + +typedef struct CaractereVgaTexte { + char caractere; + CouleurVgaTexte couleur; +} PACKED CaractereVgaTexte; + + +typedef struct EtatVgaTexte { + CaractereVgaTexte* memoireVideo; + Console console; +} EtatVgaTexte; + + +void vgaTexteEffacerConsole(); +void vgaTexteAfficherCaractereCouleurPosition(char caractere, uint32 couleurAv, uint32 couleurAr, uint32 x, uint32 y); +uint32 vgaTexteConsoleCouleur(uint32 couleur); +void vgaTexteConsolePosition(int position); + +void consoleNL(); +void afficherCaractereBrut(char caractere); +void afficherCaractere(char caractere); + +#endif diff --git a/src/inclusions/recherche/dichotomique/dichotomique.h b/src/inclusions/recherche/dichotomique/dichotomique.h new file mode 100644 index 0000000..55b26e9 --- /dev/null +++ b/src/inclusions/recherche/dichotomique/dichotomique.h @@ -0,0 +1,9 @@ +#ifndef RECHERCHE_DICHOTOMIQUE_DICHOTOMIQUE_H +#define RECHERCHE_DICHOTOMIQUE_DICHOTOMIQUE_H + +typedef char EtatRechercheDichotomique; + +int rechercheDichotomiquePremier(void* e, void* t, int taille, AccesseurIndex get, ComparaisonStricte comparer); +int rechercheDichotomiqueDernier(void* e, void* t, int taille, AccesseurIndex get, ComparaisonStricte comparer); + +#endif diff --git a/src/inclusions/stockage/ata/ata.h b/src/inclusions/stockage/ata/ata.h new file mode 100644 index 0000000..a081683 --- /dev/null +++ b/src/inclusions/stockage/ata/ata.h @@ -0,0 +1,53 @@ +#ifndef STOCKAGE_ATA_ATA_H +#define STOCKAGE_ATA_ATA_H + +#define PORT_ATA 0x1f0 + +#define PORT_ATA_DONNEES PORT_ATA + 0 + +#define PORT_ATA_ERREUR PORT_ATA + 1 + +#define PORT_ATA_NOMBRE_SECTEURS PORT_ATA + 2 + +#define PORT_ATA_ADRESSE_PARTIELLE_SECTEUR PORT_ATA + 3 +#define PORT_ATA_ADRESSE_PARTIELLE_SECTEUR_1 PORT_ATA_ADRESSE_PARTIELLE_SECTEUR + 0 +#define PORT_ATA_ADRESSE_PARTIELLE_SECTEUR_2 PORT_ATA_ADRESSE_PARTIELLE_SECTEUR + 1 +#define PORT_ATA_ADRESSE_PARTIELLE_SECTEUR_3 PORT_ATA_ADRESSE_PARTIELLE_SECTEUR + 2 + + +#define PORT_ATA_DIVERS PORT_ATA + 6 +#define PORT_ATA_SELECTION_LECTEUR PORT_ATA_DIVERS +#define PORT_ATA_DRAPEAUX PORT_ATA_DIVERS +#define PORT_ATA_FIN_ADRESSE_SECTEUR PORT_ATA_DIVERS + +#define PORT_ATA_COMMANDE_ETAT PORT_ATA + 7 +#define PORT_ATA_COMMANDE PORT_ATA_COMMANDE_ETAT +#define PORT_ATA_ETAT PORT_ATA_COMMANDE_ETAT + +#define PORT_ATA_CONTROLE_ETAT_ALTERNATIF 0x3f6 +#define PORT_ATA_CONTROLE PORT_ATA_CONTROLE_ETAT_ALTERNATIF +#define PORT_ATA_ETAT_ALTERNATIF PORT_ATA_CONTROLE_ETAT_ALTERNATIF + +typedef struct AtaOctetEtat { + bool srv:1; /* TODO : traduire "Overlapped mode service request" */ + bool erreurDisque:1; + bool pret:1; + bool occupe:1; + bool transfertPret:1; + uint8 reserve:2; + bool erreur; +} AtaOctetEtat; + +typedef struct AtaControle { + uint8 reserve_b:1; + bool interruptions:1; + bool reInitialisation:1; + uint8 reserve_a:4; + bool octetHaut:1; +} AtaControle; + + +typedef struct EtatAta { +} EtatAta; + +#endif diff --git a/src/inclusions/string.h b/src/inclusions/string.h new file mode 100644 index 0000000..438d541 --- /dev/null +++ b/src/inclusions/string.h @@ -0,0 +1,23 @@ +#ifndef STRING_H +#define STRING_H + +#include + +int strcmp(StringZ s1, StringZ s2) { + while (*s1 == *s2 && *s1 != 0) { + s1++; + s2++; + } + if (*s1 == *s2) + return 0; + else if (*s1 < *s2) + return -1; + else + return 1; +} + +bool streq(StringZ s1, StringZ s2) { + return (strcmp(s1,s2) == 0); +} + +#endif diff --git a/src/inclusions/temps/temps/temps.h b/src/inclusions/temps/temps/temps.h new file mode 100644 index 0000000..e053f37 --- /dev/null +++ b/src/inclusions/temps/temps/temps.h @@ -0,0 +1,26 @@ +#ifndef TEMPS_TEMPS_TEMPS_H +#define TEMPS_TEMPS_TEMPS_H + +typedef void (*FonctionRappel) (); + +typedef struct Echeance { + uint64 dateEcheance; + FonctionRappel fonction; + struct Echeance* echeanceSuivante; +} Echeance; + +typedef struct EtatTemps { + uint32 increments; /* 1..10^9 Nombre de nanosecondes entre chaque 'tic' d'horloge. */ + + uint32 nanosec; /* nanosecondes depuis la dernière seconde entière. */ + uint64 sec; /* secondes depuis le 01/01/1970 à 00h00 . */ + uint64 delta; /* Décalage connu à rattrapper / ralentir progressivement . */ + uint64 etapesDelta; /* Rattrapper le décalage en combien de nanosecondes ? */ + + Echeance* listeEcheancesDate; /* Tiennent compte immédiatement (ou pas ?) de delta */ + Echeance* listeEcheancesDelai; /* Ne tiennent pas compte de delta */ + + uint64 debug; /* DEBUG */ +} EtatTemps; + +#endif diff --git a/src/inclusions/tri/tas/tas.h b/src/inclusions/tri/tas/tas.h new file mode 100644 index 0000000..7f251e2 --- /dev/null +++ b/src/inclusions/tri/tas/tas.h @@ -0,0 +1,8 @@ +#ifndef TRI_TAS_TAS_H +#define TRI_TAS_TAS_H + +typedef char EtatTriParTas; + +void triParTas(void* t, int taille, AccesseurIndex get, AccesseurEchanger echanger, Comparaison comparer); + +#endif diff --git a/src/inclusions/types.h b/src/inclusions/types.h new file mode 100644 index 0000000..e1cbeb2 --- /dev/null +++ b/src/inclusions/types.h @@ -0,0 +1,59 @@ +#ifndef TYPES_H +#define TYPES_H + +/* Types simples */ +typedef unsigned char uint8; +typedef unsigned short uint16; +typedef unsigned int uint32; +typedef unsigned long long uint64; + +typedef int int32; + +typedef enum { + TRUE = 1, + FALSE = 0 +} bool; + + +/* Types composés */ +#define CAST_STRUCT_TO_INT(_struct) (*((int*)((void*)(&_struct)))) +#define CAST_INT_TO_STRUCT(_int, _struct_t) (*((_struct_t*)((void*)(&_int)))) + +typedef struct Liste { + void* car; + struct Liste* cdr; +} Liste; + +typedef char* String; +typedef String StringZ; + +#define LONGUEUR(t) (sizeof (t) / sizeof (*(t))) + + +/* Attributs */ +#define ALIGNED(alignement) __attribute__ ((aligned(alignement))) +#define PACKED __attribute__ ((packed)) +#define USED __attribute__ ((used)) +#define SECTION(sec) __attribute__ ((section(#sec))) + + +/* Constantes */ +#define NULL (void*)0 + + +/* Prototypes de fonctions */ + +/* Comparaison ComparaisonStricte + * a < b : return <0 <0 + * a = b : return peu importe =0 + * a > b : return >=0 >0 */ +typedef int (Comparaison)(void* a, void* b); + +typedef Comparaison ComparaisonStricte; + +typedef void* (AccesseurIndex)(void* t, uint32 index); + +typedef void (AccesseurEchanger)(void* t, uint32 a, uint32 b); + + +#endif diff --git a/src/makefiles/affichage.makefile b/src/makefiles/affichage.makefile new file mode 100644 index 0000000..857c88a --- /dev/null +++ b/src/makefiles/affichage.makefile @@ -0,0 +1,42 @@ +VIDE = + +# Couleurs +COULEUR = [$(1)m +COULEUR_AUCUNE = $(call COULEUR,) +COULEUR_BLEU_CLAIR = $(call COULEUR,1;34) +COULEUR_VERT_CLAIR = $(call COULEUR,1;32) +COULEUR_GRIS = $(call COULEUR,1;30) +COULEUR_JAUNE_CLAIR = $(call COULEUR,1;33) +COULEUR_VERT_FONCE = $(call COULEUR,0;32) + +COULEUR_SOURCE = $(COULEUR_BLEU_CLAIR) +COULEUR_DEST = $(COULEUR_VERT_FONCE) +COULEUR_TAG = $(COULEUR_GRIS) +COULEUR_TAG_CC = $(COULEUR_VERT_FONCE) +COULEUR_TAG_AS = $(COULEUR_TAG_CC) +COULEUR_TAG_LD = $(COULEUR_BLEU_CLAIR) +COULEUR_TAG_CD = $(COULEUR_JAUNE_CLAIR) +COULEUR_TAG_TT = $(COULEUR_VERT_CLAIR) + +# Apparence +FORMAT_TAG = $(COULEUR_TAG)[$(call COULEUR_TAG_$(1))$(1)$(COULEUR_TAG)]$(COULEUR_AUCUNE) $(VIDE) +FORMAT_FLECHE = $(VIDE) <- $(VIDE) +FORMAT_SOURCE = $(COULEUR_SOURCE)$(call FORMAT_CHEMIN,$(1))$(COULEUR_AUCUNE) +FORMAT_DEST = $(COULEUR_DEST)$(call FORMAT_CHEMIN,$(1))$(COULEUR_AUCUNE) + +FORMAT_CHEMIN = $(subst //,/,$(1)) + +FORMAT_ACTION_1 = $(call FORMAT_TAG,$(1))$(call FORMAT_DEST,$(2)) +FORMAT_ACTION_2 = $(call FORMAT_ACTION_1,$(1),$(3))$(FORMAT_FLECHE)$(call FORMAT_SOURCE,$(2)) + +# Fonctions d'affichage +AFFICHE = echo "$(1)" + +AFFICHE_ACTION = $(call AFFICHE,$(call FORMAT_ACTION_$(1),$(2),$(3),$(4))) + +AFFICHE_CC = $(call AFFICHE_ACTION,2,CC,$(1),$(notdir $(2))) +AFFICHE_AS = $(call AFFICHE_ACTION,2,AS,$(1),$(notdir $(2))) +AFFICHE_FN = $(call AFFICHE_ACTION,2,FN,$(1),$(notdir $(2))) +AFFICHE_LD = $(call AFFICHE_ACTION,2,LD,$(notdir $(1)),$(notdir $(2))) +AFFICHE_CD = $(call AFFICHE_ACTION,1,CD,$(1)) +AFFICHE_TT = $(call AFFICHE_ACTION,1,TT,$(1)) diff --git a/src/makefiles/commandes.makefile b/src/makefiles/commandes.makefile new file mode 100644 index 0000000..200a810 --- /dev/null +++ b/src/makefiles/commandes.makefile @@ -0,0 +1,37 @@ +CC := gcc +CC_OPTS := -Werror -Wall -Wextra \ + -nostdlib -nostdinc -ffreestanding -undef \ + -O3 -fomit-frame-pointer \ + -fno-strict-aliasing \ + -std=gnu99 -fasm \ + -frandom-seed=1234 + # -fextended-identifiers ? + # -finput-charset=utf-8 ? +CC_INCLUSIONS = $(patsubst %,-I%,$(REP_INCLUSIONS)) + +LD := ld +LD_OPTS := --warn-common --fatal-warnings \ + -nostdlib + +FN := $(REP_SCRIPTS)/creerPolice.sh +FN_OPTS := + +EMU := qemu +EMU_OPTS := -m 4 --full-screen + +GEN_ISO := genisoimage + +GEN_ISO_OPTS := -R -boot-load-size 4 -no-emul-boot -b boot/grub/stage2_eltorito -boot-info-table -c boot/boot.cat \ + -input-charset utf-8 -quiet \ + +RM := rm +RM_OPTS := + +CAT := cat +CAT_OPTS := + +MKDIR := mkdir +MKDIR_OPTS := -p + +CREATE_FILE := touch +CREATE_FILE_OPTS := diff --git a/src/makefiles/fichiersDossiers.makefile b/src/makefiles/fichiersDossiers.makefile new file mode 100644 index 0000000..d531e58 --- /dev/null +++ b/src/makefiles/fichiersDossiers.makefile @@ -0,0 +1,37 @@ +REP_SOURCES := ./src + +REP_TRAVAIL := ./travail + +REP_DIST := ./dist + +REP_INCLUSIONS := $(REP_SOURCES)/inclusions + +REP_SCRIPTS := $(REP_SOURCES)/scripts + +REP_A_SUPPRIMER := $(REP_TRAVAIL) $(REP_DIST) + + + +IMAGE_CDROM := $(REP_DIST)/cdrom/gruntnetwork.iso + +NOYAU_ELF := $(REP_DIST)/noyau.elf + +POLICE_FNT := $(REP_DIST)/police.fnt + +SCRIPT_LD := $(REP_SCRIPTS)/creerImage.lds + +LISTE_FICHIERS_ISO := $(REP_SCRIPTS)/liste-chemins.lst + + + +FICHIERS_ISO := $(shell cut -d '=' -f 2- $(LISTE_FICHIERS_ISO)) + +SOURCES := $(shell find $(REP_SOURCES) -name '*.c' -or -name '*.S' -or -name '*.fnt') + +OBJETS := $(patsubst %,$(REP_TRAVAIL)/%.o,$(SOURCES)) + +OBJETS_LD := $(filter %.c.o %.S.o,$(OBJETS)) + +OBJETS_FNT := $(filter %.fnt.o,$(OBJETS)) + +DEPENDANCES := $(patsubst %.o,%.d,$(OBJETS)) diff --git a/src/makefiles/regles.makefile b/src/makefiles/regles.makefile new file mode 100644 index 0000000..294c1f8 --- /dev/null +++ b/src/makefiles/regles.makefile @@ -0,0 +1,53 @@ +.PHONY: all +all: $(IMAGE_CDROM) + +.PHONY: clean +clean: + @echo " Suppression..." + @$(RM) $(RM_OPTS) -rf $(REP_A_SUPPRIMER) + @$(MKDIR) $(MKDIR_OPTS) $(REP_A_SUPPRIMER) + rmdir ./travail ./dist + mkdir ./travail ./dist + +.PHONY: test +test: $(IMAGE_CDROM) + @$(call AFFICHE_TT,$<,$@) + @sync + @$(EMU) $(EMU_OPTS) -cdrom $< -boot d + + + +-include $(DEPENDANCES) + + + +$(IMAGE_CDROM): $(FICHIERS_ISO) + @$(call AFFICHE_CD,$^,$@) + @$(MKDIR) $(MKDIR_OPTS) $(dir $@) + @$(GEN_ISO) $(GEN_ISO_OPTS) -o $@ -graft-points -path-list $(LISTE_FICHIERS_ISO) + +$(POLICE_FNT): $(OBJETS_FNT) + @$(CAT) $(CAT_OPTS) $^ > $@ + +$(NOYAU_ELF): $(OBJETS_LD) + @$(call AFFICHE_LD,$^,$@) + @$(LD) $(LD_OPTS) -o $(NOYAU_ELF) -T $(SCRIPT_LD) $^ + + + +.PRECIOUS: %.dir +%.dir: + @$(MKDIR) $(MKDIR_OPTS) $(dir $@) + @$(CREATE_FILE) $(CREATE_FILE_OPTS) $@ + +$(REP_TRAVAIL)/%.c.o: %.c $(REP_TRAVAIL)/%.dir $(MAKEFILES) + @$(call AFFICHE_CC,$<,$@) + @$(CC) $(CC_OPTS) -MMD -MF $(@:.o=.d) $(CC_INCLUSIONS) -c $< -o $@ + +$(REP_TRAVAIL)/%.S.o: %.S $(REP_TRAVAIL)/%.dir $(MAKEFILES) + @$(call AFFICHE_AS,$<,$@) + @$(CC) $(CC_OPTS) -MMD -MF $(@:.o=.d) $(CC_INCLUSIONS) -c $< -o $@ -DASM + +$(REP_TRAVAIL)/%.fnt.o: %.fnt $(REP_TRAVAIL)/%.dir $(MAKEFILES) $(FN) + @$(call AFFICHE_FN,$<,$@) + @$(FN) $(FN_OPTS) $< $@ diff --git a/src/modules/algo/math/math.c b/src/modules/algo/math/math.c new file mode 100644 index 0000000..a22f593 --- /dev/null +++ b/src/modules/algo/math/math.c @@ -0,0 +1,39 @@ +#include +#include +#include + +MODULE(Math); + +/* denominateur < 2^63 */ +Div64 div64 (uint64 numerateur, uint64 denominateur) { + uint64 reste = 0; + uint64 quotient = 0; + Div64 resultat; + + int i; + for (i = 0; i < 64; i++) { + quotient <<= 1; + reste <<= 1; + reste |= (numerateur & 0x8000000000000000L) ? 1 : 0; + numerateur <<= 1; + if (reste >= denominateur) { + quotient |= 1; + reste -= denominateur; + } + } + + resultat.quotient = quotient; + resultat.reste = reste; + + return resultat; +} + + + +void initMath (void** etat) { + *etat = etatMath; +} + +void deinitMath (void** etat) { + *etat = NULL; +} diff --git a/src/modules/demarrage/multiboot/multiboot.S b/src/modules/demarrage/multiboot/multiboot.S new file mode 100644 index 0000000..b8da44e --- /dev/null +++ b/src/modules/demarrage/multiboot/multiboot.S @@ -0,0 +1,31 @@ +.section .multiboot +.set magicEnTeteMultiboot, 0x1badb002 +.set optionsEnTeteMultiboot, 4 +.set sommeControleEnTeteMultiboot, -(magicEnTeteMultiboot + optionsEnTeteMultiboot) +.set taillePile, 4096 + +.align 4 +.long magicEnTeteMultiboot +.long optionsEnTeteMultiboot +.long sommeControleEnTeteMultiboot +.long 0 +.long 0 +.long 0 +.long 0 +.long 0 +.long 0 +.long 1024 +.long 768 +.long 24 + +.section .text +.globl _start +_start: + mov $(stack+taillePile), %esp + + push %eax + push %ebx + + call pointEntreeNoyau + +.comm stack, taillePile, 4 diff --git a/src/modules/demarrage/multiboot/multiboot.c b/src/modules/demarrage/multiboot/multiboot.c new file mode 100644 index 0000000..a525c08 --- /dev/null +++ b/src/modules/demarrage/multiboot/multiboot.c @@ -0,0 +1,214 @@ +#include +#include +#include + +#include +#include +#include +#include + +MODULE(Multiboot); + +DEPENDANCE_MODULE(Multiboot, Console); + +/* __listeModule et __finListeModules sont définis dans modules/creerImage.lds */ + +extern InfoModule __listeModules; +extern InfoModule __finListeModules; + +extern DependanceModule __listeDependancesModules; +extern DependanceModule __finListeDependancesModules; + + +void afficherNomModule(InfoModule* module) { + CouleurAvAr ancienneCouleur = consoleCouleur(0x00ff00ff, 0); + afficherChaineZ(module->nom); + afficherChaineZ("\n"); + consoleCouleur(ancienneCouleur.av, ancienneCouleur.ar); +} + +void afficherNomsModulesManques(InfoModule* listeModules) { + // effacerConsole(); /* Seulement en mode texte, en mode graphique, l'écran est déjà noir... */ + InfoModule* module = listeModules; + + while (module != NULL) { + if (module->etapeChargementModule == ETAPE_MODULE_INITIALISE) + afficherNomModule(module); + module = module->suivant; + } +} + + +void* triDependancesGet(void* t, uint32 index) { + return ((DependanceModule*)t) + index; +} + +void triDependancesEchange(void* t, uint32 a, uint32 b) { + DependanceModule* tt = t; + DependanceModule c; + + c = tt[a]; + tt[a] = tt[b]; + tt[b] = c; +} + +int triDependancesCmp(void* a, void* b) { + void* aa = ((DependanceModule*)a)->module; + void* bb = ((DependanceModule*)b)->module; + + if (aa < bb) + return -1; + else if (aa == bb) + return 0; + else + return 1; +} + +void pointEntreeNoyau(void* addrInfoMultiboot, uint32 magicMultiboot) { + asm volatile ("cli"); + + int nbModules = 0; + InfoModule* module; + InfoModule* moduleTemp; + InfoModule* listeModules = &__listeModules; + InfoModule* finListeModules = &__finListeModules; + + int i; + int nbDependancesModules; + int premiereDependanceModule; + int derniereDependanceModule; + DependanceModule dependanceRecherchee; + DependanceModule* dependanceModule; + DependanceModule* listeDependancesModules = &__listeDependancesModules; + DependanceModule* finListeDependancesModules = &__finListeDependancesModules; + + /* Pré-initialisation de l'état du module multiboot */ + etatMultiboot->InfoMultiboot = addrInfoMultiboot; + etatMultiboot->magicMultiboot = magicMultiboot; + + + /* Tri de la liste de dépendances */ + nbDependancesModules = ((int)finListeDependancesModules - (int)listeDependancesModules) / sizeof(DependanceModule); + triParTas( + listeDependancesModules, + nbDependancesModules, + triDependancesGet, + triDependancesEchange, + triDependancesCmp + ); + + /* Chaînage des modules */ + nbModules = ((int)finListeModules - (int)listeModules) / sizeof(InfoModule); + module = listeModules; + while (module < finListeModules) { + module->suivant = module + 1; + + dependanceRecherchee = (DependanceModule){ module, NULL }; + premiereDependanceModule = rechercheDichotomiquePremier( + &dependanceRecherchee, + listeDependancesModules, + nbDependancesModules, + triDependancesGet, + triDependancesCmp + ); + + if (premiereDependanceModule < 0) { + module->dependances = NULL; + module->nbDependances = -1; + } else { + derniereDependanceModule = rechercheDichotomiqueDernier( + &dependanceRecherchee, + listeDependancesModules, + nbDependancesModules, + triDependancesGet, + triDependancesCmp + ); + module->dependances = listeDependancesModules + premiereDependanceModule; + module->nbDependances = derniereDependanceModule - premiereDependanceModule + 1; + } + + module++; + } + if (nbModules != 0) + (module-1)->suivant = NULL; + + + /* Initialisation des modules */ + module = (nbModules != 0) ? listeModules : NULL; + bool consoleDisponible = FALSE; + /* GCC BUG : + * + * while ((void*)module != (void*)NULL) { + * ... + * } + * + * Lorsqu'on regarde la sortie assembleur de GCC, on voit qu'il teste + * avant l'entrée dans la boucle s'il doit l'éviter, après quoi aucune + * instruction ne permet d'en sortir. Ce qui explique le fonctionnement + * incorrect du programme à l'exécution. De plus, on se rend compte + * avec des comparaisons ( < , = , > ) qu'il semble considérer que + * 1 < module < 2 (donc on a un pointeur flottant \o/ ). Vu qu'il y a + * très peu de chances pour que l'info sur un module soit située à 1 (!), + * on utilise ((void*)module > (void*)(1)) . */ + + while ((void*)module > (void*)(1)) { + if (module->etapeChargementModule != ETAPE_MODULE_INITIALISE) { + dependanceModule = module->dependances; + + for (i = 0; i < module->nbDependances; i++) { + if (dependanceModule->dependance->etapeChargementModule != ETAPE_MODULE_INITIALISE) { + dependanceModule->dependance->suivantRecursionDependances = module; + module = dependanceModule->dependance; + goto finBoucleInitialisationModules; + } + dependanceModule++; + } + + + if (consoleDisponible) + afficherNomModule(module); + + + (*(module->init)) (module->etat); + module->etapeChargementModule = ETAPE_MODULE_INITIALISE; + + if (!consoleDisponible && consolePrete()) { + consoleDisponible = TRUE; + afficherNomsModulesManques(listeModules); + } + } + + + if (module->suivantRecursionDependances != NULL) { + moduleTemp = module->suivantRecursionDependances; + module->suivantRecursionDependances = NULL; + module = moduleTemp; + } else { + module = module->suivant; + } + + finBoucleInitialisationModules: + {} /* Fausse instruction pour éviter un "error: label at end of compound statement" */ + } + + + /* Fin */ + afficherChaineZ("\n\n"); + + for (;;) asm volatile ("hlt;"); +} + + +void initMultiboot(void** etat) { + *etat = etatMultiboot; + + /* if (etatMultiboot->InfoMultiboot->flags.bootLoaderName) { + afficherChaineZ("Charg" STR_eacute " par "); + afficherChaineZ(etatMultiboot->InfoMultiboot->bootLoaderName); + afficherChaineZ(".\n"); + } */ +} + +void deinitMultiboot(void** etat) { + *etat = NULL; +} diff --git a/src/modules/interfaceUtilisateur/clavier/clavier.c b/src/modules/interfaceUtilisateur/clavier/clavier.c new file mode 100644 index 0000000..5b6a460 --- /dev/null +++ b/src/modules/interfaceUtilisateur/clavier/clavier.c @@ -0,0 +1,26 @@ +#include +#include +#include +#include +#include + +MODULE(Clavier); + +DEPENDANCE_MODULE(Clavier, Kbc); +DEPENDANCE_MODULE(Clavier, Console); + + +void gestionnaireClavier(uint8 scancode) { + afficherEntierEnHexa(scancode); + afficherChaineZ("\n"); +} + +void initClavier (void** etat) { + *etat = NULL; + + definirGestionnaireClavier(gestionnaireClavier); +} + +void deinitClavier (void** etat) { + *etat = NULL; +} diff --git a/src/modules/interfaceUtilisateur/console/console.c b/src/modules/interfaceUtilisateur/console/console.c new file mode 100644 index 0000000..d373926 --- /dev/null +++ b/src/modules/interfaceUtilisateur/console/console.c @@ -0,0 +1,245 @@ +#include +#include +#include + +MODULE(Console); + +/* Cette variable risque d'être utilisée avant l'apel de initConsole(), + * donc on la déclare à l'extérieur de etatConsole, dont la valeur est + * indéfinie tant que initConsole n'a pas été apellée. */ +static bool _consolePrete; + + +Console* definirConsoleActive(Console* console) { + Console* ancienneConsole = etatConsole->consoleActive; + + ancienneConsole->x = etatConsole->x; + ancienneConsole->y = etatConsole->y; + + etatConsole->x = console->x; + etatConsole->y = console->y; + + etatConsole->consoleActive = console; + + _consolePrete = TRUE; + return ancienneConsole; +} + + +CouleurAvAr getConsoleCouleur() { + CouleurAvAr couleurs; + couleurs.av = etatConsole->couleurAv; + couleurs.ar = etatConsole->couleurAr; + return couleurs; +} + +CouleurAvAr consoleCouleur(Couleur couleurAv, Couleur couleurAr) { + CouleurAvAr couleurs = getConsoleCouleur(); + + etatConsole->couleurAv = couleurAv; + etatConsole->couleurAr = couleurAr; + + return couleurs; +} + + +Position getConsolePosition() { + Position pos; + pos.x = etatConsole->x; + pos.y = etatConsole->y; + return pos; +} + +Position consolePosition(uint32 x, uint32 y) { + Position pos = getConsolePosition(); + + if (x >= etatConsole->consoleActive->largeur) { + x %= etatConsole->consoleActive->largeur; + y++; + } + + if (y >= etatConsole->consoleActive->hauteur) { + y %= etatConsole->consoleActive->hauteur; + } + + etatConsole->x = x; + etatConsole->y = y; + + return pos; +} + +void consolePositionAvancerX() { + consolePosition(etatConsole->x + 1, etatConsole->y); +} + +void consolePositionAvancerY() { + consolePosition(etatConsole->x, etatConsole->y + 1); +} + + +void afficherCaractereCouleurPositionBrut(char caractere, uint32 couleurAv, uint32 couleurAr, uint32 x, uint32 y) { + etatConsole->consoleActive->fonctionAffichage(caractere, couleurAv, couleurAr, x, y); + + consolePositionAvancerX(); + + consoleCouleur(couleurAv, couleurAr); +} + +void afficherCaractereCouleurPosition(char caractere, uint32 couleurAv, uint32 couleurAr, uint32 x, uint32 y) { + if (caractere == '\n') + consolePosition(0, etatConsole->y + 1); + else + afficherCaractereCouleurPositionBrut(caractere, couleurAv, couleurAr, x, y); +} + + +void afficherCaractere(char caractere) { + afficherCaractereCouleurPosition(caractere, etatConsole->couleurAv, etatConsole->couleurAr, etatConsole->x, etatConsole->y); +} + +void afficherCaractereBrut(char caractere) { + afficherCaractereCouleurPositionBrut(caractere, etatConsole->couleurAv, etatConsole->couleurAr, etatConsole->x, etatConsole->y); +} + + +void afficherCaractereCouleur(char caractere, uint32 couleurAv, uint32 couleurAr) { + afficherCaractereCouleurPosition(caractere, couleurAv, couleurAr, etatConsole->x, etatConsole->y); +} + +void afficherCaractereCouleurBrut(char caractere, uint32 couleurAv, uint32 couleurAr) { + afficherCaractereCouleurPositionBrut(caractere, couleurAv, couleurAr, etatConsole->x, etatConsole->y); +} + + +void afficherCaracterePosition(char caractere, uint32 x, uint32 y) { + afficherCaractereCouleurPosition(caractere, etatConsole->couleurAv, etatConsole->couleurAr, x, y); +} + +void afficherCaracterePositionBrut(char caractere, uint32 x, uint32 y) { + afficherCaractereCouleurPositionBrut(caractere, etatConsole->couleurAv, etatConsole->couleurAr, x, y); +} + + +void effacerConsole() { + uint32 x, y; + consoleCouleur(0xffffffff, 0); + for (x=0; x < etatConsole->consoleActive->largeur; x++) + for (y=0; y < etatConsole->consoleActive->hauteur; y++) + afficherCaracterePosition(' ', x, y); + consolePosition(0, 0); +} + +void afficherChaineZ(char* chaine) { + while (*chaine) + afficherCaractere(*(chaine++)); +} + +void afficherChaine(char* chaine, int longueur) { + while (longueur-- > 0) + afficherCaractere(*(chaine++)); +} + +void afficherEntierVirguleEnDecimal(uint32 entier, int32 nbDecimales) { + int pos, nbChar = sizeof(int)*4 + 1; + char chiffres[nbChar]; + + for (pos = 0; (pos < nbChar) && ((nbDecimales >= 0) || (entier != 0)); nbDecimales--, pos++) { + if (nbDecimales == 0) + chiffres[pos++]='.'; + chiffres[pos] = 48 + (entier % 10); + entier /= 10; + } + + if (pos == 0) + afficherCaractere('0'); + else + for (pos--; pos >= 0; pos--) + afficherCaractere(chiffres[pos]); +} + +void afficherEntierEnDecimal(uint32 entier) { + int pos, nbChar = sizeof(int)*4; + char chiffres[nbChar]; + + for (pos = 0; (pos < nbChar) && (entier != 0); pos++) { + chiffres[pos] = 48 + (entier % 10); + entier /= 10; + } + + if (pos == 0) + afficherCaractere('0'); + else + for (pos--; pos >= 0; pos--) + afficherCaractere(chiffres[pos]); +} + +void afficherEntierEnHexa(uint32 entier) { + afficherCaractere('0'); + afficherCaractere('x'); + + int pos, nbChar = sizeof(entier)*2; + char hexa[nbChar]; + + for (pos = 0; pos < nbChar; pos++) { + if ((entier % 16) < 10) + hexa[pos] = 48 + (entier % 16); + else + hexa[pos] = 87 + (entier % 16); + entier /= 16; + } + + for (pos--; pos >= 0; pos--) + afficherCaractere(hexa[pos]); +} + +void afficherEntierEnBinaire(uint32 entier) { + int pos = 0; + for (pos = 0; pos < 32; pos++) { + if (entier & 0x80000000) + afficherChaineZ("1"); + else + afficherChaineZ("0"); + entier = entier << 1; + } +} + + +void afficherTableCaracteres() { + int i; + for (i = 0; i < 256; i++) + afficherCaractereBrut(i); +} + + +void fonctionAffichageVide (char caractere, uint32 couleurAv, uint32 couleurAr, uint32 x, uint32 y) { + caractere = caractere; + couleurAv = couleurAv; + couleurAr = couleurAr; + x = x; + y = y; +} + +Console consoleVide = { + .largeur = 80, + .hauteur = 25, + .fonctionAffichage = fonctionAffichageVide +}; + +bool consolePrete() { + return _consolePrete; +} + +void initConsole(void** etat) { + *etat = etatConsole; + + etatConsole->x = 0; + etatConsole->y = 0; + etatConsole->couleurAv = 0xffffffff; + etatConsole->couleurAr = 0x00000000; + definirConsoleActive(&consoleVide); + _consolePrete = FALSE; +} + +void deinitConsole(void** etat) { + *etat = NULL; +} diff --git a/src/modules/interfaceUtilisateur/demo/demo.c b/src/modules/interfaceUtilisateur/demo/demo.c new file mode 100644 index 0000000..cfeef76 --- /dev/null +++ b/src/modules/interfaceUtilisateur/demo/demo.c @@ -0,0 +1,278 @@ +#include +#include +#include +#include +#include +#include +#include + +MODULE(Demo); + +DEPENDANCE_MODULE(Demo, Police); +DEPENDANCE_MODULE(Demo, VesaGraphique); +DEPENDANCE_MODULE(Demo, VgaTexte); +DEPENDANCE_MODULE(Demo, Clavier); + +void demoAffiche(uint32 x1, uint32 y1) { + uint32 fg1 = 0x00880044; + uint32 fg2 = 0x00770055; + uint32 fg3 = 0x00550077; + uint32 fg4 = 0x00440088; + uint32 bg = 0x00ffcccc; + uint32 ctr = 0x00886666; + + policeAfficherCaractereCouleurPosition('L', fg1, bg, x1, y1); + policeAfficherCaractereCouleurPosition('y', fg2, bg, x1 + 8, y1); + policeAfficherCaractereCouleurPosition('r', fg3, bg, x1 + 2*8, y1); + policeAfficherCaractereCouleurPosition('a', fg4, bg, x1 + 3*8, y1); + + rectangleContour (x1 - 1, y1 - 2, x1+(4*8) + 2, y1+15 + 1, ctr); +} + +void faireDemo () { + int32 x1 = 1024/2-8*2; + int32 y1 = 768/2-15/2; + + int32 ac1 = 0x00ff0000; + int32 ac2 = 0x000000ff; + int32 dc1 = 50; + int32 dc2 = 50; + int32 c = ac1; + int32 x2 = 0; + int32 y2 = 768 / 2; + int32 x3 = x2; + int32 y3 = y2; + int32 dx = 3; + int32 dy = 7; + int32 ddx = 1; + int32 ddy = 1; + + while (FALSE) { + demoAffiche(x1, y1); + asm volatile ("hlt"); + asm volatile ("hlt"); + rectanglePlein (x1 - 1, y1 - 2, x1+(4*8) + 2, y1+15 + 1, 0); + + x1 = ((x1 + x1*x1*y1 + y1*3 + 7) % (1024 - 4*8 + 3)) + 1; + y1 = ((y1 + y1*y1*x1 + x1*3 + 42) % (768 - 15 + 3)) + 2; + + dc1 = dc1 + dy / 10; + dc2 = dc1 + dx / 5; + c = dc1 * ac1 + dc2 * ac2; + x3 = x2 + dx; + y3 = y2 + dy; + dx += abs(ddx - 3) - 1; + dy += abs(ddy - 5) - 2; + ddx = (ddx + 1) % 6; + ddy = (ddy + 1) % 10; + + if (x3 >= 1024) { + x3 = 1024 - (x3 % 1024); + dx = -dx; + } + if (y3 >= 768) { + y3 = 768 - (y3 % 768); + dy = -dy; + } + + if (x3 < 0) { + x3 = abs(x3) % 1024; + dx = -dx; + } + if (y3 < 0) { + y3 = abs(y3) % 768; + dy = -dy; + } + + ligne(x2, y2, x3, y3, c); + + x2 = x3; + y2 = y3; + } + + { + int32 alx1 = 1024/2-8*2; + int32 aly1 = 768/2-15/2; + int32 lx1 = alx1; + int32 ly1 = aly1; + int32 lx2 = lx1; + int32 ly2 = ly1; + + uint32 i, compteur = 0, compteur2 = 0; + int32 angle=0; + int32 dangle=3; + int32 ddangle=0; + int32 x1 = 100; + int32 y1 = 768/2; + int32 x2 = x1; + int32 y2 = y1; + int32 ax = lx2; // 1024-100; + int32 ay = ly2; // 768/2; + int32 v = 15; + int32 dx, dy, adx1, ady1, adx2, ady2; + int32 cx1 = 9; + int32 cy1 = 9; + int32 colmod; + + + + int32 noiralx1 = 1024/2-8*2; + int32 noiraly1 = 768/2-15/2; + int32 noirlx1 = noiralx1; + int32 noirly1 = noiraly1; + int32 noirlx2 = noirlx1; + int32 noirly2 = noirly1; + + uint32 noiri, noircompteur = 0, noirprecompteur = 0, noircompteur2 = 0; + int32 noirangle=0; + int32 noirdangle=3; + int32 noirddangle=0; + int32 noirx1 = 100; + int32 noiry1 = 768/2; + int32 noirx2 = noirx1; + int32 noiry2 = noiry1; + int32 noirax = noirlx2; // 1024-100; + int32 noiray = noirly2; // 768/2; + int32 noirv = 15; + int32 noirdx, noirdy, noiradx1, noirady1, noiradx2, noirady2; + int32 noircx1 = 9; + int32 noircy1 = 9; + + while (TRUE) { + // demoAffiche(lx2, ly2); + compteur2++; + compteur = compteur2 / 4; + + // if (compteur2 % 4 == 0) + // asm volatile ("hlt"); + // else + { int t; for (t = 0; t < 1000000; t++) asm volatile ("nop"); } + + // lx2 += sign(alx1-lx2); + // ly2 += sign(aly1-ly2); + lx2 = alx1; + ly2 = aly1; + + rectanglePlein (lx1 - 1, ly1 - 2, lx1+(4*8) + 2, ly1+15 + 1, 0); + demoAffiche(lx2, ly2); + + lx1 = lx2; + ly1 = ly2; + + alx1 = (1024 - 96)/2 + 32 + (1024 - 64) * sinRapide(compteur2 * (2<<7) ) / (2<<15); + aly1 = (768 - 80)/2 + 32 + (768 - 48) * cosRapide(compteur2 * (2<<4)*3) / (2<<15); + + + for (i = 0; i < 2000; i += dx*dx + dy*dy) { + ax = alx1; + ay = aly1; + + adx1 = v * cosRapide(angle) / (2<<15); + ady1 = v * sinRapide(angle) / (2<<15); + + adx2 = (ax-x2) / 100; + ady2 = (ay-y2) / 100; + + dx = (cx1*adx1 + (10-cx1)*adx2) / 10; + dy = (cy1*ady1 + (10-cy1)*ady2) / 10; + + x2 += dx; + y2 += dy; + + dangle += abs(ddangle - 4) - 2; + // dangle++; + angle += dangle*16; + + colmod = 0xcc / 2 + (0xcc * sinRapide(compteur * (2<<4)*15) / (2<<15)); + if ((x1 > 0) && (x1 < 1024) && + (x2 > 0) && (x2 < 1024) && + (y1 > 0) && (y1 < 768) && + (y2 > 0) && (y2 < 768)) + ligne(x1,y1,x2,y2,0x00ff0000 | (colmod << 8) | colmod); + + x1 = x2; + y1 = y2; + } + if (compteur2 % 4 == 0) + ddangle = (ddangle + 1) % 8; + + + + + + if (noirprecompteur <= 15) { + noirprecompteur++; + } else { + + noircompteur2++; + noircompteur = noircompteur2 / 4; + + // noirlx2 += sign(noiralx1-noirlx2); + // noirly2 += sign(noiraly1-noirly2); + noirlx2 = noiralx1; + noirly2 = noiraly1; + + //// rectanglePlein (noirlx1 - 1, noirly1 - 2, noirlx1+(4*8) + 2, noirly1+15 + 1, 0); + //// demoAffiche(noirlx2, noirly2); + + noirlx1 = noirlx2; + noirly1 = noirly2; + + noiralx1 = (1024 - 96)/2 + 32 + (1024 - 64) * sinRapide(noircompteur2 * (2<<7) ) / (2<<15); + noiraly1 = (768 - 80)/2 + 32 + (768 - 48) * cosRapide(noircompteur2 * (2<<4)*3) / (2<<15); + + + for (noiri = 0; noiri < 2000; noiri += noirdx*noirdx + noirdy*noirdy) { + noirax = noiralx1; + noiray = noiraly1; + + noiradx1 = noirv * cosRapide(noirangle) / (2<<15); + noirady1 = noirv * sinRapide(noirangle) / (2<<15); + + noiradx2 = (noirax-noirx2) / 100; + noirady2 = (noiray-noiry2) / 100; + + noirdx = (noircx1*noiradx1 + (10-noircx1)*noiradx2) / 10; + noirdy = (noircy1*noirady1 + (10-noircy1)*noirady2) / 10; + + noirx2 += noirdx; + noiry2 += noirdy; + + noirdangle += abs(noirddangle - 4) - 2; + // dangle++; + noirangle += noirdangle*16; + + if ((noirx1 > 0) && (noirx1 < 1024) && + (noirx2 > 0) && (noirx2 < 1024) && + (noiry1 > 0) && (noiry1 < 768) && + (noiry2 > 0) && (noiry2 < 768)) + ligne(noirx1,noiry1,noirx2,noiry2,0); + + noirx1 = noirx2; + noiry1 = noiry2; + } + if (noircompteur2 % 4 == 0) + noirddangle = (noirddangle + 1) % 8; + + } // if noirprecompteur <= 10 + } + } +} + +void demoNombres() { + int i; + for (i = 0; i <= 10; i++) { + afficherEntierEnDecimal(i); + afficherChaineZ(" "); + } + afficherChaineZ("\n"); +} + + +void initDemo(void** etat) { + *etat = NULL; +} + +void deinitDemo(void** etat) { + *etat = NULL; +} diff --git a/src/modules/interfaceUtilisateur/police/8x15/,.png b/src/modules/interfaceUtilisateur/police/8x15/,.png new file mode 100644 index 0000000000000000000000000000000000000000..826114910786b30549c9ec902e94cfda1fe658ae GIT binary patch literal 98 zcmeAS@N?(olHy`uVBq!ia0vp^96-#^!3-qdU8!RPQfvV}A+A9B|Ns9>Z_d99WQlva tIEHXsPfloIVv916kVsIH;9(Ov${;_Tp=9|9+3P?h44$rjF6*2UngAy!7?=P6 literal 0 HcmV?d00001 diff --git a/src/modules/interfaceUtilisateur/police/8x15/..png b/src/modules/interfaceUtilisateur/police/8x15/..png new file mode 100644 index 0000000000000000000000000000000000000000..34b1bec4454172b4d8b8f27475adae1543fab2e9 GIT binary patch literal 96 zcmeAS@N?(olHy`uVBq!ia0vp^96-#^!3-qdU8!RPQfvV}A+A9B|Ns9>Z_d99WQlsZ rIEHXsPfloIVv916khmaeA;QccKbxUc_4tn)Km`n*u6{1-oD!M<1H%}n literal 0 HcmV?d00001 diff --git a/src/modules/interfaceUtilisateur/police/8x15/0.png b/src/modules/interfaceUtilisateur/police/8x15/0.png new file mode 100644 index 0000000000000000000000000000000000000000..138dc48d35968e451298672fe60a138cc04163be GIT binary patch literal 113 zcmeAS@N?(olHy`uVBq!ia0vp^96-#^!3-qdU8!RPQfvV}A+A9B|Ns9>Z_d99WT|<& zIEHXsPfloIVoPCTW^Q404lrbs;BReIWV_h2L^e@DZ1({M28r7Y@v@6I&j9LR@O1Ta JS?83{1OUWa9eV%( literal 0 HcmV?d00001 diff --git a/src/modules/interfaceUtilisateur/police/8x15/1.png b/src/modules/interfaceUtilisateur/police/8x15/1.png new file mode 100644 index 0000000000000000000000000000000000000000..9d0a15a85e204bfceb91193b6ea2ffe7beb2b161 GIT binary patch literal 105 zcmeAS@N?(olHy`uVBq!ia0vp^96-#^!3-qdU8!RPQfvV}A+A9B|Ns9>Z_d99WXXBD zIEHXsPfloIViRFw=5dzfDG=Nw!K2WS#>&OaAS1(&`Gfb+LZC_pPgg&ebxsLQ0IN6{ A+yDRo literal 0 HcmV?d00001 diff --git a/src/modules/interfaceUtilisateur/police/8x15/2.png b/src/modules/interfaceUtilisateur/police/8x15/2.png new file mode 100644 index 0000000000000000000000000000000000000000..6f471ca7ad6935f2da7568b638f33e787877f1d4 GIT binary patch literal 119 zcmeAS@N?(olHy`uVBq!ia0vp^96-#^!3-qdU8!RPQfvV}A+A9B|Ns9>Z_d99Wa)Ui zIEHXsPfloIVoPCTW^Q40<`Ljzo5964!;5VPpBqbiqhPG1#Db{CQw$8!?F{L=n2h9r P`WQT2{an^LB{Ts5K5QKY literal 0 HcmV?d00001 diff --git a/src/modules/interfaceUtilisateur/police/8x15/3.png b/src/modules/interfaceUtilisateur/police/8x15/3.png new file mode 100644 index 0000000000000000000000000000000000000000..1dc84eea757e4de283cab6d4d51e1d7d4c7f4079 GIT binary patch literal 114 zcmeAS@N?(olHy`uVBq!ia0vp^96-#^!3-qdU8!RPQfvV}A+A9B|Ns9>Z_d99WT|_) zIEHXsPfloIVoPCTW^Q40<`Ljzo5964!z<-zk3^T`hLs0TF)&EyGGrM3HsuCtVeoYI Kb6Mw<&;$V9jU9Oa literal 0 HcmV?d00001 diff --git a/src/modules/interfaceUtilisateur/police/8x15/4.png b/src/modules/interfaceUtilisateur/police/8x15/4.png new file mode 100644 index 0000000000000000000000000000000000000000..cd4b6b5d004d739ca85f80044af3ceb4330d1cf9 GIT binary patch literal 110 zcmeAS@N?(olHy`uVBq!ia0vp^96-#^!3-qdU8!RPQfvV}A+A9B|Ns9>Z_d99WGQ>P zIEHXsPfloIViRFw7II58Fj!Z_d99WNCQ1 zIEHXsPfloIVqQSQ%0luL2v(;OXk; Jvd$@?2>=X^9fJS> literal 0 HcmV?d00001 diff --git a/src/modules/interfaceUtilisateur/police/8x15/6.png b/src/modules/interfaceUtilisateur/police/8x15/6.png new file mode 100644 index 0000000000000000000000000000000000000000..e6dd092a89286784f1eecffd4bc02d2a99e3d517 GIT binary patch literal 118 zcmeAS@N?(olHy`uVBq!ia0vp^96-#^!3-qdU8!RPQfvV}A+A9B|Ns9>Z_d99WNCZ4 zIEHXsPfloIVoPCTW^QThX_&#djO$EG*Fg~j1EtlCh6^?sFmJrU%Eln2!I1p(WpO1? O8-u5-pUXO@geCyZi6O)Q literal 0 HcmV?d00001 diff --git a/src/modules/interfaceUtilisateur/police/8x15/7.png b/src/modules/interfaceUtilisateur/police/8x15/7.png new file mode 100644 index 0000000000000000000000000000000000000000..81a9b6e8fe57dcf31761a243dc9c7da436cbbb00 GIT binary patch literal 110 zcmeAS@N?(olHy`uVBq!ia0vp^96-#^!3-qdU8!RPQfvV}A+A9B|Ns9>Z_d99WGQ>P zIEHXsPfloIVqZ_d99WGQ;O zIEHXsPfloIVoPCTW^Q40<`Ljj5wywrpm{7wT!Mi?s+%G8pP$xCpkfA3S3j3^P6Z_d99WNCW3 zIEHXsPfloIVoPCTW@etjnAWUl#oQyYpes>`!<1(Q#}c-)Tp?@>lIIwb{l1rr0yQys My85}Sb4q9e01H7KVE_OC literal 0 HcmV?d00001 diff --git a/src/modules/interfaceUtilisateur/police/8x15/A.png b/src/modules/interfaceUtilisateur/police/8x15/A.png new file mode 100644 index 0000000000000000000000000000000000000000..0c4d312ea475cd121fee89530b232f8305909032 GIT binary patch literal 108 zcmeAS@N?(olHy`uVBq!ia0vp^96-#^!3-qdU8!RPQfvV}A+A9B|Ns9>Z_d99WGQ;O zIEHXsPfloIVoPCTW|m?$PilC<=w#p^crYPhGdB-|(pkfA3S3j3^P6Z_d99WT|<& zIEHXsPfloIVqZ_d99WT|_) zIEHXsPfloIViRFwW@esokU=!D!OPGwb7agIvV$L4#{ji3c)I$z JtaD0e0sz5)92x)s literal 0 HcmV?d00001 diff --git a/src/modules/interfaceUtilisateur/police/8x15/D.png b/src/modules/interfaceUtilisateur/police/8x15/D.png new file mode 100644 index 0000000000000000000000000000000000000000..8b7032f50d48804d3cc52919a228ee2602620790 GIT binary patch literal 113 zcmeAS@N?(olHy`uVBq!ia0vp^96-#^!3-qdU8!RPQfvV}A+A9B|Ns9>Z_d99WT|<& zIEHXsPfloIVqzopr0OY0}umAu6 literal 0 HcmV?d00001 diff --git a/src/modules/interfaceUtilisateur/police/8x15/E.png b/src/modules/interfaceUtilisateur/police/8x15/E.png new file mode 100644 index 0000000000000000000000000000000000000000..10c5cb9a9125ee9787c4d22ec574c416c6ba1d97 GIT binary patch literal 109 zcmeAS@N?(olHy`uVBq!ia0vp^96-#^!3-qdU8!RPQfvV}A+A9B|Ns9>Z_d99WGQ*N zIEHXsPfloIVqZ_d99WXXHF zIEHXsPfloIVq*HnlNnGcgQu&X%Q~loCII9k B8L$8V literal 0 HcmV?d00001 diff --git a/src/modules/interfaceUtilisateur/police/8x15/G.png b/src/modules/interfaceUtilisateur/police/8x15/G.png new file mode 100644 index 0000000000000000000000000000000000000000..5ef54da865d6bde511f6dba5cd8cde4bc86574b0 GIT binary patch literal 117 zcmeAS@N?(olHy`uVBq!ia0vp^96-#^!3-qdU8!RPQfvV}A+A9B|Ns9>Z_d99WNCT2 zIEHXsPfloIViRFwW@esokU=!D!OPGfDY-$^_`pvd37!p=8DR?y7^IaL(&jIjeha9J N!PC{xWt~$(697~nAAkS= literal 0 HcmV?d00001 diff --git a/src/modules/interfaceUtilisateur/police/8x15/H.png b/src/modules/interfaceUtilisateur/police/8x15/H.png new file mode 100644 index 0000000000000000000000000000000000000000..499ebc5641f9a21625f4a0dcc8fb2ffb428e3284 GIT binary patch literal 101 zcmeAS@N?(olHy`uVBq!ia0vp^96-#^!3-qdU8!RPQfvV}A+A9B|Ns9>Z_d99WJ!6t wIEHXsPfloIVqmdKI;Vst0ActTFaQ7m literal 0 HcmV?d00001 diff --git a/src/modules/interfaceUtilisateur/police/8x15/I.png b/src/modules/interfaceUtilisateur/police/8x15/I.png new file mode 100644 index 0000000000000000000000000000000000000000..a50067108a4ba08c442c6876194293226b89a1d4 GIT binary patch literal 104 zcmeAS@N?(olHy`uVBq!ia0vp^96-#^!3-qdU8!RPQfvV}A+A9B|Ns9>Z_d99WXXEE zIEHXsPfloIVpCyb=5TP4NC*-!oWSFZ_d99WGQ&M zIEHXsPfloIVq+6KWfPY8gCT{an^LB{Ts5 D6K@-d literal 0 HcmV?d00001 diff --git a/src/modules/interfaceUtilisateur/police/8x15/K.png b/src/modules/interfaceUtilisateur/police/8x15/K.png new file mode 100644 index 0000000000000000000000000000000000000000..43a068ad1f7e1cdd2a321170aac89347c0d46802 GIT binary patch literal 116 zcmeAS@N?(olHy`uVBq!ia0vp^96-#^!3-qdU8!RPQfvV}A+A9B|Ns9>Z_d99WNCW3 zIEHXsPfloIVqTMtEM#Rf1iNR>0B`YmOB2Gqph M>FVdQ&MBb@07yX}RR910 literal 0 HcmV?d00001 diff --git a/src/modules/interfaceUtilisateur/police/8x15/L.png b/src/modules/interfaceUtilisateur/police/8x15/L.png new file mode 100644 index 0000000000000000000000000000000000000000..9351a9d7e59cded668d3561592c0b900ec29649a GIT binary patch literal 98 zcmeAS@N?(olHy`uVBq!ia0vp^96-#^!3-qdU8!RPQfvV}A+A9B|Ns9>Z_d99WQlva tIEHXsPfloIVqZ_d99WGQ*N zIEHXsPfloIVqZ_d99WGQ*N zIEHXsPfloIVqZ_d99WGQ&M zIEHXsPfloIVoPCTW^Q40<`Li&lH_197wC>nU|^8yW=K7#5q1-(mci52&t;ucLK6Vh C8yOk^ literal 0 HcmV?d00001 diff --git a/src/modules/interfaceUtilisateur/police/8x15/P.png b/src/modules/interfaceUtilisateur/police/8x15/P.png new file mode 100644 index 0000000000000000000000000000000000000000..4915a18372b6a8a8a43e41441fa06bfc8e767854 GIT binary patch literal 108 zcmeAS@N?(olHy`uVBq!ia0vp^96-#^!3-qdU8!RPQfvV}A+A9B|Ns9>Z_d99WGQ;O zIEHXsPfloIVqZ_d99WGQ>P zIEHXsPfloIVoPCTW^Q40<`LjrBw4`K<-lgNAgb{c1A~+;Lvs5wre8qi44$rjF6*2U FngCb^8`J;* literal 0 HcmV?d00001 diff --git a/src/modules/interfaceUtilisateur/police/8x15/R.png b/src/modules/interfaceUtilisateur/police/8x15/R.png new file mode 100644 index 0000000000000000000000000000000000000000..6dd0ba491d6a4546c3ce3a607d225490af29e5ac GIT binary patch literal 112 zcmeAS@N?(olHy`uVBq!ia0vp^96-#^!3-qdU8!RPQfvV}A+A9B|Ns9>Z_d99WT|?( zIEHXsPfloIVqZ_d99WNCT2 zIEHXsPfloIVoPCT7HE**2@qs+D`5-Zj1gy!QC$|aLF9&oiFSY_gS0e5`iYd}zd&6K Mp00i_>zopr01R^-Gynhq literal 0 HcmV?d00001 diff --git a/src/modules/interfaceUtilisateur/police/8x15/T.png b/src/modules/interfaceUtilisateur/police/8x15/T.png new file mode 100644 index 0000000000000000000000000000000000000000..ecccc0edf9b4cf79640706a52890608924852c74 GIT binary patch literal 102 zcmeAS@N?(olHy`uVBq!ia0vp^96-#^!3-qdU8!RPQfvV}A+A9B|Ns9>Z_d99WJ!Cv wIEHXsPfloIVpCyb=5TP4NC>);WRR2!lv}`%tvy308>o!I)78&qol`;+0D-z000000 literal 0 HcmV?d00001 diff --git a/src/modules/interfaceUtilisateur/police/8x15/U.png b/src/modules/interfaceUtilisateur/police/8x15/U.png new file mode 100644 index 0000000000000000000000000000000000000000..b93f8224e0004d896ee29462a523c14e88bba404 GIT binary patch literal 101 zcmeAS@N?(olHy`uVBq!ia0vp^96-#^!3-qdU8!RPQfvV}A+A9B|Ns9>Z_d99WJ!6t wIEHXsPfloIVqzopr0FQwhI{*Lx literal 0 HcmV?d00001 diff --git a/src/modules/interfaceUtilisateur/police/8x15/V.png b/src/modules/interfaceUtilisateur/police/8x15/V.png new file mode 100644 index 0000000000000000000000000000000000000000..46e121d2878e74c0ed32970987a7fe0f367f2e86 GIT binary patch literal 105 zcmeAS@N?(olHy`uVBq!ia0vp^96-#^!3-qdU8!RPQfvV}A+A9B|Ns9>Z_d99WXXBD zIEHXsPfloIVqZ_d99WXX8C zIEHXsPfloIVqKHs-{an^LB{Ts5*FYQ0 literal 0 HcmV?d00001 diff --git a/src/modules/interfaceUtilisateur/police/8x15/X.png b/src/modules/interfaceUtilisateur/police/8x15/X.png new file mode 100644 index 0000000000000000000000000000000000000000..2912c40637dc27cbe2dbae84146bb690054b40e3 GIT binary patch literal 109 zcmeAS@N?(olHy`uVBq!ia0vp^96-#^!3-qdU8!RPQfvV}A+A9B|Ns9>Z_d99WGQ*N zIEHXsPfloIVq+A)w66tgOY%oM^~?SWkn2L8_Y}^|Ew<4^TCOr>mdKI;Vst E035Fw$p8QV literal 0 HcmV?d00001 diff --git a/src/modules/interfaceUtilisateur/police/8x15/Y.png b/src/modules/interfaceUtilisateur/police/8x15/Y.png new file mode 100644 index 0000000000000000000000000000000000000000..af76e6be5cf0872d4cfd2671f2249383349b4fc2 GIT binary patch literal 103 zcmeAS@N?(olHy`uVBq!ia0vp^96-#^!3-qdU8!RPQfvV}A+A9B|Ns9>Z_d99WXX8C zIEHXsPfloIVpCybo^j~Z0VTetf+rJ>oMK>*?qbNAaiexUP#uG(tDnm{r-UW|1OOds literal 0 HcmV?d00001 diff --git a/src/modules/interfaceUtilisateur/police/8x15/Z.png b/src/modules/interfaceUtilisateur/police/8x15/Z.png new file mode 100644 index 0000000000000000000000000000000000000000..0f82bca6da78280c66866b92e459a20fd6d2656c GIT binary patch literal 112 zcmeAS@N?(olHy`uVBq!ia0vp^96-#^!3-qdU8!RPQfvV}A+A9B|Ns9>Z_d99WT|?( zIEHXsPfloIVqZ_d99WT|<& zIEHXsPfloIVq3$*#>T*nZ_d99WGQ>P zIEHXsPfloIV$V<(;gExeqv+!;+zit57}9Z_d99WGQ&M zIEHXsPfloIVpEdj;o(VOV-9I)6jWzk$F`7r`bh@a1q^vFMGkERs%7wW^>bP0l+XkK D4$d2p literal 0 HcmV?d00001 diff --git a/src/modules/interfaceUtilisateur/police/8x15/curseur.png b/src/modules/interfaceUtilisateur/police/8x15/curseur.png new file mode 100644 index 0000000000000000000000000000000000000000..8a523dcaed645a498db24e7844a86be563b012d2 GIT binary patch literal 121 zcmeAS@N?(olHy`uVBq!ia0vp^96-#^!3-qdU8!RPQfvV}A+A9B|Ns9>Z_d99Wa)Xj zIEHXsk3H?k$6&z0bnxl_`DS8 RR}4@mgQu&X%Q~loCIDJKBYpq? literal 0 HcmV?d00001 diff --git a/src/modules/interfaceUtilisateur/police/8x15/d.png b/src/modules/interfaceUtilisateur/police/8x15/d.png new file mode 100644 index 0000000000000000000000000000000000000000..5ddcfb5e04bde7392f3575eb9e542b73346d9187 GIT binary patch literal 109 zcmeAS@N?(olHy`uVBq!ia0vp^96-#^!3-qdU8!RPQfvV}A+A9B|Ns9>Z_d99WGQ*N zIEHXsPfloIVvFHnli^`w<7j3)*y3?evOqIM^u}8z2I+$gX+Cm`)&W&Bc)I$ztaD0e F0svE196Z_d99WGQ>P zIEHXsPfloIVpEdj;SpftF?3LA5MX(rWWZVw%TwXY#voJ2kjeG=yZ}%+gQu&X%Q~lo FCIBnt8ZZC= literal 0 HcmV?d00001 diff --git a/src/modules/interfaceUtilisateur/police/8x15/espace.png b/src/modules/interfaceUtilisateur/police/8x15/espace.png new file mode 100644 index 0000000000000000000000000000000000000000..e4cc615351f1d0dd1d44aeb0602c61c582641d92 GIT binary patch literal 90 zcmeAS@N?(olHy`uVBq!ia0vp^96-#^!3-qdU8!RPQfvV}A+A9B|Ns9>Z_d99lJ<0Q k4B@z*oY2D5#+b^$prFlAdG*b^X+S9kPgg&ebxsLQ0EWRAvj6}9 literal 0 HcmV?d00001 diff --git a/src/modules/interfaceUtilisateur/police/8x15/f.png b/src/modules/interfaceUtilisateur/police/8x15/f.png new file mode 100644 index 0000000000000000000000000000000000000000..c9b00e539cc066a4d697614a42aae027a44db3be GIT binary patch literal 108 zcmeAS@N?(olHy`uVBq!ia0vp^96-#^!3-qdU8!RPQfvV}A+A9B|Ns9>Z_d99WGQ;O zIEHXsPfloIVtd2G#>UaisCDQ-$H9bz1DdS|52T7S$XsE_JmdKI;Vst E0GWUv8vpZ_d99WGQ;O zIEHXsPfloIVhfVw;SpftF?3LwAdzr{A-G4gHHD8smY*SY)}=R9K*bE6u6{1-oD!M< D9ZnlQ literal 0 HcmV?d00001 diff --git a/src/modules/interfaceUtilisateur/police/8x15/h.png b/src/modules/interfaceUtilisateur/police/8x15/h.png new file mode 100644 index 0000000000000000000000000000000000000000..47e608946ca0af3370657597c3429e81b48364d5 GIT binary patch literal 104 zcmeAS@N?(olHy`uVBq!ia0vp^96-#^!3-qdU8!RPQfvV}A+A9B|Ns9>Z_d99WXXEE zIEHXsPfloIV$0!StKnhOXlB&nd-yp0!6t4787GEJ`H6eEfeINsUHx3vIVCg!0M|Pj A$p8QV literal 0 HcmV?d00001 diff --git a/src/modules/interfaceUtilisateur/police/8x15/i.png b/src/modules/interfaceUtilisateur/police/8x15/i.png new file mode 100644 index 0000000000000000000000000000000000000000..ff633344828e3e61d436f5717b1667c960964217 GIT binary patch literal 100 zcmeAS@N?(olHy`uVBq!ia0vp^96-#^!3-qdU8!RPQfvV}A+A9B|Ns9>Z_d99WJ!9u vIEHXsPfloIVq@ZAyQAb{AR!^~A&QYf&X1vhIr<Z_d99WJ!6t wIEHXsPfloIVq@ZAyQ5?w$x|T6#uUcDAeYEc$hQ1Y22d4)r>mdKI;Vst08z>pZ_d99WGQ*N zIEHXsPfloIV$zopr E08SJexc~qF literal 0 HcmV?d00001 diff --git a/src/modules/interfaceUtilisateur/police/8x15/l.png b/src/modules/interfaceUtilisateur/police/8x15/l.png new file mode 100644 index 0000000000000000000000000000000000000000..92c4791675b7b667cc68a7ac4968a7e341989de1 GIT binary patch literal 97 zcmeAS@N?(olHy`uVBq!ia0vp^96-#^!3-qdU8!RPQfvV}A+A9B|Ns9>Z_d99WQlpY tIEHXsPfloIVq3$*re!E#^QMfELG}bg!MfZvtAHvPJYD@<);T3K0RSjs8Cd`T literal 0 HcmV?d00001 diff --git a/src/modules/interfaceUtilisateur/police/8x15/m.png b/src/modules/interfaceUtilisateur/police/8x15/m.png new file mode 100644 index 0000000000000000000000000000000000000000..98245a38caf3bc06e76f2f9a00190e3be35a1a51 GIT binary patch literal 99 zcmeAS@N?(olHy`uVBq!ia0vp^96-#^!3-qdU8!RPQfvV}A+A9B|Ns9>Z_d99WJ!3s uIEHXsPfloIViS_&Nswa}5juGwQ-MKdF++ywM&+wOH4L7velF{r5}E)$*BHV8 literal 0 HcmV?d00001 diff --git a/src/modules/interfaceUtilisateur/police/8x15/magickCPZzva b/src/modules/interfaceUtilisateur/police/8x15/magickCPZzva new file mode 100644 index 0000000..e69de29 diff --git a/src/modules/interfaceUtilisateur/police/8x15/magickILOpac b/src/modules/interfaceUtilisateur/police/8x15/magickILOpac new file mode 100644 index 0000000..e69de29 diff --git a/src/modules/interfaceUtilisateur/police/8x15/magickNIygPK b/src/modules/interfaceUtilisateur/police/8x15/magickNIygPK new file mode 100644 index 0000000..e69de29 diff --git a/src/modules/interfaceUtilisateur/police/8x15/magickTAbVVp b/src/modules/interfaceUtilisateur/police/8x15/magickTAbVVp new file mode 100644 index 0000000..e69de29 diff --git a/src/modules/interfaceUtilisateur/police/8x15/magickUbyoYb b/src/modules/interfaceUtilisateur/police/8x15/magickUbyoYb new file mode 100644 index 0000000..e69de29 diff --git a/src/modules/interfaceUtilisateur/police/8x15/magickYmNcu2 b/src/modules/interfaceUtilisateur/police/8x15/magickYmNcu2 new file mode 100644 index 0000000..e69de29 diff --git a/src/modules/interfaceUtilisateur/police/8x15/magickcylYvt b/src/modules/interfaceUtilisateur/police/8x15/magickcylYvt new file mode 100644 index 0000000..e69de29 diff --git a/src/modules/interfaceUtilisateur/police/8x15/magickdVV9sC b/src/modules/interfaceUtilisateur/police/8x15/magickdVV9sC new file mode 100644 index 0000000..e69de29 diff --git a/src/modules/interfaceUtilisateur/police/8x15/magickmas2Rl b/src/modules/interfaceUtilisateur/police/8x15/magickmas2Rl new file mode 100644 index 0000000..e69de29 diff --git a/src/modules/interfaceUtilisateur/police/8x15/magicknw0TJ4 b/src/modules/interfaceUtilisateur/police/8x15/magicknw0TJ4 new file mode 100644 index 0000000..e69de29 diff --git a/src/modules/interfaceUtilisateur/police/8x15/magickoVnTPK b/src/modules/interfaceUtilisateur/police/8x15/magickoVnTPK new file mode 100644 index 0000000..e69de29 diff --git a/src/modules/interfaceUtilisateur/police/8x15/magickuHXNJE b/src/modules/interfaceUtilisateur/police/8x15/magickuHXNJE new file mode 100644 index 0000000..e69de29 diff --git a/src/modules/interfaceUtilisateur/police/8x15/n.png b/src/modules/interfaceUtilisateur/police/8x15/n.png new file mode 100644 index 0000000000000000000000000000000000000000..f3ddbd8f711998c10cb48b8e1846ca8d20d1bad0 GIT binary patch literal 101 zcmeAS@N?(olHy`uVBq!ia0vp^96-#^!3-qdU8!RPQfvV}A+A9B|Ns9>Z_d99WJ!6t wIEHXsPfloIViS_&Ns#L}$na38wLp@CK{k#d=hMAusX$c>p00i_>zopr0FF-@hyVZp literal 0 HcmV?d00001 diff --git a/src/modules/interfaceUtilisateur/police/8x15/o.png b/src/modules/interfaceUtilisateur/police/8x15/o.png new file mode 100644 index 0000000000000000000000000000000000000000..38d4967647f6f9f434daa49968dfcba53c2b844d GIT binary patch literal 105 zcmeAS@N?(olHy`uVBq!ia0vp^96-#^!3-qdU8!RPQfvV}A+A9B|Ns9>Z_d99WXXBD zIEHXsPfloIVhfVw;SpftF?3LwAi=>B-gDZ4L3S}iZo0o)7EmRFr>mdKI;Vst0J)tR ALI3~& literal 0 HcmV?d00001 diff --git a/src/modules/interfaceUtilisateur/police/8x15/p.png b/src/modules/interfaceUtilisateur/police/8x15/p.png new file mode 100644 index 0000000000000000000000000000000000000000..3a5966041a9f8f14aa55ec5a0a6fa12a9efad845 GIT binary patch literal 108 zcmeAS@N?(olHy`uVBq!ia0vp^96-#^!3-qdU8!RPQfvV}A+A9B|Ns9>Z_d99WGQ;O zIEHXsPfloIVhfVw;SpftF?3LwAjzS*B8hEASqU41tQtec|0+E{pkfA3S3j3^P6Z_d99WGQ*N zIEHXsPfloIVhfVw;SpftF?3LwAdzr{A@~f#<-T4<23dQCi~_cG+CbF|p00i_>zopr E06Ezj{r~^~ literal 0 HcmV?d00001 diff --git a/src/modules/interfaceUtilisateur/police/8x15/r.png b/src/modules/interfaceUtilisateur/police/8x15/r.png new file mode 100644 index 0000000000000000000000000000000000000000..441ce5ec07c72aff7eefe8a361b43ba24cb6cf69 GIT binary patch literal 101 zcmeAS@N?(olHy`uVBq!ia0vp^96-#^!3-qdU8!RPQfvV}A+A9B|Ns9>Z_d99WJ!6t xIEHXsPfloIVk?s5Ns#L}$RK|3Z_d99WGQ*N zIEHXsPfloIVpEdj;o(VOWAZ_d99WXX8C yIEHXsPfloIV%x*R=EKI!?5D}YrtD*=r_CT+z>xQQ|HE5Abqt=aelF{r5}E**SsCd7 literal 0 HcmV?d00001 diff --git a/src/modules/interfaceUtilisateur/police/8x15/u.png b/src/modules/interfaceUtilisateur/police/8x15/u.png new file mode 100644 index 0000000000000000000000000000000000000000..9df3defbfb399a874dd338e47e5fac3822043159 GIT binary patch literal 98 zcmeAS@N?(olHy`uVBq!ia0vp^96-#^!3-qdU8!RPQfvV}A+A9B|Ns9>Z_d99WQlva uIEHXsPfloIViS@)qR7UZ_d99WJ!3s uIEHXsPfloIViS@)qM*=bw7_N#8xw=<5r#Z%$;nJWH4L7velF{r5}E)-^B7zJ literal 0 HcmV?d00001 diff --git a/src/modules/interfaceUtilisateur/police/8x15/w.png b/src/modules/interfaceUtilisateur/police/8x15/w.png new file mode 100644 index 0000000000000000000000000000000000000000..e95961a85ffdb40b7f50bc12ed9af509c253c9ac GIT binary patch literal 97 zcmeAS@N?(olHy`uVBq!ia0vp^96-#^!3-qdU8!RPQfvV}A+A9B|Ns9>Z_d99WQlpY sIEHXsPfloIV!I?E;Gx3o^w?N{L8go$V-fqxD?k+tp00i_>zopr03WOvyZ`_I literal 0 HcmV?d00001 diff --git a/src/modules/interfaceUtilisateur/police/8x15/x.png b/src/modules/interfaceUtilisateur/police/8x15/x.png new file mode 100644 index 0000000000000000000000000000000000000000..954f674226ce141f313f1d15522a3e608fbb6cab GIT binary patch literal 103 zcmeAS@N?(olHy`uVBq!ia0vp^96-#^!3-qdU8!RPQfvV}A+A9B|Ns9>Z_d99WXX8C yIEHXsPfloIVl$HDNnjC6Z17xYJmJa%19k>ER)#!1C7};Mbqt=aelF{r5}E+BfEoS( literal 0 HcmV?d00001 diff --git a/src/modules/interfaceUtilisateur/police/8x15/y.png b/src/modules/interfaceUtilisateur/police/8x15/y.png new file mode 100644 index 0000000000000000000000000000000000000000..9bef0897e0cc7fc74701d6e2fcc6f96ffcd7bca8 GIT binary patch literal 106 zcmeAS@N?(olHy`uVBq!ia0vp^96-#^!3-qdU8!RPQfvV}A+A9B|Ns9>Z_d99WXXHF zIEHXsPfloIV!I^4W5C7F+@ny##-Z_d99WGQ&M zIEHXsPfloIVtXXPqrf2CXehBDOJagSjDWMa* +#include +#include +#include +#include + +MODULE(Police); + +DEPENDANCE_MODULE(Police, Multiboot); +// DEPENDANCE_MODULE(Police, VesaGraphique); + +extern EtatMultiboot* etatMultiboot; + +void initPolice (void** etat) { + *etat = etatPolice; + + etatPolice->tableCaracteres = etatMultiboot->InfoMultiboot->modsAddr[0].modStart; +} + +void deinitPolice (void** etat) { + *etat = NULL; +} + +void policeAfficherCaractereCouleurPosition(char caractere, uint32 couleurAv, uint32 couleurAr, uint32 x, uint32 y) { + int i, j; + for (i = 0; i < 15; i++) + for (j = 0; j < 8; j++) + if ((etatPolice->tableCaracteres[(uint8)caractere * 15 + i] >> j) & 1) + setPixel32(x + 8 - j, y + i, couleurAv); + else + setPixel32(x + 8 - j, y + i, couleurAr); +} diff --git a/src/modules/modeleModule.c b/src/modules/modeleModule.c new file mode 100644 index 0000000..6125fe5 --- /dev/null +++ b/src/modules/modeleModule.c @@ -0,0 +1,18 @@ +#include +#include +#include + +#include /* DEBUG */ + +MODULE(ModeleModule); + +/* DEPENDANCE_MODULE(ModeleModule, ...); */ +DEPENDANCE_MODULE(ModeleModule, Console); /* DEBUG */ + +void initModeleModule (void** etat) { + *etat = etatModeleModule; +} + +void deinitModeleModule (void** etat) { + *etat = NULL; +} diff --git a/src/modules/pc/gdt/gdt.c b/src/modules/pc/gdt/gdt.c new file mode 100644 index 0000000..b811844 --- /dev/null +++ b/src/modules/pc/gdt/gdt.c @@ -0,0 +1,39 @@ +#include +#include +#include +#include + +MODULE(Gdt); + +static DescripteurSegment tableDescripteursSegment[] = { + [0] = descripteurSegmentNULL, + [1] = descripteurSegmentBasicFlatModel(SEGMENT_CODE), + [2] = descripteurSegmentBasicFlatModel(SEGMENT_DONNEES) +}; + +void initGdt (void** etat) { + *etat = etatGdt; + + etatGdt->tableDescripteursSegment = tableDescripteursSegment; + etatGdt->registreGDTR.base = etatGdt->tableDescripteursSegment; + etatGdt->registreGDTR.limite = sizeof (tableDescripteursSegment) - 1; + + asm volatile ("\ + lgdt %0 \n\ + ljmp %1, $label \n\ + label: \n\ + movw %2, %%ax \n\ + movw %%ax, %%ds \n\ + movw %%ax, %%es \n\ + movw %%ax, %%fs \n\ + movw %%ax, %%gs \n\ + movw %%ax, %%ss" + : + : "m" (etatGdt->registreGDTR), "g" (8), "g" (16) + : "memory", "eax" + ); +} + +void deinitGdt (void** etat) { + *etat = NULL; +} diff --git a/src/modules/pc/idt/idt.S b/src/modules/pc/idt/idt.S new file mode 100644 index 0000000..6d1ab7b --- /dev/null +++ b/src/modules/pc/idt/idt.S @@ -0,0 +1,79 @@ +.section .text + +.irp _ligne_1,0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f +.irp _ligne_2,0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f + +.globl enregistrerContexteInterruption\_ligne_1\_ligne_2 +enregistrerContexteInterruption\_ligne_1\_ligne_2: + +/* Les noms de registres proviennent de : + * x86-doc-vol3.pdf fig 6.2 (section 6.2.1) */ +pushl %esp +pushl %ebp + +pushl %edi +pushl %esi + +pushl %eax +pushl %ebx +pushl %ecx +pushl %edx + +subl $2,%esp +pushw %ds +pushw %es +pushw %fs +pushw %gs +pushw %ss + +call *(tableGestionnairesInterruption + 4*0x\_ligne_1\_ligne_2) + +popw %ss +popw %gs +popw %fs +popw %es +popw %ds +addl $2,%esp + +popl %edx +popl %ecx +popl %ebx +popl %eax + +popl %esi +popl %edi + +popl %ebp +popl %esp + +iret + +.endr +.endr + + +.section .data + +.globl tableEnregistreursContexteInterruption +tableEnregistreursContexteInterruption: +.irp _ligne_1,0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f +.irp _ligne_2,0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f + .long (enregistrerContexteInterruption\_ligne_1\_ligne_2) +.endr +.endr + +/* .globl tableEnregistreursContexteInterruption + tableEnregistreursContexteInterruption: + .long (_tableEnregistreursContexteInterruption) */ + +.globl tableGestionnairesInterruption +tableGestionnairesInterruption: +.irp _ligne_1,0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f +.irp _ligne_2,0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f + .long (gestionnaireInterruptionVide) +.endr +.endr + +/* .globl tableGestionnairesInterruption + tableGestionnairesInterruption: + .long (_tableGestionnairesInterruption) */ diff --git a/src/modules/pc/idt/idt.c b/src/modules/pc/idt/idt.c new file mode 100644 index 0000000..53a286a --- /dev/null +++ b/src/modules/pc/idt/idt.c @@ -0,0 +1,90 @@ +#include +#include +#include +#include + +MODULE(Idt); + +DEPENDANCE_MODULE(Idt, Gdt); + +extern EnregistreurContexteInterruption tableEnregistreursContexteInterruption[]; +extern GestionnaireInterruption tableGestionnairesInterruption[]; + +void gestionnaireInterruptionVide() { +} + +void initIdt (void** etat) { + *etat = etatIdt; + + etatIdt->interruptionsDesactivees = 0; + desactiverInterruptions(); + + etatIdt->nombreDescripteursInterruption = LONGUEUR(etatIdt->tableDescripteursInterruption); + etatIdt->registreIDTR.base = etatIdt->tableDescripteursInterruption; + etatIdt->registreIDTR.limite = sizeof (etatIdt->tableDescripteursInterruption) - 1; + + int i; + for (i = 0; i < etatIdt->nombreDescripteursInterruption; i++) + etatIdt->tableDescripteursInterruption[i] = (DescripteurInterruption){ + .offset_15_0 = (uint32)(tableEnregistreursContexteInterruption[i]) & 0xffff, + .selecteurSegment = 1 << 3, /* Segment de code */ + + ._zero_a = 0, + /* .type = 0, + ._un = 1, + .taillePorte = 0, + ._zero_b = 0, */ + .type = 14, + .niveauPrivilegeDescripteur = 0, + .present = FALSE, + .offset_31_16 = (((uint32)(tableEnregistreursContexteInterruption[i])) >> 16) & 0xffff + }; + + asm volatile ("lidt %0" + : + : "m" (etatIdt->registreIDTR) + : "memory" + ); + + activerInterruptions(); +} + +void deinitIdt (void** etat) { + *etat = NULL; +} + +int desactiverInterruptions() { + asm volatile ("cli"); + etatIdt->interruptionsDesactivees++; + return 0; +} + +int activerInterruptions() { + if (etatIdt->interruptionsDesactivees <= 1) { + etatIdt->interruptionsDesactivees = 0; + asm volatile ("sti"); + } else { + etatIdt->interruptionsDesactivees--; + } + return 0; +} + +void definirGestionnaireInterruption(int numeroInterruption, GestionnaireInterruption gestionnaire) { + desactiverInterruptions(); + + tableGestionnairesInterruption[numeroInterruption] = gestionnaire; + + activerInterruptions(); +} + +void activerInterruption(int numeroInterruption) { + desactiverInterruptions(); + etatIdt->tableDescripteursInterruption[numeroInterruption].present = TRUE; + activerInterruptions(); +} + +void desactiverInterruption(int numeroInterruption) { + desactiverInterruptions(); + etatIdt->tableDescripteursInterruption[numeroInterruption].present = FALSE; + activerInterruptions(); +} diff --git a/src/modules/pc/io/io.c b/src/modules/pc/io/io.c new file mode 100644 index 0000000..203142a --- /dev/null +++ b/src/modules/pc/io/io.c @@ -0,0 +1,13 @@ +#include +#include +#include + +MODULE(Io); + +void initIo (void** etat) { + *etat = NULL; +} + +void deinitIo (void** etat) { + *etat = NULL; +} diff --git a/src/modules/pc/irq/irq.S b/src/modules/pc/irq/irq.S new file mode 100644 index 0000000..c01995a --- /dev/null +++ b/src/modules/pc/irq/irq.S @@ -0,0 +1,53 @@ +.section .text + +.irp ligne,0,1,2,3,4,5,6,7 + +.globl envoyerFinInterruptionMaitre\ligne +envoyerFinInterruptionMaitre\ligne: + +mov $0x20, %al +outb %al, $0x20 + +call *(tableGestionnairesRequeteInterruption + 4*\ligne) + +ret + +.endr + + +.irp ligne,0,1,2,3,4,5,6,7 + +.globl envoyerFinInterruptionEsclave\ligne +envoyerFinInterruptionEsclave\ligne: + +mov $0x20, %al +outb %al, $0xa0 +outb %al, $0x20 + +call *(tableGestionnairesRequeteInterruption + 4*(8 + \ligne)) + +ret + +.endr + + +.section .data + +.globl tableFonctionsEnvoiFinInterruption +tableFonctionsEnvoiFinInterruption: +.irp ligne,0,1,2,3,4,5,6,7 + .long (envoyerFinInterruptionMaitre\ligne) +.endr +.irp ligne,0,1,2,3,4,5,6,7 + .long (envoyerFinInterruptionEsclave\ligne) +.endr + + +.globl tableGestionnairesRequeteInterruption +tableGestionnairesRequeteInterruption: +.irp ligne,0,1,2,3,4,5,6,7 + .long (gestionnaireRequeteInterruptionVide) +.endr +.irp ligne,0,1,2,3,4,5,6,7 + .long (gestionnaireRequeteInterruptionVide) +.endr diff --git a/src/modules/pc/irq/irq.c b/src/modules/pc/irq/irq.c new file mode 100644 index 0000000..307c4cc --- /dev/null +++ b/src/modules/pc/irq/irq.c @@ -0,0 +1,132 @@ +#include +#include +#include +#include +#include +#include /* DEBUG */ + +MODULE(Irq); + +DEPENDANCE_MODULE(Irq, Idt); +DEPENDANCE_MODULE(Irq, Io); + +extern GestionnaireRequeteInterruption tableFonctionsEnvoiFinInterruption[]; +extern GestionnaireRequeteInterruption tableGestionnairesRequeteInterruption[]; + +void gestionnaireRequeteInterruptionVide() { +} + +void initIrq (void** etat) { + desactiverInterruptions(); + + *etat = etatIrq; + + etatIrq->tableFonctionsEnvoiFinInterruption = tableFonctionsEnvoiFinInterruption; + etatIrq->tableGestionnairesRequeteInterruption = tableGestionnairesRequeteInterruption; + + etatIrq->adresseVecteurInterruptionMaitre = 32; + etatIrq->adresseVecteurInterruptionEsclave = 32 + 8; + + etatIrq->masqueMaitre = 0xff & (~(1 << 2)); /* connexion avec l'esclave activée */ + etatIrq->masqueEsclave = 0xff; + + etatIrq->ancienMasqueMaitre = inb(PORT_PIC_MAITRE_DONNEES); + etatIrq->ancienMasqueEsclave = inb(PORT_PIC_ESCLAVE_DONNEES); + + + etatIrq->ICW1_Maitre = (PicICW1){ + .ICW4_present = TRUE, + .single = PIC_ICW1_CASCADE, + .adi = PIC_ICW1_INTERVALLE_8, + .ltim = PIC_ICW1_EDGE_TRIGGERED_MODE, + .init = 1, + ._zero = 0 + }; + + etatIrq->ICW2_Maitre = (PicICW2){ + ._zero = 0, + .adresseVecteurInterruption_7_3 = etatIrq->adresseVecteurInterruptionMaitre >> 3 + }; + + etatIrq->ICW3_Maitre = ESCLAVE_CONNECTE_SUR_MAITRE_PATTE(2); + + etatIrq->ICW4_Maitre = (PicICW4){ + .microPM = PIC_ICW4_MODE_8086_8088, + .autoEOI = FALSE, + .tampon = PIC_ICW4_MODE_SANS_TAMPON, + .specialFullyNestedMode = FALSE + }; + + + etatIrq->ICW1_Esclave = etatIrq->ICW1_Maitre; + + etatIrq->ICW2_Esclave = (PicICW2){ + ._zero = 0, + .adresseVecteurInterruption_7_3 = etatIrq->adresseVecteurInterruptionEsclave >> 3 + }; + + etatIrq->ICW3_Esclave = (PicICW3_Esclave){ + .patteConnexionMaitre = 2, + ._zero = 0 + }; + + etatIrq->ICW4_Esclave = etatIrq->ICW4_Maitre; + + + outb (PORT_PIC_MAITRE_COMMANDE, etatIrq->ICW1_Maitre); + outb (PORT_PIC_MAITRE_DONNEES, etatIrq->ICW2_Maitre); + outb (PORT_PIC_MAITRE_DONNEES, etatIrq->ICW3_Maitre); + outb (PORT_PIC_MAITRE_DONNEES, etatIrq->ICW4_Maitre); + outb (PORT_PIC_MAITRE_DONNEES, etatIrq->masqueMaitre); + + outb (PORT_PIC_ESCLAVE_COMMANDE, etatIrq->ICW1_Esclave); + outb (PORT_PIC_ESCLAVE_DONNEES, etatIrq->ICW2_Esclave); + outb (PORT_PIC_ESCLAVE_DONNEES, etatIrq->ICW3_Esclave); + outb (PORT_PIC_ESCLAVE_DONNEES, etatIrq->ICW4_Esclave); + outb (PORT_PIC_ESCLAVE_DONNEES, etatIrq->masqueEsclave); + + int i; + for (i = 0; i < 8; i++) { + definirGestionnaireInterruption(etatIrq->adresseVecteurInterruptionMaitre + i, tableFonctionsEnvoiFinInterruption[i]); + } + + for (i = 0; i < 8; i++) + definirGestionnaireInterruption(etatIrq->adresseVecteurInterruptionEsclave + i, tableFonctionsEnvoiFinInterruption[i+8]); + activerInterruptions(); +} + +void deinitIrq (void** etat) { + *etat = NULL; +} + +void definirGestionnaireRequeteInterruption(int ligne, GestionnaireRequeteInterruption gestionnaire) { + desactiverInterruptions(); + + etatIrq->tableGestionnairesRequeteInterruption[ligne] = gestionnaire; + + activerInterruptions(); +} + +void activerLigneRequeteInterruption(int ligne) { + if (ligne < 8) { + activerInterruption(etatIrq->adresseVecteurInterruptionMaitre + ligne); + etatIrq->masqueMaitre &= ~(1 << (ligne & 0x07)); + outb (PORT_PIC_MAITRE_DONNEES, etatIrq->masqueMaitre); + } else { + activerInterruption(etatIrq->adresseVecteurInterruptionEsclave + ligne - 8); + etatIrq->masqueEsclave &= ~(1 << (ligne & 0x07)); + outb (PORT_PIC_ESCLAVE_DONNEES, etatIrq->masqueEsclave); + } +} + +void desactiverLigneRequeteInterruption(int ligne) { + if (ligne < 8) { + desactiverInterruption(etatIrq->adresseVecteurInterruptionMaitre + ligne); + etatIrq->masqueMaitre |= (1 << (ligne & 0x07)); + outb (PORT_PIC_MAITRE_DONNEES, etatIrq->masqueMaitre); + } else { + desactiverInterruption(etatIrq->adresseVecteurInterruptionEsclave + ligne - 8); + etatIrq->masqueEsclave |= (1 << (ligne & 0x07)); + outb (PORT_PIC_ESCLAVE_DONNEES, etatIrq->masqueEsclave); + } +} diff --git a/src/modules/pc/kbc/kbc.c b/src/modules/pc/kbc/kbc.c new file mode 100644 index 0000000..23c30a8 --- /dev/null +++ b/src/modules/pc/kbc/kbc.c @@ -0,0 +1,73 @@ +#include +#include +#include +#include +#include +#include + +MODULE(Kbc); + +DEPENDANCE_MODULE(Kbc, Irq); +DEPENDANCE_MODULE(Kbc, Io); +DEPENDANCE_MODULE(Kbc, Console); + +void gestionnaireRequeteInterruptionKbc() { + etatKbc->gestionnaireClavier(inb(PORT_KBC_SCANCODE)); +} + +void gestionnaireClavierVide(uint8 scancode) { + scancode = scancode; +} + +void activerClavier() { + uint8 ppi = inb(PORT_KBC_PPI); + ppi = ppi & ~0x80; + outb(PORT_KBC_PPI, ppi); +} + +void activerSouris() { + +} + +void desactiverClavier() { + uint8 ppi = inb(PORT_KBC_PPI); + ppi = ppi | 0x80; + outb(PORT_KBC_PPI, ppi); +} + +void attenteKbc() { + /* Attendre un tampon d'entrée vide */ + while ((inb(PORT_KBC_COMMANDE) & 2) == 2); +} + +void attenteLectureKbc() { + /* Attendre un tampon d'entrée plein */ + while ((inb(PORT_KBC_COMMANDE) & 2) != 2); +} + +void resetCpu() { + attenteKbc(); + outb(PORT_KBC_COMMANDE, KBC_DEMMANDE_ECRITURE_CLAVIER); + + attenteKbc(); + outb(PORT_KBC_SCANCODE, KBC_RESET_CPU); +} + +void definirGestionnaireClavier(GestionnaireClavier gestionnaireClavier) { + etatKbc->gestionnaireClavier = gestionnaireClavier; +} + +void initKbc (void** etat) { + *etat = etatKbc; + + etatKbc->gestionnaireClavier = gestionnaireClavierVide; + + definirGestionnaireRequeteInterruption(LIGNE_IRQ_CLAVIER, gestionnaireRequeteInterruptionKbc); + activerLigneRequeteInterruption(LIGNE_IRQ_CLAVIER); + + activerClavier(); +} + +void deinitKbc (void** etat) { + *etat = NULL; +} diff --git a/src/modules/pc/pit/pit.c b/src/modules/pc/pit/pit.c new file mode 100644 index 0000000..281aa02 --- /dev/null +++ b/src/modules/pc/pit/pit.c @@ -0,0 +1,110 @@ +#include +#include +#include +#include +#include +#include + +#include /* DEBUG */ + +MODULE(Pit); + +DEPENDANCE_MODULE(Pit, Irq); +DEPENDANCE_MODULE(Pit, Io); +DEPENDANCE_MODULE(Pit, Math); +DEPENDANCE_MODULE(Pit, Console); /* DEBUG */ + +void gestionnaireRequeteInterruptionPit() { + etatPit->gestionnairePit(); +} + +void gestionnairePitVide() { +} + +void definirCompteurCanal(uint16 compteur, PitCanal canal) { + uint8 haut = (compteur >> 8) & 0xff; + uint8 bas = compteur & 0xff; + int port = PORT_PIT_CANAUX + canal; + /* TODO : lorsqu'on fait les outb avec un entier dans une variable + * pour le port, il y a un problème. */ + port = port; + + if ((etatPit->modeAcces == PIT_OCTET_BAS) || + (etatPit->modeAcces == PIT_OCTETS_HAUT_BAS)) + outb(PORT_PIT_CANAUX, bas); + + if ((etatPit->modeAcces == PIT_OCTET_HAUT) || + (etatPit->modeAcces == PIT_OCTETS_HAUT_BAS)) + outb(PORT_PIT_CANAUX, haut); +} + +void definirModeCanal(PitModeCanal mode, PitCanal canal) { + PitCommandeMode commande; + commande.bcd = FALSE; + commande.mode = mode; + commande.acces = etatPit->modeAcces; + commande.canal = canal; + + outb(PORT_PIT_COMMANDE, commande); +} + +/* freq en 1/1000 hz [~18000..FREQUENCE_PIT_KHZ] */ +uint32 definirFrequenceCanal(uint32 freq, PitCanal canal) { + uint32 diviseur = FREQUENCE_PIT_MILI_HZ / freq; + + if (diviseur > 65536) { + return 0; + } else if (diviseur == 65536) { + definirCompteurCanal(0, canal); + return FREQUENCE_PIT_MILI_HZ / 65536; + } else if (diviseur == 0) { + definirCompteurCanal(1, canal); + return FREQUENCE_PIT_MILI_HZ; + } else { + definirCompteurCanal(diviseur, canal); + return FREQUENCE_PIT_MILI_HZ / diviseur; + } +} + +/* delai en ns [1..10^8] */ +uint32 definirDelaiCanal(uint32 delai, PitCanal canal) { + //afficherEntierVirguleEnDecimal(delai, 9); + uint64 fd = (uint64)FREQUENCE_PIT_MILI_HZ * (uint64)delai; + Div64 r = div64 (fd, 1000000000000); + uint64 diviseur = r.quotient; + + if (diviseur >= 65536) { + definirCompteurCanal(0, canal); + diviseur = 65536; + } else if (diviseur == 0) { + definirCompteurCanal(1, canal); + diviseur = 1; + } else { + definirCompteurCanal(diviseur, canal); + } + + Div64 delaiEffectif = div64(diviseur * 1000000000000L, FREQUENCE_PIT_MILI_HZ); + + return (uint32)delaiEffectif.quotient; +} + +void definirGestionnairePit(GestionnairePit gestionnairePit) { + etatPit->gestionnairePit = gestionnairePit; +} + +void initPit (void** etat) { + *etat = etatPit; + + etatPit->gestionnairePit = gestionnairePitVide; + + definirGestionnaireRequeteInterruption(LIGNE_IRQ_PIT, gestionnaireRequeteInterruptionPit); + activerLigneRequeteInterruption(LIGNE_IRQ_PIT); + + etatPit->modeAcces = PIT_OCTETS_HAUT_BAS; + definirModeCanal(PIT_MODE_GENERATEUR_FREQUENCE, 0); + definirCompteurCanal(0, 0); +} + +void deinitPit (void** etat) { + *etat = NULL; +} diff --git a/src/modules/pc/sourisPS2/sourisPS2.c b/src/modules/pc/sourisPS2/sourisPS2.c new file mode 100644 index 0000000..a5872c8 --- /dev/null +++ b/src/modules/pc/sourisPS2/sourisPS2.c @@ -0,0 +1,265 @@ +#include +#include +#include +#include +#include +#include +#include +#include /* DEBUG */ +#include /* DEBUG */ +#include /* DEBUG */ +#include /* DEBUG */ + +MODULE(SourisPS2); + +DEPENDANCE_MODULE(SourisPS2, Kbc); +DEPENDANCE_MODULE(SourisPS2, Clavier); /* DEBUG */ +DEPENDANCE_MODULE(SourisPS2, VesaGraphique); /* DEBUG */ + + +void envoyerCommandeSourisPS2(uint8 commande) { + /* TODO : ne pas partir dans une attente infinie en cas de bug matériel */ + attenteKbc(); + outb(PORT_KBC_COMMANDE, KBC_DEMMANDE_ECRITURE_SOURIS); + + attenteKbc(); + outb(PORT_KBC_COMMANDE_SOURIS, commande); +} + +void gestionnairePaquetSourisPS2(uint8 val) { + etatSourisPS2->paquets[etatSourisPS2->paquet++] = val; + + if (((etatSourisPS2->mouseID == 0) && (etatSourisPS2->paquet == 3)) || (etatSourisPS2->paquet >= 4)) { + etatSourisPS2->paquet = 0; + etatSourisPS2->etatGestionnaireSourisPS2 = ETAT_GESTIONNAIRE_SOURIS_PS2_ATTENTE; + + /* DEBUG */ + //afficherChaineZ(" p"); + //afficherEntierEnHexa(*(uint32*)(void*)&(etatSourisPS2->paquets)); + + PaquetSourisPS2_1 p1 = CAST_INT_TO_STRUCT(etatSourisPS2->paquets[0], PaquetSourisPS2_1); + int xsgn = p1.xNegatif ? 0xffffff00 : 0; + int ysgn = p1.yNegatif ? 0xffffff00 : 0; + + if (p1.boutonGauche) + etatSourisPS2->couleur = 0xffffffff; + else if (p1.boutonDroite) + etatSourisPS2->couleur = 0; + else if (p1.boutonMilieu) + etatSourisPS2->couleur = 0xff8800ff; + + etatSourisPS2->curseur_x += etatSourisPS2->paquets[1] | xsgn; + etatSourisPS2->curseur_y -= etatSourisPS2->paquets[2] | ysgn; + etatSourisPS2->curseur_x = clip(etatSourisPS2->curseur_x, 0, 1023); + etatSourisPS2->curseur_y = clip(etatSourisPS2->curseur_y, 0, 767); + // setPixel32(etatSourisPS2->curseur_x, etatSourisPS2->curseur_y, etatSourisPS2->couleur); + policeAfficherCaractereCouleurPosition(0, etatSourisPS2->couleur, 0x00000000, etatSourisPS2->curseur_x, etatSourisPS2->curseur_y); + } +} + +void gestionnaireDialogueSourisPS2(uint8 val) { + // afficherChaineZ(" gestionnaireDialogueSourisPS2"); + // afficherChaineZ(" r"); + // afficherEntierEnHexa(val); /* DEBUG */ + // afficherChaineZ(" "); + // afficherEntierEnDecimal(etatSourisPS2->etapeDialogue); + // afficherChaineZ(" "); + // afficherEntierEnDecimal(etatSourisPS2->dialogue.longueur); + // afficherChaineZ(" "); + + + DialogueSourisPS2 dialogue = etatSourisPS2->dialogue; + int etape; + uint8 action, valeur; + uint8* parametre = dialogue.parametre; + + + boucle: + etape = etatSourisPS2->etapeDialogue++; + action = dialogue.sequence[etape * 2]; + valeur = dialogue.sequence[etape * 2 + 1]; + + if (etape >= dialogue.longueur) + goto fin; + + if (action == RECEVOIR) { + if (val != valeur) { + etatSourisPS2->etatGestionnaireSourisPS2 = ETAT_GESTIONNAIRE_SOURIS_PS2_ATTENTE; + dialogue.rappel(TRUE); + return; + } + } else if (action == RECEVOIR_V) { + *parametre = val; + } else if (action == RECEVOIR_OU_PAS) { + if (val != valeur) + goto boucle; + } + /* Fin boucle */ + + etape = etatSourisPS2->etapeDialogue++; + while (etape < dialogue.longueur) { + action = dialogue.sequence[etape * 2]; + valeur = dialogue.sequence[etape * 2 + 1]; + + if (action == ENVOYER) { + /* DEBUG */ + // afficherChaineZ(" s"); + // afficherEntierEnHexa(valeur); + envoyerCommandeSourisPS2(valeur); + } else if (action == ENVOYER_V) { + /* DEBUG */ + // afficherChaineZ(" s"); + // afficherEntierEnHexa(*parametre); + envoyerCommandeSourisPS2(*parametre); + } else if (action == COMMANDE) { + attenteKbc(); + outb(PORT_KBC_COMMANDE, valeur); + } else { + break; + } + etape = etatSourisPS2->etapeDialogue++; + } + + fin: + if (etape >= dialogue.longueur) { + etatSourisPS2->etatGestionnaireSourisPS2 = ETAT_GESTIONNAIRE_SOURIS_PS2_ATTENTE; + dialogue.rappel(FALSE); + } +} + +bool dialoguer(const uint8* sequence, int longueur, uint8* parametre, FonctionRappelSourisPS2 rappel) { + // afficherChaineZ(" dialoguer"); + desactiverInterruptions(); + + longueur /= 2; + + if (etatSourisPS2->etatGestionnaireSourisPS2 != ETAT_GESTIONNAIRE_SOURIS_PS2_ATTENTE) { + activerInterruptions(); + return FALSE; + } + + uint8 action, valeur; + int etape; + for (etape = 0; etape < longueur; etape++) { + action = sequence[etape * 2]; + valeur = sequence[etape * 2 + 1]; + + if (action == ENVOYER) { + /* DEBUG */ + // afficherChaineZ(" s"); + // afficherEntierEnHexa(valeur); + envoyerCommandeSourisPS2(valeur); +// afficherChaineZ(" "); afficherEntierEnDecimal(etape); afficherChaineZ(" "); afficherEntierEnDecimal(longueur); afficherChaineZ(" "); + } else if (action == ENVOYER_V) { + /* DEBUG */ + // afficherChaineZ(" s"); + // afficherEntierEnHexa(*parametre); + envoyerCommandeSourisPS2(*parametre); +// afficherChaineZ(" "); afficherEntierEnDecimal(etape); afficherChaineZ(" "); afficherEntierEnDecimal(longueur); afficherChaineZ(" "); + } else + break; + } + + if (etape >= longueur) { + rappel(FALSE); + } else { + etatSourisPS2->dialogue.sequence = sequence; + etatSourisPS2->dialogue.longueur = longueur; + etatSourisPS2->dialogue.parametre = parametre; + etatSourisPS2->dialogue.rappel = rappel; + etatSourisPS2->etapeDialogue = etape; + etatSourisPS2->etatGestionnaireSourisPS2 = ETAT_GESTIONNAIRE_SOURIS_PS2_DIALOGUE; + } + + activerInterruptions(); + return TRUE; +} + +void gestionnaireSourisPS2() { + // afficherChaineZ(" gs "); + uint8 val; + val = inb(PORT_KBC_SOURIS); + // afficherEntierEnHexa(val); + + switch (etatSourisPS2->etatGestionnaireSourisPS2) { + case ETAT_GESTIONNAIRE_SOURIS_PS2_ATTENTE : + case ETAT_GESTIONNAIRE_SOURIS_PS2_PAQUET : + gestionnairePaquetSourisPS2(val); + break; + case ETAT_GESTIONNAIRE_SOURIS_PS2_DIALOGUE : + gestionnaireDialogueSourisPS2(val); + break; + } +} + +void fonctionRappelVide(bool erreur) { + erreur = erreur; + // afficherChaineZ(" rappel "); /* DEBUG */ + // afficherEntierEnDecimal(erreur); +} + + +void definirResolution(uint8 res) { + etatSourisPS2->resolution = res; + dialoguer(DialogueDefinirResolution, LONGUEUR(DialogueDefinirResolution), &(etatSourisPS2->resolution), fonctionRappelVide); +} + +void demanderPaquet() { + // afficherChaineZ(" demanderPaquet"); /* DEBUG */ + dialoguer(DialogueDemanderPaquet, LONGUEUR(DialogueDemanderPaquet), NULL, fonctionRappelVide); +} + +void autoPaquets() { + // afficherChaineZ(" autoPaquets"); /* DEBUG */ + dialoguer(DialogueAutoPaquets, LONGUEUR(DialogueAutoPaquets), NULL, fonctionRappelVide); +} + +uint8 obtenirCompaqStatusByte() { + // afficherChaineZ(" getcsb"); /* DEBUG */ + + attenteKbc(); + outb(PORT_KBC_COMMANDE, KBC_DEMMANDE_LECTURE_COMPAQ_STATUS_BYTE); + + // attenteLectureKbc(); + return inb(PORT_KBC_DONNEES); +} + +void definirCompaqStatusByte(uint8 csb) { + attenteKbc(); + outb(PORT_KBC_COMMANDE, KBC_DEMMANDE_ECRITURE_COMPAQ_STATUS_BYTE); + + attenteKbc(); + outb(PORT_KBC_DONNEES, csb); +} + +void activerIrq12() { + definirGestionnaireRequeteInterruption(LIGNE_IRQ_SOURIS, gestionnaireSourisPS2); + activerLigneRequeteInterruption(LIGNE_IRQ_SOURIS); + + uint8 csb = obtenirCompaqStatusByte(); + // afficherEntierEnHexa(csb); afficherChaineZ(" "); /* DEBUG */ + csb |= 2; // Activer Irq 12 + csb &= ~0x20; // Désactiver l'horloge souris + // afficherEntierEnHexa(csb); /* DEBUG */ + definirCompaqStatusByte(csb); +} + +void initSourisPS2 (void** etat) { + *etat = etatSourisPS2; + + etatSourisPS2->etapeDialogue = 0; + etatSourisPS2->etatGestionnaireSourisPS2 = ETAT_GESTIONNAIRE_SOURIS_PS2_ATTENTE; + + etatSourisPS2->curseur_x = 1024/2; + etatSourisPS2->curseur_y = 768/2; + + activerIrq12(); + + autoPaquets(); + + etatSourisPS2->couleur = 0xffffffff; /* DEBUG */ +} + +void deinitSourisPS2 (void** etat) { + *etat = NULL; +} diff --git a/src/modules/pc/vesaGraphique/vesaGraphique.c b/src/modules/pc/vesaGraphique/vesaGraphique.c new file mode 100644 index 0000000..bc8ced9 --- /dev/null +++ b/src/modules/pc/vesaGraphique/vesaGraphique.c @@ -0,0 +1,109 @@ +#include +#include +#include +#include +#include +#include +#include + +MODULE(VesaGraphique); + +DEPENDANCE_MODULE(VesaGraphique, Multiboot); +DEPENDANCE_MODULE(VesaGraphique, Console); +DEPENDANCE_MODULE(VesaGraphique, Police); + +extern EtatMultiboot* etatMultiboot; + + +void setPixel32 (uint32 x, uint32 y, uint32 couleur) { + etatVesaGraphique->memoireVideo[x + 1024*y].rvb = couleur; +} + +void ligne (uint32 x1, uint32 y1, uint32 x2, uint32 y2, uint32 couleur) { + uint32 mdx2, mdy2, dx2, dy2; + int32 err, dx, dy; + + setPixel32 (x2, y2, couleur); + + dx = x2 - x1; + dy = y2 - y1; + + if (abs(dx) > abs(dy)) { // y++ ou y-- ou y=y à chaque tour + err = - abs(dx); + mdx2 = 2 * err; + dy2 = 2 * abs(dy); + + for (; x1 != x2; x1 += sign(dx)) { + setPixel32 (x1, y1, couleur); + err += dy2; + if (err >= 0) { + err += mdx2; + y1 += sign(dy); + } + } + } else { // x++ ou x-- ou x=x à chaque tour + err = - abs(dy); + mdy2 = 2 * err; + dx2 = 2 * abs(dx); + + for (; y1 != y2; y1 += sign(dy)) { + setPixel32 (x1, y1, couleur); + err += dx2; + if (err >= 0) { + err += mdy2; + x1 += sign(dx); + } + } + } +} + +void rectanglePlein (uint32 x1, uint32 y1, uint32 x2, uint32 y2, uint32 couleur) { + uint32 y; + for (; x1 <= x2; x1++) + for (y = y1; y <= y2; y++) + setPixel32(x1, y, couleur); +} + +void rectangleContour (uint32 x1, uint32 y1, uint32 x2, uint32 y2, uint32 couleur) { + uint32 x; + for (x = x1; x <= x2; x++) { + setPixel32(x, y1, couleur); + setPixel32(x, y2, couleur); + } + + for (; y1 <= y2; y1++) { + setPixel32(x1, y1, couleur); + setPixel32(x2, y1, couleur); + } +} + + +void vesaGraphiqueAfficherCaractereCouleurPosition(char caractere, uint32 couleurAv, uint32 couleurAr, uint32 x, uint32 y) { + policeAfficherCaractereCouleurPosition(caractere, couleurAv, couleurAr, x * 8, y * 15); + caractere = caractere; + couleurAv = couleurAv; + couleurAr = couleurAr; + x = x; + y = y; +} + + +void initVesaGraphique (void** etat) { + *etat = etatVesaGraphique; + + /* Passage en mode graphique. Actuellement effectué par grub (avec le patch pour VBE) */ + + etatVesaGraphique->memoireVideo = etatMultiboot->InfoMultiboot->vbeModeInfo->linearAddress; + + etatVesaGraphique->console.x = 0; + etatVesaGraphique->console.y = 0; + etatVesaGraphique->console.largeur = 1024 / 8; + etatVesaGraphique->console.hauteur = 768 / 15; + etatVesaGraphique->console.fonctionAffichage = vesaGraphiqueAfficherCaractereCouleurPosition; + + definirConsoleActive(&etatVesaGraphique->console); +} + +void deinitVesaGraphique (void** etat) { + *etat = NULL; +} diff --git a/src/modules/pc/vgaTexte/vgaTexte.c b/src/modules/pc/vgaTexte/vgaTexte.c new file mode 100644 index 0000000..54f4dd8 --- /dev/null +++ b/src/modules/pc/vgaTexte/vgaTexte.c @@ -0,0 +1,52 @@ +#include +#include +#include +#include + +MODULE(VgaTexte); + +DEPENDANCE_MODULE(VgaTexte, Console); + +CouleurVgaTexte CouleursVersCouleurVgaTexte(Couleur couleurAv, Couleur couleurAr) { + CouleurComposantes composantesAv = CAST_INT_TO_STRUCT(couleurAv, CouleurComposantes); + CouleurComposantes composantesAr = CAST_INT_TO_STRUCT(couleurAr, CouleurComposantes); + + CouleurVgaTexte couleurVgaTexte; + + couleurVgaTexte.avClair = ((composantesAv.rouge + composantesAv.vert + composantesAv.bleu) > 3*128); + couleurVgaTexte.avRouge = (composantesAv.rouge > 128); + couleurVgaTexte.avVert = (composantesAv.vert > 128); + couleurVgaTexte.avBleu = (composantesAv.bleu > 128); + + couleurVgaTexte._reserve = 0; + couleurVgaTexte.arRouge = (composantesAr.rouge > 128); + couleurVgaTexte.arVert = (composantesAr.vert > 128); + couleurVgaTexte.arBleu = (composantesAr.bleu > 128); + + return couleurVgaTexte; +} + +void vgaTexteAfficherCaractereCouleurPosition(char caractere, uint32 couleurAv, uint32 couleurAr, uint32 x, uint32 y) { + etatVgaTexte->memoireVideo[x + y * etatVgaTexte->console.largeur] = (CaractereVgaTexte) { + .caractere = caractere, + .couleur = CouleursVersCouleurVgaTexte(couleurAv, couleurAr) + }; +} + +void initVgaTexte (void** etat) { + *etat = etatVgaTexte; + + etatVgaTexte->memoireVideo = (CaractereVgaTexte*)0xb8000; + + etatVgaTexte->console.x = 0; + etatVgaTexte->console.y = 0; + etatVgaTexte->console.largeur = 80; + etatVgaTexte->console.hauteur = 25; + etatVgaTexte->console.fonctionAffichage = vgaTexteAfficherCaractereCouleurPosition; + + // definirConsoleActive(&etatVgaTexte->console); +} + +void deinitVgaTexte (void** etat) { + *etat = NULL; +} diff --git a/src/modules/recherche/dichotomique.c b/src/modules/recherche/dichotomique.c new file mode 100644 index 0000000..9e6a66b --- /dev/null +++ b/src/modules/recherche/dichotomique.c @@ -0,0 +1,62 @@ +#include +#include +#include +#include + +MODULE(RechercheDichotomique); + +void* testGet(void* t, uint32 index) { + return ((int*)t) + index; +} + +int testCmp(void* a, void* b) { + int aa = *((int*)a); + int bb = *((int*)b); + return (aa == bb) ? 0 : ((aa < bb) ? -1 : 1); +} + +void initRechercheDichotomique(void** etat) { + *etat = NULL; +} + +void deinitRechercheDichotomique(void** etat) { + *etat = NULL; +} + +int rechercheDichotomiquePremier(void* e, void* t, int taille, AccesseurIndex get, ComparaisonStricte comparer) { + int i = 0; + int j = taille - 1; + int m; + + if (comparer(get(t, i), e) == 0) + return i; + + while (i + 1 < j) { + m = (i + j) / 2; + if (comparer(get(t, m), e) < 0) + i = m; + else + j = m; + } + + return (comparer(get(t, j), e) == 0) ? j : -1; +} + +int rechercheDichotomiqueDernier(void* e, void* t, int taille, AccesseurIndex get, ComparaisonStricte comparer) { + int i = 0; + int j = taille - 1; + int m; + + if (comparer(get(t, j), e) == 0) + return j; + + while (i + 1 < j) { + m = (i + j) / 2; + if (comparer(get(t, m), e) > 0) + j = m; + else + i = m; + } + + return (comparer(get(t, i), e) == 0) ? i : -1; +} diff --git a/src/modules/stockage/ata/ata.c b/src/modules/stockage/ata/ata.c new file mode 100644 index 0000000..93765b2 --- /dev/null +++ b/src/modules/stockage/ata/ata.c @@ -0,0 +1,18 @@ +#include +#include +#include + +#include /* DEBUG */ + +MODULE(Ata); + +/* DEPENDANCE_MODULE(Ata, ...); */ +DEPENDANCE_MODULE(Ata, Console); /* DEBUG */ + +void initAta (void** etat) { + *etat = etatAta; +} + +void deinitAta (void** etat) { + *etat = NULL; +} diff --git a/src/modules/temps/temps/temps.c b/src/modules/temps/temps/temps.c new file mode 100644 index 0000000..459cb1d --- /dev/null +++ b/src/modules/temps/temps/temps.c @@ -0,0 +1,49 @@ +#include +#include +#include +#include + +#include /* DEBUG */ + +MODULE(Temps); + +DEPENDANCE_MODULE(Temps, Pit); +DEPENDANCE_MODULE(Temps, Console); /* DEBUG */ + +void gestionnairePit() { + etatTemps->nanosec += etatTemps->increments; + etatTemps->debug++; + if (etatTemps->nanosec >= 1000000000) { + etatTemps->nanosec -= 1000000000; + etatTemps->sec++; + + Position p = consolePosition(118, 0); + afficherEntierEnHexa(etatTemps->sec); + consolePosition(p.x, p.y); + } +} + +void initTemps (void** etat) { + *etat = etatTemps; + + etatTemps->nanosec = 0; + etatTemps->sec = 0; + etatTemps->delta = 0; + etatTemps->etapesDelta = 1; + etatTemps->increments = definirDelaiCanal(1000000000, 0); + + etatTemps->listeEcheancesDate = NULL; + etatTemps->listeEcheancesDelai = NULL; + + definirGestionnairePit(gestionnairePit); + etatTemps->sec = 0; // TODO : Récupérer depuis la RTC + etatTemps->nanosec = 0; // TODO : Récupérer depuis la RTC + + Position p = consolePosition(118, 0); + afficherEntierEnHexa(0); + consolePosition(p.x, p.y); +} + +void deinitTemps (void** etat) { + *etat = NULL; +} diff --git a/src/modules/tri/tas/tas.c b/src/modules/tri/tas/tas.c new file mode 100644 index 0000000..7bded31 --- /dev/null +++ b/src/modules/tri/tas/tas.c @@ -0,0 +1,63 @@ +#include +#include +#include + +MODULE(TriParTas); + + +void initTriParTas(void** etat) { + *etat = NULL; +} + +void deinitTriParTas(void** etat) { + *etat = NULL; +} + +void percoler(int racine, void* t, int taille, AccesseurIndex get, AccesseurEchanger echanger, Comparaison comparer) { + int gauche = 2 * racine + 1; + int droite = 2 * racine + 2; + + void* valracine; + void* valgauche; + + while (droite < taille) { + valracine = get(t, racine); + valgauche = get(t, gauche); + + if (comparer(valracine, valgauche) < 0) { + if (comparer(valgauche, get(t, droite)) < 0) { + echanger(t, racine, droite); + racine = droite; + } + else { + echanger(t, racine, gauche); + racine = gauche; + } + } else { + if (comparer(valracine, get(t, droite)) < 0) { + echanger(t, racine, droite); + racine = droite; + } else { + return; + } + } + + gauche = 2 * racine + 1; + droite = 2 * racine + 2; + } + + if ((gauche < taille) && (comparer(get(t, racine), get(t, gauche)) < 0)) + echanger(t, racine, gauche); +} + +void triParTas(void* t, int taille, AccesseurIndex get, AccesseurEchanger echanger, Comparaison comparer) { + int i; + for (i = (taille / 2) - 1; i >= 0; i--) + percoler(i, t, taille, get, echanger, comparer); + + for (i = taille - 1; i > 0; i--) { + echanger(t, i, 0); + taille--; + percoler(0, t, taille, get, echanger, comparer); + } +} diff --git a/src/scripts/creerImage.lds b/src/scripts/creerImage.lds new file mode 100644 index 0000000..81368e7 --- /dev/null +++ b/src/scripts/creerImage.lds @@ -0,0 +1,43 @@ +ENTRY (_start) + +SECTIONS { + /* le format ELF utilise les 0x80 premiers octets. Si on met 0x100000, + * il remplit le début du fichier par des zéros jusqu'à 4ko, pour être + * aligné. Ici, 0x100080 nous permet d'être juste après l'en-tête ELF, + * et de gaspiller moins de place */ + . = 0x100080 ; + + .multiboot . : { + *(.multiboot*) + /* On force l'allocation au début du fichier : */ + LONG (0); + } + + .text . : { + *(.text*) + } + + .data . : { + *(.data*) + } + + .rodata . : { + *(.rodata*) + } + + .modules : { + __listeModules = .; + *(.modules*); + __finListeModules = . ; + } + + .dependancesModules . : { + __listeDependancesModules = .; + *(.dependancesModules*); + __finListeDependancesModules = . ; + } + + .bss . : { + *(.bss*); + } +} diff --git a/src/scripts/creerModule.sh b/src/scripts/creerModule.sh new file mode 100644 index 0000000..c76e2e8 --- /dev/null +++ b/src/scripts/creerModule.sh @@ -0,0 +1,35 @@ +#!/bin/sh + +if [ "$1" == "--help" ]; then + echo "$0 catégorie/nomModule" + exit +fi + +n="$(basename "$1" | dd bs=1 count=1 2>/dev/null)" +omMod="$(basename "$1" | dd bs=1 skip=1 2>/dev/null)" + +N="$(echo "$n" | tr '[:lower:]' '[:upper:]')" +OMMOD="$(echo "$omMod" | sed -e 's/[A-Z]/_\0/g' | tr '[:lower:]' '[:upper:]')" + +nomMod="$n$omMod" +NomMod="$N$omMod" +NOMMOD="$N$OMMOD" + +NOMCAT="$(echo "$1" | sed -e 's/[A-Z]/_\0/g; s|/|_|g' | tr '[:lower:]' '[:upper:]')" + +destc="src/modules/$1/$nomMod.c" +desth="src/inclusions/$1/$nomMod.h" + +[ -e "$destc" ] && echo "$destc existe !" && exit +[ -e "$desth" ] && echo "$desth existe !" && exit + +mkdir -p "$(dirname "$destc")" +mkdir -p "$(dirname "$desth")" + +echo --------------- "$destc" --------------- +cat src/modules/modeleModule.c | sed -e "s|modeleModule|$1/$nomMod|g; s/ModeleModule/$NomMod/g; s/MODELE_MODULE/${NOMCAT}_$NOMMOD/g" | tee -a "$destc" +echo +echo --------------- "$desth" --------------- +cat src/inclusions/modeleModule.h | sed -e "s|modeleModule|$1/$nomMod|g; s/ModeleModule/$NomMod/g; s/MODELE_MODULE/${NOMCAT}_$NOMMOD/g" | tee -a "$desth" + +geany "$destc" "$desth" & diff --git a/src/scripts/creerPolice.sh b/src/scripts/creerPolice.sh new file mode 100755 index 0000000..6ec92c5 --- /dev/null +++ b/src/scripts/creerPolice.sh @@ -0,0 +1,6 @@ +#!/bin/sh + +( + cd "$(dirname "$1")" + montage $(sort -g "$(basename "$1")" | cut -d ' ' -f 2-) -tile 1x -geometry +0+0 pbm:- | tail -n +3 +) > "$2" diff --git a/src/scripts/liste-chemins.lst b/src/scripts/liste-chemins.lst new file mode 100644 index 0000000..002731f --- /dev/null +++ b/src/scripts/liste-chemins.lst @@ -0,0 +1,4 @@ +boot/gruntnetwork.elf=./dist/noyau.elf +boot/grub/stage2_eltorito=./src/demarrage/grub/stage2_eltorito_vbe +boot/grub/menu.lst=./src/demarrage/grub/menu.lst +donnees/police.fnt=./dist/police.fnt