feat: mode 320x200 chained fonctionnel
This commit is contained in:
parent
605953aa3b
commit
aac62edd51
|
@ -129,7 +129,7 @@
|
|||
asm volatile ("cld;rep movsw"::"S" (src), "D" (dst), "c" (count));
|
||||
|
||||
#define movsd(src,dst,count) \
|
||||
asm volatile ("cld;rep movsd"::"S" (src), "D" (dst), "c" (count));
|
||||
asm volatile ("cld;rep movsl"::"S" (src), "D" (dst), "c" (count));
|
||||
|
||||
#define stosb(pattern,dst,count) \
|
||||
asm volatile ("cld;rep stosb"::"c" (count), "D" (dst), "a" (pattern));
|
||||
|
@ -138,13 +138,13 @@
|
|||
asm volatile ("cld;rep stosw"::"a" (pattern), "c" (count), "D" (dst));
|
||||
|
||||
#define stosd(pattern,dst,count) \
|
||||
asm volatile ("cld;rep stosd"::"a" (pattern), "c" (count), "D" (dst));
|
||||
asm volatile ("cld;rep stosl"::"a" (pattern), "c" (count), "D" (dst));
|
||||
|
||||
#define rol(addr) \
|
||||
asm volatile ("rolb %0":"=m" (addr):);
|
||||
asm volatile ("rolb $0x1,%0":"=m" (addr):);
|
||||
|
||||
#define ror(addr) \
|
||||
asm volatile ("rorb %0":"=m" (addr):);
|
||||
asm volatile ("rorb $0x1,%0":"=m" (addr):);
|
||||
/******************************************************************************/
|
||||
|
||||
#define outb(port,value) \
|
||||
|
|
|
@ -7,7 +7,10 @@
|
|||
|
||||
#include "stdarg.h"
|
||||
|
||||
#define maxdrivers 10
|
||||
#define MAXDRIVERS 10
|
||||
|
||||
#define FONT8X16 0
|
||||
#define FONT8X8 1
|
||||
|
||||
typedef struct videoinfos {
|
||||
u8 currentmode;
|
||||
|
@ -66,6 +69,7 @@ typedef struct capabilities {
|
|||
bool graphic;
|
||||
u8 depth;
|
||||
u8 refresh;
|
||||
u8 fonttype;
|
||||
} capabilities __attribute__ ((packed));
|
||||
|
||||
typedef struct console {
|
||||
|
@ -90,11 +94,14 @@ u8 getchar (u16 coordx, u16 coordy);
|
|||
u8 getattrib (u16 coordx, u16 coordy);
|
||||
void writepxl (u16 x, u16 y, u32 color);
|
||||
void line(u32 x1, u32 y1, u32 x2, u32 y2, u8 color);
|
||||
void changemode(u8 mode);
|
||||
|
||||
/* Fonctions de console */
|
||||
void changevc(u8 vc);
|
||||
void putchar(u8 thechar);
|
||||
void clearscreen(void);
|
||||
u16 getwidth(void);
|
||||
u16 getheight(void);
|
||||
|
||||
/* Fonctions de haut niveau */
|
||||
u32 print(u8* string);
|
||||
|
|
|
@ -113,9 +113,8 @@ void mouse(void)
|
|||
if (mousey >= 65535) {
|
||||
mousey = 65535;
|
||||
}
|
||||
videoinfos *vinfo=getvideo_info();
|
||||
u16 newx = (u32) mousex * vinfo->currentwidth / 65536;
|
||||
u16 newy = (u32) mousey * vinfo->currentheight / 65536;
|
||||
u16 newx = (u32) mousex * getwidth() / 65536;
|
||||
u16 newy = (u32) mousey * getheight() / 65536;
|
||||
|
||||
// Retrieve mouse button status from packet
|
||||
mousebut1 = mpacket[0] & 1;
|
||||
|
|
104
lib/vga.c
104
lib/vga.c
|
@ -94,18 +94,18 @@ u8 VGA_setvideo_mode(u8 mode)
|
|||
/* mode 256 couleurs */
|
||||
if (modes[index].sequencer.Sequencer_Memory_Mode_Register == 0x0E) {
|
||||
/* mode chainé (plus rapide mais limité en mémoire) */
|
||||
infos.currentpitch = (infos.currentwidth << 3);
|
||||
infos.currentpitch = infos.currentwidth;
|
||||
realsize=8;
|
||||
} else {
|
||||
/* mode non chainé */
|
||||
infos.currentpitch = (infos.currentwidth << 1);
|
||||
infos.currentpitch = infos.currentwidth >> 2;
|
||||
realsize=9;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
infos.pagesize = ((infos.currentheight * infos.currentpitch) << 3);
|
||||
infos.pagesize = infos.currentheight * infos.currentpitch;
|
||||
}
|
||||
else {
|
||||
infos.currentpitch= infos.currentwidth * 2;
|
||||
|
@ -189,7 +189,7 @@ u32 VGA_mem_to_video (void *src,u32 dst, u32 size, bool increment_src) {
|
|||
if (size%4 == 0)
|
||||
{
|
||||
u32 pattern = tmp + (tmp<<8) + (tmp<<16) + (tmp<<24);
|
||||
stosb(pattern,realdst,(size>>2));
|
||||
stosd(pattern,realdst,(size>>2));
|
||||
}
|
||||
else if (size%2 == 0)
|
||||
{
|
||||
|
@ -373,12 +373,14 @@ void VGA_wait_hretrace(void)
|
|||
|
||||
void VGA_cursor_enable(void)
|
||||
{
|
||||
u8 curs;
|
||||
/* active le curseur hardware */
|
||||
outb(CCRT, 10);
|
||||
curs = inb(CCRT + 1) & ~32;
|
||||
outb(CCRT + 1, curs);
|
||||
infos.isgraphic=true;
|
||||
if (!infos.isgraphic) {
|
||||
u8 curs;
|
||||
/* active le curseur hardware */
|
||||
outb(CCRT, 10);
|
||||
curs = inb(CCRT + 1) & ~32;
|
||||
outb(CCRT + 1, curs);
|
||||
infos.iscursorvisible=true;
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************/
|
||||
|
@ -386,12 +388,14 @@ void VGA_cursor_enable(void)
|
|||
|
||||
void VGA_cursor_disable(void)
|
||||
{
|
||||
u8 curs;
|
||||
/* Desactive le curseur hardware */
|
||||
outb(CCRT, 10);
|
||||
curs = inb(CCRT + 1) | 32;
|
||||
outb(CCRT + 1, curs);
|
||||
infos.isgraphic=false;
|
||||
if (!infos.isgraphic) {
|
||||
u8 curs;
|
||||
/* Desactive le curseur hardware */
|
||||
outb(CCRT, 10);
|
||||
curs = inb(CCRT + 1) | 32;
|
||||
outb(CCRT + 1, curs);
|
||||
infos.iscursorvisible=false;
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************/
|
||||
|
@ -415,17 +419,19 @@ void useplane(u8 plan)
|
|||
|
||||
void VGA_cursor_set(u16 x, u16 y)
|
||||
{
|
||||
u16 pos;
|
||||
if (splitY == 0)
|
||||
pos = (infos.currentshowedpage * infos.pagesize / 2 + x + y * infos.currentwidth);
|
||||
else
|
||||
pos = (x + y * infos.currentwidth);
|
||||
outb(CCRT, 0x0F);
|
||||
outb(CCRT + 1, (u8) (pos & 0x00FF));
|
||||
outb(CCRT, 0x0E);
|
||||
outb(CCRT + 1, (u8) ((pos & 0xFF00) >> 8));
|
||||
infos.currentcursorX=x;
|
||||
infos.currentcursorY=y;
|
||||
if (!infos.isgraphic) {
|
||||
u16 pos;
|
||||
if (splitY == 0)
|
||||
pos = (infos.currentshowedpage * infos.pagesize / 2 + x + y * infos.currentwidth);
|
||||
else
|
||||
pos = (x + y * infos.currentwidth);
|
||||
outb(CCRT, 0x0F);
|
||||
outb(CCRT + 1, (u8) (pos & 0x00FF));
|
||||
outb(CCRT, 0x0E);
|
||||
outb(CCRT + 1, (u8) ((pos & 0xFF00) >> 8));
|
||||
infos.currentcursorX=x;
|
||||
infos.currentcursorY=y;
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************/
|
||||
|
@ -486,12 +492,14 @@ u32 VGA_font_load(u8 * def, u8 size, u8 font)
|
|||
|
||||
void VGA_font1_set(u8 num)
|
||||
{
|
||||
num &= 0x07;
|
||||
outb(SEQUENCER, 3);
|
||||
outb(SEQUENCER + 1,
|
||||
(inb(SEQUENCER + 1) & 0xEC) | ((num & 0x03) +
|
||||
((num & 0x04) << 2)));
|
||||
infos.currentfont1=num;
|
||||
if (!infos.isgraphic) {
|
||||
num &= 0x07;
|
||||
outb(SEQUENCER, 3);
|
||||
outb(SEQUENCER + 1,
|
||||
(inb(SEQUENCER + 1) & 0xEC) | ((num & 0x03) +
|
||||
((num & 0x04) << 2)));
|
||||
infos.currentfont1=num;
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************/
|
||||
|
@ -499,12 +507,14 @@ void VGA_font1_set(u8 num)
|
|||
|
||||
void VGA_font2_set(u8 num)
|
||||
{
|
||||
num &= 0x07;
|
||||
outb(SEQUENCER, 3);
|
||||
outb(SEQUENCER + 1,
|
||||
(inb(SEQUENCER + 1) & 0xD3) | (((num & 0x03) << 2) +
|
||||
((num & 0x04) << 3)));
|
||||
infos.currentfont2=num;
|
||||
if (!infos.isgraphic) {
|
||||
num &= 0x07;
|
||||
outb(SEQUENCER, 3);
|
||||
outb(SEQUENCER + 1,
|
||||
(inb(SEQUENCER + 1) & 0xD3) | (((num & 0x03) << 2) +
|
||||
((num & 0x04) << 3)));
|
||||
infos.currentfont2=num;
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************/
|
||||
|
@ -512,9 +522,11 @@ void VGA_font2_set(u8 num)
|
|||
|
||||
void VGA_blink_enable(void)
|
||||
{
|
||||
outb(CCRT, 0x10);
|
||||
outb(CCRT + 1, (inb(SEQUENCER + 1) | 0x04));
|
||||
infos.isblinking=true;
|
||||
if (!infos.isgraphic) {
|
||||
outb(CCRT, 0x10);
|
||||
outb(CCRT + 1, (inb(SEQUENCER + 1) | 0x04));
|
||||
infos.isblinking=true;
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************/
|
||||
|
@ -522,9 +534,11 @@ void VGA_blink_enable(void)
|
|||
|
||||
void VGA_blink_disable(void)
|
||||
{
|
||||
outb(CCRT, 0x10);
|
||||
outb(CCRT + 1, (inb(SEQUENCER + 1) & ~0x04));
|
||||
infos.isblinking=false;
|
||||
if (!infos.isgraphic) {
|
||||
outb(CCRT, 0x10);
|
||||
outb(CCRT + 1, (inb(SEQUENCER + 1) & ~0x04));
|
||||
infos.isblinking=false;
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************/
|
||||
|
|
102
lib/video.c
102
lib/video.c
|
@ -8,10 +8,12 @@
|
|||
#include "VGA/8x8fnt.c"
|
||||
#include "VGA/8x16fnt.c"
|
||||
|
||||
static drivers registred[maxdrivers];
|
||||
static drivers registred[MAXDRIVERS];
|
||||
|
||||
static videoinfos *vinfo;
|
||||
|
||||
static width,height;
|
||||
|
||||
static console vc[8] = {
|
||||
{0x07, 0, 0, 0, 0, 0, 0, 0, true} ,
|
||||
{0x07, 0, 0, 0, 0, 0, 0, 0, true} ,
|
||||
|
@ -117,8 +119,8 @@ bool makeansi(u8 c)
|
|||
/* ESC[num1B -- bouge le curseur de num1 vers le bas */
|
||||
else if (c == 'B') {
|
||||
vc[usedvc].cursY += vc[usedvc].param1;
|
||||
if (vc[usedvc].cursY >= vinfo->currentheight - 1)
|
||||
vc[usedvc].cursY = vinfo->currentheight;
|
||||
if (vc[usedvc].cursY >= getheight() - 1)
|
||||
vc[usedvc].cursY = getheight() ;
|
||||
vc[usedvc].ansi = 0;
|
||||
cursor_set(vc[usedvc].cursX, vc[usedvc].cursY);
|
||||
return 1;
|
||||
|
@ -135,8 +137,8 @@ bool makeansi(u8 c)
|
|||
/* ESC[num1C -- bouge le curseur de num1 vers la droite */
|
||||
else if (c == 'C') {
|
||||
vc[usedvc].cursX += vc[usedvc].param1;
|
||||
if (vc[usedvc].cursX >= vinfo->currentwidth - 1)
|
||||
vc[usedvc].cursX = vinfo->currentwidth;
|
||||
if (vc[usedvc].cursX >= getwidth() - 1)
|
||||
vc[usedvc].cursX = getwidth();
|
||||
vc[usedvc].ansi = 0;
|
||||
cursor_set(vc[usedvc].cursX, vc[usedvc].cursY);
|
||||
return 1;
|
||||
|
@ -194,6 +196,8 @@ bool makeansi(u8 c)
|
|||
return 0; /* Ansi fini ;) */
|
||||
}
|
||||
|
||||
/*******************************************************************************/
|
||||
/* Change de mode video */
|
||||
void changemode(u8 mode)
|
||||
{
|
||||
setvideo_mode(mode);
|
||||
|
@ -201,9 +205,31 @@ void changemode(u8 mode)
|
|||
if (!vinfo->isgraphic) {
|
||||
font_load(font8x8, 8, 1);
|
||||
font_load(font8x16, 16, 0);
|
||||
width=vinfo->currentwidth;
|
||||
height=vinfo->currentheight;
|
||||
}
|
||||
else
|
||||
{
|
||||
width=(vinfo->currentwidth>>3);
|
||||
height=(vinfo->currentheight>>3);
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************/
|
||||
/* Renvoie la taille horizontale */
|
||||
u16 getwidth(void)
|
||||
{
|
||||
return width;
|
||||
}
|
||||
|
||||
/*******************************************************************************/
|
||||
/* Renvoie la taille verticale */
|
||||
u16 getheight(void)
|
||||
{
|
||||
return height;
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************/
|
||||
/* Efface la console en cours d'utilisation */
|
||||
void clearscreen(void)
|
||||
|
@ -240,7 +266,7 @@ void putchar(u8 thechar)
|
|||
vc[usedvc].cursY--;
|
||||
break;
|
||||
case 0x12:
|
||||
if (vc[usedvc].cursY < vinfo->currentheight - 1)
|
||||
if (vc[usedvc].cursY < getheight() - 1)
|
||||
vc[usedvc].cursY++;
|
||||
break;
|
||||
case 0x13:
|
||||
|
@ -248,7 +274,7 @@ void putchar(u8 thechar)
|
|||
vc[usedvc].cursX--;
|
||||
break;
|
||||
case 0x14:
|
||||
if (vc[usedvc].cursX < vinfo->currentwidth - 1)
|
||||
if (vc[usedvc].cursX < getwidth() - 1)
|
||||
vc[usedvc].cursX++;
|
||||
break;
|
||||
case 0x2:
|
||||
|
@ -257,15 +283,15 @@ void putchar(u8 thechar)
|
|||
break;
|
||||
case 0x3:
|
||||
vc[usedvc].cursX = 0;
|
||||
vc[usedvc].cursY = vinfo->currentheight - 1;
|
||||
vc[usedvc].cursY = getheight() - 1;
|
||||
break;
|
||||
case 0x19:
|
||||
vc[usedvc].cursX = vinfo->currentwidth - 1;
|
||||
vc[usedvc].cursX = getwidth() - 1;
|
||||
break;
|
||||
case '\b':
|
||||
if (vc[usedvc].cursX == 0) {
|
||||
if (vc[usedvc].cursY > 0) {
|
||||
vc[usedvc].cursX = vinfo->currentwidth - 1;
|
||||
vc[usedvc].cursX = getwidth() - 1;
|
||||
vc[usedvc].cursY--;
|
||||
}
|
||||
} else {
|
||||
|
@ -291,13 +317,13 @@ void putchar(u8 thechar)
|
|||
}
|
||||
break;
|
||||
}
|
||||
if (vc[usedvc].cursX >= vinfo->currentwidth) {
|
||||
if (vc[usedvc].cursX >= getwidth()) {
|
||||
vc[usedvc].cursX = 0;
|
||||
vc[usedvc].cursY++;
|
||||
}
|
||||
if (vc[usedvc].cursY >= vinfo->currentheight) {
|
||||
if (vc[usedvc].cursY >= getheight() ) {
|
||||
scroll(1, vc[usedvc].attrib);
|
||||
vc[usedvc].cursY = vinfo->currentheight - 1;
|
||||
vc[usedvc].cursY = getheight() - 1;
|
||||
}
|
||||
cursor_set(vc[usedvc].cursX, vc[usedvc].cursY);
|
||||
}
|
||||
|
@ -827,7 +853,7 @@ u8 *sitoa(u64 num, u8 * str, u64 dim)
|
|||
/*******************************************************************************/
|
||||
/* initialise le tableau des pilotes vidéo */
|
||||
void initdriver() {
|
||||
for(u32 i=0;i<maxdrivers;i++)
|
||||
for(u32 i=0;i<MAXDRIVERS;i++)
|
||||
registred[i].nom=NULL;
|
||||
}
|
||||
|
||||
|
@ -836,11 +862,11 @@ void initdriver() {
|
|||
void registerdriver(videofonction *pointer)
|
||||
{
|
||||
u32 i;
|
||||
for(i=0;i<maxdrivers;i++)
|
||||
for(i=0;i<MAXDRIVERS;i++)
|
||||
if (registred[i].pointer==pointer)
|
||||
return;
|
||||
i=0;
|
||||
while (registred[i].nom!=NULL && i<maxdrivers)
|
||||
while (registred[i].nom!=NULL && i<MAXDRIVERS)
|
||||
i++;
|
||||
registred[i].pointer=pointer;
|
||||
registred[i].nom=pointer->getvideo_drivername();
|
||||
|
@ -854,7 +880,7 @@ void apply_bestdriver(void) {
|
|||
u8 bestmode=0x0;
|
||||
u8* bestdriver=NULL;
|
||||
capabilities *cap;
|
||||
while (registred[i].nom!=NULL && i<maxdrivers) {
|
||||
while (registred[i].nom!=NULL && i<MAXDRIVERS) {
|
||||
cap=registred[i].pointer->getvideo_capabilities();
|
||||
while(cap[j].modenumber!=0xFF) {
|
||||
if (cap[j].depth>bestdepth && (cap[j].width*cap[j].height)>=bestresol)
|
||||
|
@ -877,7 +903,7 @@ void apply_bestdriver(void) {
|
|||
void apply_driver(u8* name)
|
||||
{
|
||||
u32 i=0;
|
||||
while (registred[i].nom!=NULL && i<maxdrivers) {
|
||||
while (registred[i].nom!=NULL && i<MAXDRIVERS) {
|
||||
if (strcmp(name,registred[i].nom)==0) {
|
||||
detect_hardware=registred[i].pointer->detect_hardware;
|
||||
setvideo_mode=registred[i].pointer->setvideo_mode;
|
||||
|
@ -911,7 +937,7 @@ void apply_driver(u8* name)
|
|||
|
||||
void apply_nextdriver(void) {
|
||||
u32 i=0;
|
||||
while (registred[i].nom!=NULL && i<maxdrivers)
|
||||
while (registred[i].nom!=NULL && i<MAXDRIVERS)
|
||||
if (strcmp(getvideo_drivername(),registred[i].nom)==0) {
|
||||
i++;
|
||||
if (registred[i].nom!=NULL) i=0;
|
||||
|
@ -950,7 +976,7 @@ void initvideo(void)
|
|||
initdriver();
|
||||
registerdriver(&fonctions);
|
||||
apply_driver("VGA");
|
||||
changemode(0x1);
|
||||
changemode(0x83);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
@ -960,8 +986,15 @@ static u8 space=' ';
|
|||
|
||||
void fill(u8 attrib)
|
||||
{
|
||||
mem_to_video(space ,0,vinfo->pagesize>>1, false);
|
||||
mem_to_video(attrib,1,vinfo->pagesize>>1, false);
|
||||
if (!vinfo->isgraphic)
|
||||
{
|
||||
mem_to_video(space ,0,vinfo->pagesize>>1, false);
|
||||
mem_to_video(attrib,1,vinfo->pagesize>>1, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
mem_to_video(0x0,0,vinfo->pagesize, false);
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
@ -977,6 +1010,12 @@ void scroll (u8 lines, u8 attrib)
|
|||
mem_to_video(space ,vinfo->pagesize-gain-2,gain, false);
|
||||
mem_to_video(attrib,vinfo->pagesize-gain-1,gain, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
u32 gain=vinfo->currentpitch*(lines<<3);
|
||||
video_to_video(gain,0,vinfo->pagesize-gain);
|
||||
mem_to_video(0x0 ,vinfo->pagesize-gain-2,gain, false);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1005,6 +1044,7 @@ void scroll_disable(void)
|
|||
|
||||
void showchar(u16 coordx, u16 coordy, u8 thechar, u8 attrib)
|
||||
{
|
||||
u8 x, y, pattern, set;
|
||||
if (!vinfo->isgraphic)
|
||||
{
|
||||
u32 addr=(coordx<<1)+vinfo->currentpitch*coordy;
|
||||
|
@ -1013,17 +1053,17 @@ void showchar(u16 coordx, u16 coordy, u8 thechar, u8 attrib)
|
|||
}
|
||||
else
|
||||
{
|
||||
u8 x, y, pattern, set;
|
||||
for (y = 0; y < 8; y++)
|
||||
{
|
||||
pattern = font8x8[thechar<<3 + y];
|
||||
for (x = 0; x < 8; x++) {
|
||||
pattern = font8x8[(thechar<<3) + y];
|
||||
for (x = 0; x < 8; x++)
|
||||
{
|
||||
set = pattern & 0x1;
|
||||
if (set == 0)
|
||||
writepxl((coordx<<3) + x, (coordy<<3) + y, ((attrib & 0xF0) >> 8));
|
||||
else
|
||||
writepxl((coordx<<3) + x, (coordy<<3) + y, (attrib & 0x0F) );
|
||||
rol(pattern);
|
||||
//set = ((pattern >> (7 - x)) & 0x1);
|
||||
if (pattern & 0x1 == 0)
|
||||
writepxl(coordx << 3 + x, coordy << 3 + y, ((attrib & 0xF0) >> 8) * set);
|
||||
else
|
||||
writepxl(coordx << 3 + x, coordy << 3 + y, (attrib & 0x0F) * set);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1075,7 +1115,7 @@ void hline(u32 x1, u32 x2, u32 y, u8 color)
|
|||
/* Affiche un pixel à l'écran */
|
||||
void writepxl (u16 x, u16 y, u32 color)
|
||||
{
|
||||
u32 addr=x+vinfo->currentheight*y;
|
||||
u32 addr=x+vinfo->currentpitch*y;
|
||||
mem_to_video(color,addr,1,false);
|
||||
}
|
||||
|
||||
|
|
|
@ -50,7 +50,7 @@ int main(u32 magic, u32 addr)
|
|||
/* Efface l'ecran */
|
||||
|
||||
print("\033[2J\000");
|
||||
print(ansilogo);
|
||||
if (getwidth()>40) print(ansilogo);
|
||||
|
||||
print("\033[37m\033[0m -Chargement noyaux");
|
||||
ok();
|
||||
|
|
Loading…
Reference in New Issue