2018-09-28 20:35:51 +02:00
|
|
|
|
/*******************************************************************************/
|
|
|
|
|
/* COS2000 - Compatible Operating System - LGPL v3 - Hord<72> Nicolas */
|
|
|
|
|
/* */
|
2018-10-13 11:25:55 +02:00
|
|
|
|
#include "asm.h"
|
2018-10-26 14:09:43 +02:00
|
|
|
|
#include "math.h"
|
2007-04-02 15:21:28 +02:00
|
|
|
|
#include "video.h"
|
2007-04-02 16:14:21 +02:00
|
|
|
|
#include "stdarg.h"
|
2018-10-14 19:14:19 +02:00
|
|
|
|
#include "string.h"
|
2018-10-13 11:25:55 +02:00
|
|
|
|
#include "VGA/8x8fnt.c"
|
|
|
|
|
#include "VGA/8x16fnt.c"
|
2007-04-02 15:21:28 +02:00
|
|
|
|
|
2018-10-26 14:09:43 +02:00
|
|
|
|
/******************************************************************************/
|
|
|
|
|
/* VARIABLES */
|
|
|
|
|
|
2018-10-13 13:23:00 +02:00
|
|
|
|
static drivers registred[MAXDRIVERS];
|
2018-10-13 05:35:08 +02:00
|
|
|
|
|
2018-10-14 19:14:19 +02:00
|
|
|
|
static font fonts[MAXFONTS];
|
|
|
|
|
|
2018-12-12 15:25:04 +01:00
|
|
|
|
static videoinfos *vinfo;
|
2018-10-13 05:35:08 +02:00
|
|
|
|
|
2018-12-12 15:25:04 +01:00
|
|
|
|
static width, height;
|
2018-10-13 13:23:00 +02:00
|
|
|
|
|
2018-12-12 15:25:04 +01:00
|
|
|
|
static font *currentfont;
|
2018-10-14 19:14:19 +02:00
|
|
|
|
|
2018-12-12 15:25:04 +01:00
|
|
|
|
static console vc[8] = {
|
|
|
|
|
{0x07, 0, 0, 0, 0, 0, 0, 0, true},
|
|
|
|
|
{0x07, 0, 0, 0, 0, 0, 0, 0, true},
|
|
|
|
|
{0x07, 0, 0, 0, 0, 0, 0, 0, true},
|
|
|
|
|
{0x07, 0, 0, 0, 0, 0, 0, 0, true},
|
|
|
|
|
{0x07, 0, 0, 0, 0, 0, 0, 0, true},
|
|
|
|
|
{0x07, 0, 0, 0, 0, 0, 0, 0, true},
|
|
|
|
|
{0x07, 0, 0, 0, 0, 0, 0, 0, true},
|
2018-10-13 11:25:55 +02:00
|
|
|
|
{0x07, 0, 0, 0, 0, 0, 0, 0, true}
|
2018-08-17 16:46:56 +02:00
|
|
|
|
};
|
2007-04-02 16:14:21 +02:00
|
|
|
|
|
2018-10-13 05:35:08 +02:00
|
|
|
|
static u8 usedvc = 0;
|
2007-04-02 15:44:12 +02:00
|
|
|
|
|
2018-10-26 14:09:43 +02:00
|
|
|
|
/******************************************************************************/
|
|
|
|
|
/* FONCTIONS CONSOLE */
|
|
|
|
|
|
2007-04-02 15:44:12 +02:00
|
|
|
|
/*******************************************************************************/
|
|
|
|
|
/* Fixe l'attribut courant */
|
|
|
|
|
|
|
|
|
|
void setattrib(u8 att)
|
|
|
|
|
{
|
2018-08-17 16:46:56 +02:00
|
|
|
|
static const u8 ansitovga[] = {
|
2007-04-02 15:44:12 +02:00
|
|
|
|
0, 4, 2, 6, 1, 5, 3, 7
|
|
|
|
|
};
|
2018-12-12 15:25:04 +01:00
|
|
|
|
u8 tempattr;
|
2007-04-02 15:44:12 +02:00
|
|
|
|
|
2007-04-02 16:14:21 +02:00
|
|
|
|
tempattr = vc[usedvc].attrib;
|
2018-08-17 16:46:56 +02:00
|
|
|
|
if (att == 0)
|
|
|
|
|
tempattr = 0x07; /* Couleur Grise sur fond noir */
|
2007-04-02 16:14:21 +02:00
|
|
|
|
else if (att == 5)
|
2018-08-17 16:46:56 +02:00
|
|
|
|
tempattr |= 0x80;
|
2007-04-02 16:14:21 +02:00
|
|
|
|
else if (att == 7)
|
2018-12-12 15:25:04 +01:00
|
|
|
|
tempattr =
|
|
|
|
|
((tempattr & 0x0F) << 4) +
|
|
|
|
|
((tempattr & 0xF0) >> 4);
|
2007-04-02 16:14:21 +02:00
|
|
|
|
else if (att == 8)
|
2018-08-17 16:46:56 +02:00
|
|
|
|
tempattr = 0;
|
2007-04-02 16:14:21 +02:00
|
|
|
|
else if (att == 1)
|
2018-08-17 16:46:56 +02:00
|
|
|
|
tempattr |= 0x08; /* Forte intensit<69> */
|
2018-12-12 15:25:04 +01:00
|
|
|
|
else if (att >= 30 && att <= 37)
|
|
|
|
|
{
|
2007-04-02 15:44:12 +02:00
|
|
|
|
att = ansitovga[att - 30];
|
2018-08-17 16:46:56 +02:00
|
|
|
|
tempattr = (tempattr & ~0x07) | att; /* couleur de premier plan */
|
2018-12-12 15:25:04 +01:00
|
|
|
|
}
|
|
|
|
|
else if (att >= 40 && att <= 47)
|
|
|
|
|
{
|
2007-04-02 15:44:12 +02:00
|
|
|
|
att = ansitovga[att - 40] << 4;
|
2018-08-17 16:46:56 +02:00
|
|
|
|
tempattr = (tempattr & ~0x70) | att; /* couleur de fond */
|
2007-04-02 15:44:12 +02:00
|
|
|
|
}
|
2007-04-02 16:14:21 +02:00
|
|
|
|
vc[usedvc].attrib = tempattr;
|
2007-04-02 15:44:12 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*******************************************************************************/
|
|
|
|
|
/* gere l'ansi */
|
|
|
|
|
|
|
|
|
|
bool makeansi(u8 c)
|
|
|
|
|
{
|
|
|
|
|
/* state machine to handle the escape sequences */
|
2018-12-12 15:25:04 +01:00
|
|
|
|
switch (vc[usedvc].ansi)
|
|
|
|
|
{
|
|
|
|
|
case 0:
|
2007-04-02 15:44:12 +02:00
|
|
|
|
/* ESC -- next state */
|
2018-12-12 15:25:04 +01:00
|
|
|
|
if (c == 0x1B)
|
|
|
|
|
{
|
|
|
|
|
vc[usedvc].ansi++;
|
|
|
|
|
return 1; /* "I handled it" */
|
|
|
|
|
}
|
|
|
|
|
break;
|
2007-04-02 15:44:12 +02:00
|
|
|
|
/* ESC */
|
2018-12-12 15:25:04 +01:00
|
|
|
|
case 1:
|
|
|
|
|
if (c == '[')
|
|
|
|
|
{
|
|
|
|
|
vc[usedvc].ansi++;
|
|
|
|
|
vc[usedvc].param1 = 0;
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
break;
|
2007-04-02 15:44:12 +02:00
|
|
|
|
/* ESC[ */
|
2018-12-12 15:25:04 +01:00
|
|
|
|
case 2:
|
|
|
|
|
if (isdigit(c))
|
|
|
|
|
{
|
|
|
|
|
vc[usedvc].param1 =
|
|
|
|
|
vc[usedvc].param1 * 10 + c - '0';
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
else if (c == ';')
|
|
|
|
|
{
|
|
|
|
|
vc[usedvc].ansi++;
|
|
|
|
|
vc[usedvc].param2 = 0;
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
2007-04-02 15:44:12 +02:00
|
|
|
|
/* ESC[2J -- efface l'ecran */
|
2018-12-12 15:25:04 +01:00
|
|
|
|
else if (c == 'J')
|
|
|
|
|
{
|
|
|
|
|
if (vc[usedvc].param1 == 2)
|
|
|
|
|
{
|
|
|
|
|
fill(vc[usedvc].attrib);
|
|
|
|
|
vc[usedvc].cursX = 0;
|
|
|
|
|
vc[usedvc].cursY = 0;
|
|
|
|
|
cursor_set(0, 0);
|
|
|
|
|
vc[usedvc].ansi = 0;
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/* ESC[num1m -- met l'attribut num1 */
|
|
|
|
|
else if (c == 'm')
|
|
|
|
|
{
|
|
|
|
|
setattrib(vc[usedvc].param1);
|
2007-04-02 16:14:21 +02:00
|
|
|
|
vc[usedvc].ansi = 0;
|
2007-04-02 15:44:12 +02:00
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
/* ESC[num1A -- bouge le curseur de num1 vers le haut */
|
2018-12-12 15:25:04 +01:00
|
|
|
|
else if (c == 'A')
|
|
|
|
|
{
|
|
|
|
|
vc[usedvc].cursY -= vc[usedvc].param1;
|
|
|
|
|
if (vc[usedvc].cursY < 0)
|
|
|
|
|
vc[usedvc].cursY = 0;
|
|
|
|
|
vc[usedvc].ansi = 0;
|
|
|
|
|
cursor_set(vc[usedvc].cursX,
|
|
|
|
|
vc[usedvc].cursY);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
2007-04-02 15:44:12 +02:00
|
|
|
|
/* ESC[num1B -- bouge le curseur de num1 vers le bas */
|
2018-12-12 15:25:04 +01:00
|
|
|
|
else if (c == 'B')
|
|
|
|
|
{
|
|
|
|
|
vc[usedvc].cursY += vc[usedvc].param1;
|
|
|
|
|
if (vc[usedvc].cursY >= getheight() - 1)
|
|
|
|
|
vc[usedvc].cursY = getheight();
|
|
|
|
|
vc[usedvc].ansi = 0;
|
|
|
|
|
cursor_set(vc[usedvc].cursX,
|
|
|
|
|
vc[usedvc].cursY);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
2007-04-02 16:14:21 +02:00
|
|
|
|
/* ESC[num1D -- bouge le curseur de num1 vers la gauche */
|
2018-12-12 15:25:04 +01:00
|
|
|
|
else if (c == 'D')
|
|
|
|
|
{
|
|
|
|
|
vc[usedvc].cursX -= vc[usedvc].param1;
|
|
|
|
|
if (vc[usedvc].cursX < 0)
|
|
|
|
|
vc[usedvc].cursX = 0;
|
|
|
|
|
vc[usedvc].ansi = 0;
|
|
|
|
|
cursor_set(vc[usedvc].cursX,
|
|
|
|
|
vc[usedvc].cursY);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
2007-04-02 16:14:21 +02:00
|
|
|
|
/* ESC[num1C -- bouge le curseur de num1 vers la droite */
|
2018-12-12 15:25:04 +01:00
|
|
|
|
else if (c == 'C')
|
|
|
|
|
{
|
|
|
|
|
vc[usedvc].cursX += vc[usedvc].param1;
|
|
|
|
|
if (vc[usedvc].cursX >= getwidth() - 1)
|
|
|
|
|
vc[usedvc].cursX = getwidth();
|
|
|
|
|
vc[usedvc].ansi = 0;
|
|
|
|
|
cursor_set(vc[usedvc].cursX,
|
|
|
|
|
vc[usedvc].cursY);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
break;
|
2007-04-02 15:44:12 +02:00
|
|
|
|
/* ESC[num1; */
|
2018-12-12 15:25:04 +01:00
|
|
|
|
case 3:
|
|
|
|
|
if (isdigit(c))
|
|
|
|
|
{
|
|
|
|
|
vc[usedvc].param2 =
|
|
|
|
|
vc[usedvc].param2 * 10 + c - '0';
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
else if (c == ';')
|
|
|
|
|
{
|
|
|
|
|
vc[usedvc].ansi++;
|
|
|
|
|
vc[usedvc].param3 = 0;
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
2007-04-02 15:44:12 +02:00
|
|
|
|
/* ESC[num1;num2H ou ESC[num1;num2f-- bouge le curseur en num1,num2 */
|
2018-12-12 15:25:04 +01:00
|
|
|
|
else if ((c == 'H') || (c == 'f'))
|
|
|
|
|
{
|
|
|
|
|
/* Remet la position du curseur mat<61>riel a num1,num2 */
|
|
|
|
|
cursor_set(vc[usedvc].param2,
|
|
|
|
|
vc[usedvc].param1);
|
|
|
|
|
/* Remet la position du curseur logiciel a num1,num2 */
|
|
|
|
|
vc[usedvc].cursX = vc[usedvc].param2;
|
|
|
|
|
vc[usedvc].cursY = vc[usedvc].param1;
|
|
|
|
|
vc[usedvc].ansi = 0;
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
2007-04-02 15:44:12 +02:00
|
|
|
|
/* ESC[num1;num2m -- met les attributs num1,num2 */
|
2018-12-12 15:25:04 +01:00
|
|
|
|
else if (c == 'm')
|
|
|
|
|
{
|
|
|
|
|
setattrib(vc[usedvc].param1);
|
|
|
|
|
setattrib(vc[usedvc].param2);
|
|
|
|
|
vc[usedvc].ansi = 0;
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
break;
|
2007-04-02 15:44:12 +02:00
|
|
|
|
/* ESC[num1;num2;num3 */
|
2018-12-12 15:25:04 +01:00
|
|
|
|
case 4:
|
|
|
|
|
if (isdigit(c))
|
|
|
|
|
{
|
|
|
|
|
vc[usedvc].param3 =
|
|
|
|
|
vc[usedvc].param3 * 10 + c - '0';
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
2007-04-02 15:44:12 +02:00
|
|
|
|
/* ESC[num1;num2;num3m -- met les attributs num1,num2,num3 */
|
2018-12-12 15:25:04 +01:00
|
|
|
|
else if (c == 'm')
|
|
|
|
|
{
|
|
|
|
|
setattrib(vc[usedvc].param1);
|
|
|
|
|
setattrib(vc[usedvc].param2);
|
|
|
|
|
setattrib(vc[usedvc].param3);
|
|
|
|
|
vc[usedvc].ansi = 0;
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
break;
|
2007-04-02 15:44:12 +02:00
|
|
|
|
/* Mauvais etat >> reset */
|
2018-12-12 15:25:04 +01:00
|
|
|
|
default:
|
|
|
|
|
vc[usedvc].ansi = 0;
|
|
|
|
|
break;
|
2007-04-02 15:44:12 +02:00
|
|
|
|
}
|
2007-04-02 16:14:21 +02:00
|
|
|
|
vc[usedvc].ansi = 0;
|
2018-08-17 16:46:56 +02:00
|
|
|
|
return 0; /* Ansi fini ;) */
|
2007-04-02 15:44:12 +02:00
|
|
|
|
}
|
2018-10-12 22:31:34 +02:00
|
|
|
|
|
2007-04-02 16:14:21 +02:00
|
|
|
|
/*******************************************************************************/
|
2007-04-02 15:44:12 +02:00
|
|
|
|
/* affiche un caract<63>re a l'<27>cran */
|
|
|
|
|
|
|
|
|
|
void putchar(u8 thechar)
|
|
|
|
|
{
|
2018-10-12 22:31:34 +02:00
|
|
|
|
page_show(usedvc);
|
|
|
|
|
page_set(usedvc);
|
2018-08-17 16:46:56 +02:00
|
|
|
|
if (makeansi(thechar))
|
|
|
|
|
return;
|
2018-12-12 15:25:04 +01:00
|
|
|
|
switch (thechar)
|
|
|
|
|
{
|
|
|
|
|
case 0x11:
|
|
|
|
|
if (vc[usedvc].cursY > 0)
|
2018-08-17 16:46:56 +02:00
|
|
|
|
vc[usedvc].cursY--;
|
2018-12-12 15:25:04 +01:00
|
|
|
|
break;
|
|
|
|
|
case 0x12:
|
|
|
|
|
if (vc[usedvc].cursY < getheight() - 1)
|
|
|
|
|
vc[usedvc].cursY++;
|
|
|
|
|
break;
|
|
|
|
|
case 0x13:
|
|
|
|
|
if (vc[usedvc].cursX > 0)
|
|
|
|
|
vc[usedvc].cursX--;
|
|
|
|
|
break;
|
|
|
|
|
case 0x14:
|
|
|
|
|
if (vc[usedvc].cursX < getwidth() - 1)
|
|
|
|
|
vc[usedvc].cursX++;
|
|
|
|
|
break;
|
|
|
|
|
case 0x2:
|
|
|
|
|
vc[usedvc].cursX = 0;
|
|
|
|
|
vc[usedvc].cursY = 0;
|
|
|
|
|
break;
|
|
|
|
|
case 0x3:
|
|
|
|
|
vc[usedvc].cursX = 0;
|
|
|
|
|
vc[usedvc].cursY = getheight() - 1;
|
|
|
|
|
break;
|
|
|
|
|
case 0x19:
|
|
|
|
|
vc[usedvc].cursX = getwidth() - 1;
|
|
|
|
|
break;
|
|
|
|
|
case '\b':
|
|
|
|
|
if (vc[usedvc].cursX == 0)
|
|
|
|
|
{
|
|
|
|
|
if (vc[usedvc].cursY > 0)
|
|
|
|
|
{
|
|
|
|
|
vc[usedvc].cursX = getwidth() - 1;
|
|
|
|
|
vc[usedvc].cursY--;
|
|
|
|
|
}
|
2018-08-17 16:46:56 +02:00
|
|
|
|
}
|
2018-12-12 15:25:04 +01:00
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
vc[usedvc].cursX--;
|
|
|
|
|
}
|
|
|
|
|
showchar(vc[usedvc].cursX, vc[usedvc].cursY, ' ',
|
|
|
|
|
vc[usedvc].attrib);
|
|
|
|
|
break;
|
|
|
|
|
case '\t':
|
|
|
|
|
vc[usedvc].cursX =
|
|
|
|
|
(vc[usedvc].cursX + 8) & ~(8 - 1);
|
|
|
|
|
break;
|
|
|
|
|
case '\n':
|
|
|
|
|
vc[usedvc].cursX = 0;
|
|
|
|
|
break;
|
|
|
|
|
case '\r':
|
|
|
|
|
vc[usedvc].cursX = 0;
|
|
|
|
|
vc[usedvc].cursY++;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
if (thechar >= ' ')
|
|
|
|
|
{
|
|
|
|
|
showchar(vc[usedvc].cursX,
|
|
|
|
|
vc[usedvc].cursY, thechar,
|
|
|
|
|
vc[usedvc].attrib);
|
|
|
|
|
vc[usedvc].cursX++;
|
|
|
|
|
}
|
|
|
|
|
break;
|
2018-08-17 16:46:56 +02:00
|
|
|
|
}
|
2018-12-12 15:25:04 +01:00
|
|
|
|
if (vc[usedvc].cursX >= getwidth())
|
|
|
|
|
{
|
2018-08-17 16:46:56 +02:00
|
|
|
|
vc[usedvc].cursX = 0;
|
|
|
|
|
vc[usedvc].cursY++;
|
|
|
|
|
}
|
2018-12-12 15:25:04 +01:00
|
|
|
|
if (vc[usedvc].cursY >= getheight())
|
|
|
|
|
{
|
2018-08-17 16:46:56 +02:00
|
|
|
|
scroll(1, vc[usedvc].attrib);
|
2018-12-12 15:25:04 +01:00
|
|
|
|
vc[usedvc].cursY = getheight() - 1;
|
2018-08-17 16:46:56 +02:00
|
|
|
|
}
|
2018-10-12 22:31:34 +02:00
|
|
|
|
cursor_set(vc[usedvc].cursX, vc[usedvc].cursY);
|
2007-04-02 15:44:12 +02:00
|
|
|
|
}
|
|
|
|
|
|
2007-04-02 15:21:28 +02:00
|
|
|
|
/*******************************************************************************/
|
2018-10-26 14:09:43 +02:00
|
|
|
|
/* Change la console en cours d'utilisation */
|
2007-04-02 15:21:28 +02:00
|
|
|
|
|
2018-10-26 14:09:43 +02:00
|
|
|
|
void changevc(u8 avc)
|
2007-04-02 15:21:28 +02:00
|
|
|
|
{
|
2018-10-26 14:09:43 +02:00
|
|
|
|
usedvc = avc;
|
|
|
|
|
page_show(usedvc);
|
|
|
|
|
page_set(usedvc);
|
|
|
|
|
cursor_set(vc[usedvc].cursX, vc[usedvc].cursY);
|
2007-04-02 15:21:28 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*******************************************************************************/
|
2018-10-26 14:09:43 +02:00
|
|
|
|
/* Renvoie la taille horizontale */
|
|
|
|
|
u16 getwidth(void)
|
|
|
|
|
{
|
2018-12-12 15:25:04 +01:00
|
|
|
|
return width;
|
2018-10-07 12:57:38 +02:00
|
|
|
|
}
|
2007-04-02 15:21:28 +02:00
|
|
|
|
|
2018-10-07 12:57:38 +02:00
|
|
|
|
/*******************************************************************************/
|
2018-10-26 14:09:43 +02:00
|
|
|
|
/* Renvoie la taille verticale */
|
|
|
|
|
u16 getheight(void)
|
|
|
|
|
{
|
2018-12-12 15:25:04 +01:00
|
|
|
|
return height;
|
2018-10-07 12:57:38 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*******************************************************************************/
|
2018-10-26 14:09:43 +02:00
|
|
|
|
/* Efface la console en cours d'utilisation */
|
|
|
|
|
void clearscreen(void)
|
2007-04-02 15:21:28 +02:00
|
|
|
|
{
|
2018-12-12 15:25:04 +01:00
|
|
|
|
fill(vc[usedvc].attrib);
|
|
|
|
|
vc[usedvc].cursX = 0;
|
|
|
|
|
vc[usedvc].cursY = 0;
|
|
|
|
|
cursor_set(0, 0);
|
2018-10-07 12:57:38 +02:00
|
|
|
|
}
|
|
|
|
|
|
2018-10-26 14:09:43 +02:00
|
|
|
|
/******************************************************************************/
|
|
|
|
|
/* Active le scrolling */
|
2018-10-07 12:57:38 +02:00
|
|
|
|
|
2018-12-12 15:25:04 +01:00
|
|
|
|
void scroll_enable(void)
|
2018-10-07 12:57:38 +02:00
|
|
|
|
{
|
2018-12-12 15:25:04 +01:00
|
|
|
|
vc[usedvc].scroll = true;
|
2018-10-08 21:50:40 +02:00
|
|
|
|
}
|
2018-10-07 12:57:38 +02:00
|
|
|
|
|
2018-10-26 14:09:43 +02:00
|
|
|
|
/******************************************************************************/
|
|
|
|
|
/* D<>sactive le scrolling */
|
2018-10-08 21:50:40 +02:00
|
|
|
|
|
2018-12-12 15:25:04 +01:00
|
|
|
|
void scroll_disable(void)
|
2018-10-08 21:50:40 +02:00
|
|
|
|
{
|
2018-12-12 15:25:04 +01:00
|
|
|
|
vc[usedvc].scroll = false;
|
2018-10-07 12:57:38 +02:00
|
|
|
|
}
|
|
|
|
|
|
2018-10-26 14:09:43 +02:00
|
|
|
|
/******************************************************************************/
|
|
|
|
|
/* FONCTIONS VIDEO BASIQUES */
|
|
|
|
|
|
2018-10-08 21:50:40 +02:00
|
|
|
|
/*******************************************************************************/
|
2018-10-26 14:09:43 +02:00
|
|
|
|
/* initialise le tableau des pilotes vid<69>o */
|
2018-12-12 15:25:04 +01:00
|
|
|
|
void initdriver()
|
|
|
|
|
{
|
|
|
|
|
for (u32 i = 0; i < MAXDRIVERS; i++)
|
|
|
|
|
registred[i].nom = NULL;
|
2018-10-26 14:09:43 +02:00
|
|
|
|
}
|
2018-10-08 21:50:40 +02:00
|
|
|
|
|
2018-10-26 14:09:43 +02:00
|
|
|
|
/*******************************************************************************/
|
|
|
|
|
/* Enregistre un pilote dans le tableau des pilotes vid<69>o */
|
2018-12-12 15:25:04 +01:00
|
|
|
|
void registerdriver(videofonction * pointer)
|
2018-10-08 21:50:40 +02:00
|
|
|
|
{
|
2018-12-12 15:25:04 +01:00
|
|
|
|
u32 i;
|
|
|
|
|
for (i = 0; i < MAXDRIVERS; i++)
|
|
|
|
|
if (registred[i].pointer == pointer)
|
|
|
|
|
return;
|
|
|
|
|
i = 0;
|
|
|
|
|
while (registred[i].nom != NULL && i < MAXDRIVERS)
|
|
|
|
|
i++;
|
|
|
|
|
if (pointer->detect_hardware() != NULL)
|
|
|
|
|
{
|
|
|
|
|
registred[i].pointer = pointer;
|
|
|
|
|
registred[i].nom = pointer->getvideo_drivername();
|
|
|
|
|
}
|
2018-10-08 21:50:40 +02:00
|
|
|
|
}
|
2018-10-07 12:57:38 +02:00
|
|
|
|
/*******************************************************************************/
|
2018-10-26 14:09:43 +02:00
|
|
|
|
/* Choisi le meilleur driver en terme d'affichage */
|
2018-12-12 15:25:04 +01:00
|
|
|
|
void apply_bestdriver(void)
|
|
|
|
|
{
|
|
|
|
|
u32 i = 0, j;
|
|
|
|
|
u8 bestdepth = 0x0;
|
|
|
|
|
u32 bestresol = 0x0;
|
|
|
|
|
u8 bestmode = 0x0;
|
|
|
|
|
u8 *bestdriver = NULL;
|
|
|
|
|
capabilities *cap;
|
|
|
|
|
while (registred[i].nom != NULL && i < MAXDRIVERS)
|
|
|
|
|
{
|
|
|
|
|
cap = registred[i].pointer->getvideo_capabilities();
|
|
|
|
|
j = 0;
|
|
|
|
|
while (cap[j].modenumber != 0xFF)
|
|
|
|
|
{
|
|
|
|
|
if (cap[j].depth > bestdepth
|
|
|
|
|
&& (cap[j].width * cap[j].height) >= bestresol)
|
|
|
|
|
{
|
|
|
|
|
bestdepth = cap[j].depth;
|
|
|
|
|
bestresol = cap[j].width * cap[j].height;
|
|
|
|
|
bestmode = cap[j].modenumber;
|
|
|
|
|
bestdriver =
|
2018-12-12 17:57:23 +01:00
|
|
|
|
registred[i].
|
|
|
|
|
pointer->getvideo_drivername();
|
2018-12-12 15:25:04 +01:00
|
|
|
|
}
|
|
|
|
|
j++;
|
|
|
|
|
}
|
|
|
|
|
i++;
|
|
|
|
|
}
|
|
|
|
|
if (bestdriver != NULL)
|
|
|
|
|
apply_driver(bestdriver);
|
|
|
|
|
setvideo_mode(bestmode);
|
2018-10-26 14:09:43 +02:00
|
|
|
|
}
|
2018-10-08 21:50:40 +02:00
|
|
|
|
|
2018-10-26 14:09:43 +02:00
|
|
|
|
/*******************************************************************************/
|
|
|
|
|
/* Choisi le meilleur driver sp<73>cifi<66> par le nom */
|
2018-12-12 15:25:04 +01:00
|
|
|
|
void apply_driver(u8 * name)
|
2018-10-08 21:50:40 +02:00
|
|
|
|
{
|
2018-12-12 15:25:04 +01:00
|
|
|
|
u32 i = 0;
|
|
|
|
|
while (registred[i].nom != NULL && i < MAXDRIVERS)
|
|
|
|
|
{
|
|
|
|
|
if (strcmp(name, registred[i].nom) == 0)
|
|
|
|
|
{
|
|
|
|
|
remap_memory = registred[i].pointer->remap_memory;
|
|
|
|
|
detect_hardware =
|
|
|
|
|
registred[i].pointer->detect_hardware;
|
|
|
|
|
setvideo_mode =
|
|
|
|
|
registred[i].pointer->setvideo_mode;
|
|
|
|
|
getvideo_drivername =
|
|
|
|
|
registred[i].pointer->getvideo_drivername;
|
|
|
|
|
getvideo_capabilities =
|
2018-12-12 17:57:23 +01:00
|
|
|
|
registred[i].
|
|
|
|
|
pointer->getvideo_capabilities;
|
2018-12-12 15:25:04 +01:00
|
|
|
|
getvideo_info =
|
|
|
|
|
registred[i].pointer->getvideo_info;
|
|
|
|
|
mem_to_video = registred[i].pointer->mem_to_video;
|
|
|
|
|
video_to_mem = registred[i].pointer->video_to_mem;
|
|
|
|
|
video_to_video =
|
|
|
|
|
registred[i].pointer->video_to_video;
|
|
|
|
|
wait_vretrace =
|
|
|
|
|
registred[i].pointer->wait_vretrace;
|
|
|
|
|
wait_hretrace =
|
|
|
|
|
registred[i].pointer->wait_hretrace;
|
|
|
|
|
page_set = registred[i].pointer->page_set;
|
|
|
|
|
page_show = registred[i].pointer->page_show;
|
|
|
|
|
page_split = registred[i].pointer->page_split;
|
|
|
|
|
cursor_enable =
|
|
|
|
|
registred[i].pointer->cursor_enable;
|
|
|
|
|
cursor_disable =
|
|
|
|
|
registred[i].pointer->cursor_disable;
|
|
|
|
|
cursor_set = registred[i].pointer->cursor_set;
|
|
|
|
|
font_load = registred[i].pointer->font_load;
|
|
|
|
|
font1_set = registred[i].pointer->font1_set;
|
|
|
|
|
font2_set = registred[i].pointer->font2_set;
|
|
|
|
|
blink_enable = registred[i].pointer->blink_enable;
|
|
|
|
|
blink_disable =
|
|
|
|
|
registred[i].pointer->blink_disable;
|
|
|
|
|
changemode(0x0);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
i++;
|
|
|
|
|
}
|
2018-10-08 21:50:40 +02:00
|
|
|
|
}
|
|
|
|
|
/*******************************************************************************/
|
2018-10-26 14:09:43 +02:00
|
|
|
|
/* Applique le driver suivant */
|
2018-10-07 12:57:38 +02:00
|
|
|
|
|
2018-12-12 15:25:04 +01:00
|
|
|
|
void apply_nextdriver(void)
|
|
|
|
|
{
|
|
|
|
|
u32 i = 0;
|
|
|
|
|
while (registred[i].nom != NULL && i < MAXDRIVERS)
|
|
|
|
|
if (strcmp(getvideo_drivername(), registred[i].nom) == 0)
|
|
|
|
|
{
|
|
|
|
|
i++;
|
|
|
|
|
if (registred[i].nom != NULL)
|
|
|
|
|
i = 0;
|
|
|
|
|
apply_driver(registred[i].nom);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
i++;
|
2018-10-08 21:50:40 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*******************************************************************************/
|
2018-10-26 14:09:43 +02:00
|
|
|
|
/* Applique le mode suivant (le driver suivant si dernier mode) */
|
2018-10-12 20:37:26 +02:00
|
|
|
|
|
2018-12-12 15:25:04 +01:00
|
|
|
|
void apply_nextvideomode(void)
|
|
|
|
|
{
|
|
|
|
|
capabilities *cap = getvideo_capabilities();
|
|
|
|
|
videoinfos *info = getvideo_info();
|
|
|
|
|
u32 mode = info->currentmode;
|
|
|
|
|
u8 index = 0;
|
|
|
|
|
while (cap[index].modenumber != 0xFF)
|
|
|
|
|
{
|
|
|
|
|
if (cap[index].modenumber == mode)
|
|
|
|
|
{
|
|
|
|
|
index++;
|
|
|
|
|
if (cap[index].modenumber == 0xFF)
|
|
|
|
|
apply_nextdriver();
|
|
|
|
|
else
|
|
|
|
|
changemode(cap[index].modenumber);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
index++;
|
|
|
|
|
}
|
2018-10-12 20:37:26 +02:00
|
|
|
|
}
|
|
|
|
|
|
2018-10-26 14:09:43 +02:00
|
|
|
|
/*******************************************************************************/
|
|
|
|
|
/* Change de mode video */
|
|
|
|
|
|
|
|
|
|
void changemode(u8 mode)
|
|
|
|
|
{
|
2018-12-12 15:25:04 +01:00
|
|
|
|
setvideo_mode(mode);
|
|
|
|
|
vinfo = getvideo_info();
|
|
|
|
|
if (!vinfo->isgraphic)
|
|
|
|
|
{
|
|
|
|
|
width = vinfo->currentwidth;
|
|
|
|
|
height = vinfo->currentheight;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
width = (vinfo->currentwidth >> 3);
|
|
|
|
|
height = (vinfo->currentheight >> 3);
|
|
|
|
|
}
|
|
|
|
|
for (u32 i = 0; i < MAXFONTS; i++)
|
|
|
|
|
fonts[i].nom[0] = NULL;
|
|
|
|
|
loadfont("BIOS1", font8x8, 8, 8);
|
|
|
|
|
loadfont("BIOS0", font8x16, 8, 16);
|
|
|
|
|
setfont("BIOS1");
|
|
|
|
|
clearscreen();
|
2018-10-26 14:09:43 +02:00
|
|
|
|
}
|
|
|
|
|
|
2018-10-13 11:25:55 +02:00
|
|
|
|
/******************************************************************************/
|
|
|
|
|
/* Rempli l'<27>cran avec un attribut donn<6E> et des espaces vides */
|
|
|
|
|
|
2018-12-12 15:25:04 +01:00
|
|
|
|
static u8 space = ' ';
|
2018-10-12 20:37:26 +02:00
|
|
|
|
|
2018-12-12 15:25:04 +01:00
|
|
|
|
void fill(u8 attrib)
|
2018-10-12 20:37:26 +02:00
|
|
|
|
{
|
2018-12-12 15:25:04 +01:00
|
|
|
|
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 >> 2, false);
|
|
|
|
|
}
|
2018-10-12 20:37:26 +02:00
|
|
|
|
}
|
|
|
|
|
|
2018-10-13 11:25:55 +02:00
|
|
|
|
/******************************************************************************/
|
|
|
|
|
/* D<>file l'<27>cran de N ligne si le scrolling est activ<69> */
|
|
|
|
|
|
2018-12-12 15:25:04 +01:00
|
|
|
|
void scroll(u8 lines, u8 attrib)
|
2018-10-12 20:37:26 +02:00
|
|
|
|
{
|
2018-12-12 15:25:04 +01:00
|
|
|
|
if (vc[usedvc].scroll)
|
|
|
|
|
{
|
|
|
|
|
if (!vinfo->isgraphic)
|
|
|
|
|
{
|
|
|
|
|
u32 gain = vinfo->currentpitch * lines;
|
|
|
|
|
video_to_video(gain, 0, vinfo->pagesize - gain);
|
|
|
|
|
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
|
|
|
|
|
{
|
|
|
|
|
clearscreen();
|
|
|
|
|
}
|
2018-10-12 20:37:26 +02:00
|
|
|
|
}
|
|
|
|
|
|
2018-10-13 11:25:55 +02:00
|
|
|
|
/******************************************************************************/
|
2018-10-26 14:09:43 +02:00
|
|
|
|
/* Retourne une couleur RGB 32 bits depuis une couleur EGA/VGA */
|
2018-10-13 11:25:55 +02:00
|
|
|
|
|
2018-12-12 15:25:04 +01:00
|
|
|
|
static convertega[] =
|
|
|
|
|
{ 0, 1, 2, 3, 4, 5, 20, 7, 56, 57, 58, 59, 60, 61, 62, 63 };
|
2018-10-26 14:09:43 +02:00
|
|
|
|
|
|
|
|
|
u8 egatovga(u8 ega)
|
2018-10-12 20:37:26 +02:00
|
|
|
|
{
|
2018-12-12 15:25:04 +01:00
|
|
|
|
return convertega[ega & 0xF];
|
2018-10-12 20:37:26 +02:00
|
|
|
|
}
|
|
|
|
|
|
2018-10-13 11:25:55 +02:00
|
|
|
|
/******************************************************************************/
|
2018-10-26 14:09:43 +02:00
|
|
|
|
/* Retourne une couleur RGB 32 bits depuis une couleur EGA/VGA */
|
2018-10-13 11:25:55 +02:00
|
|
|
|
|
2018-12-12 15:25:04 +01:00
|
|
|
|
static convertrgb[] =
|
|
|
|
|
{ 0x000000, 0x0000AA, 0x00AA00, 0x00AAAA, 0xAA0000, 0xAA00AA,
|
2018-12-12 17:57:23 +01:00
|
|
|
|
0xAA5500, 0xAAAAAA, 0x555555, 0x5555FF, 0x55FF55, 0x55FFFF,
|
|
|
|
|
0xFF5555,
|
|
|
|
|
0xFF55FF, 0xFFFF55, 0xFFFFFF
|
|
|
|
|
};
|
2018-10-26 14:09:43 +02:00
|
|
|
|
|
|
|
|
|
u32 egatorgb(u8 vga)
|
2018-10-12 20:37:26 +02:00
|
|
|
|
{
|
2018-12-12 15:25:04 +01:00
|
|
|
|
return convertrgb[vga & 0xF];
|
2018-10-26 14:09:43 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
|
/* Retourne le caract<63>re du mode texte aux coordonn<6E>es sp<73>cifi<66>es */
|
|
|
|
|
|
2018-12-12 15:25:04 +01:00
|
|
|
|
u8 getchar(u16 coordx, u16 coordy)
|
2018-10-26 14:09:43 +02:00
|
|
|
|
{
|
2018-12-12 15:25:04 +01:00
|
|
|
|
u8 thechar = 0;
|
|
|
|
|
if (!vinfo->isgraphic)
|
|
|
|
|
{
|
|
|
|
|
u32 addr =
|
|
|
|
|
(coordx << 1) + vinfo->currentpitch * coordy;
|
|
|
|
|
video_to_mem(addr, &thechar, 1);
|
|
|
|
|
}
|
|
|
|
|
return thechar;
|
2018-10-26 14:09:43 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
|
/* Retourne l'attribut du mode texte aux coordonn<6E>es sp<73>cifi<66>es */
|
|
|
|
|
|
2018-12-12 15:25:04 +01:00
|
|
|
|
u8 getattrib(u16 coordx, u16 coordy)
|
2018-10-26 14:09:43 +02:00
|
|
|
|
{
|
2018-12-12 15:25:04 +01:00
|
|
|
|
u8 attrib = 0;
|
|
|
|
|
if (!vinfo->isgraphic)
|
|
|
|
|
{
|
|
|
|
|
u32 addr =
|
|
|
|
|
(coordx << 1) + vinfo->currentpitch * coordy;
|
|
|
|
|
video_to_mem(addr + 1, &attrib, 1);
|
|
|
|
|
}
|
|
|
|
|
return attrib;
|
2018-10-26 14:09:43 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
|
/* Chargement d'une police de caract<63>re */
|
|
|
|
|
|
2018-12-12 15:25:04 +01:00
|
|
|
|
void loadfont(u8 * name, font * pointer, u8 width, u8 height)
|
2018-10-26 14:09:43 +02:00
|
|
|
|
{
|
2018-12-12 15:25:04 +01:00
|
|
|
|
u32 i;
|
|
|
|
|
for (i = 0; i < MAXFONTS; i++)
|
|
|
|
|
if (fonts[i].nom[0] != NULL && fonts[i].pointer == pointer)
|
|
|
|
|
return;
|
|
|
|
|
i = 0;
|
|
|
|
|
while (fonts[i].nom[0] != NULL && i < MAXFONTS)
|
|
|
|
|
i++;
|
|
|
|
|
fonts[i].pointer = pointer;
|
|
|
|
|
strcpy(name, fonts[i].nom);
|
|
|
|
|
fonts[i].width = width;
|
|
|
|
|
fonts[i].height = height;
|
|
|
|
|
if (fonts[i].nom[0] == 'B' && fonts[i].nom[1] == 'I'
|
|
|
|
|
&& fonts[i].nom[2] == 'O' && fonts[i].nom[3] == 'S')
|
|
|
|
|
{
|
|
|
|
|
u8 number = (fonts[i].nom[4] - '0');
|
|
|
|
|
font_load(pointer, height, number);
|
|
|
|
|
}
|
2018-10-26 14:09:43 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
|
/* Changement de la police */
|
|
|
|
|
|
2018-12-12 15:25:04 +01:00
|
|
|
|
void setfont(u8 * fontname)
|
2018-10-26 14:09:43 +02:00
|
|
|
|
{
|
2018-12-12 15:25:04 +01:00
|
|
|
|
u32 i = 0;
|
|
|
|
|
while (fonts[i].nom != NULL && i < MAXFONTS)
|
|
|
|
|
{
|
|
|
|
|
if (strcmp(fontname, fonts[i].nom) == 0)
|
|
|
|
|
{
|
|
|
|
|
currentfont = &fonts[i];
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
i++;
|
|
|
|
|
}
|
2018-10-12 20:37:26 +02:00
|
|
|
|
}
|
|
|
|
|
|
2018-10-26 14:09:43 +02:00
|
|
|
|
/******************************************************************************/
|
|
|
|
|
/* FONCTIONS VIDEO GRAPHIQUES */
|
|
|
|
|
|
2018-10-13 11:25:55 +02:00
|
|
|
|
/******************************************************************************/
|
|
|
|
|
/* Affiche un caract<63>re */
|
|
|
|
|
|
2018-12-12 15:25:04 +01:00
|
|
|
|
void showchar(u16 coordx, u16 coordy, u8 thechar, u8 attrib)
|
2018-10-12 20:37:26 +02:00
|
|
|
|
{
|
2018-12-12 15:25:04 +01:00
|
|
|
|
u8 x, y, pattern, set;
|
|
|
|
|
u32 color;
|
|
|
|
|
if (!vinfo->isgraphic)
|
|
|
|
|
{
|
|
|
|
|
u32 addr =
|
|
|
|
|
(coordx << 1) + vinfo->currentpitch * coordy;
|
|
|
|
|
mem_to_video(thechar, addr, 1, false);
|
|
|
|
|
mem_to_video(attrib, addr + 1, 1, false);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
for (y = 0; y < currentfont->height; y++)
|
|
|
|
|
{
|
|
|
|
|
pattern =
|
|
|
|
|
currentfont->pointer[currentfont->height *
|
|
|
|
|
thechar + y];
|
|
|
|
|
for (x = 0; x < currentfont->width; x++)
|
|
|
|
|
{
|
|
|
|
|
rol(pattern);
|
|
|
|
|
set = pattern & 0x1;
|
|
|
|
|
if (set == 0)
|
|
|
|
|
if (vinfo->currentdepth == 32)
|
|
|
|
|
color = egatorgb((attrib &
|
|
|
|
|
0xF0) >>
|
|
|
|
|
4);
|
|
|
|
|
else
|
|
|
|
|
color = egatovga((attrib &
|
|
|
|
|
0xF0) >>
|
|
|
|
|
4);
|
|
|
|
|
else if (vinfo->currentdepth == 32)
|
|
|
|
|
color = egatorgb(attrib & 0x0F);
|
|
|
|
|
else
|
|
|
|
|
color = egatovga(attrib & 0x0F);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
writepxl(currentfont->width * coordx + x +
|
|
|
|
|
1,
|
|
|
|
|
currentfont->height * coordy + y,
|
|
|
|
|
color);
|
|
|
|
|
}
|
2018-10-26 14:09:43 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
|
/* Affiche une ligne horizontale entre les points sp<73>cifi<66>s */
|
|
|
|
|
|
2018-11-08 22:12:51 +01:00
|
|
|
|
void hline(s16 x1, s16 x2, s16 y, u32 color)
|
2018-10-26 14:09:43 +02:00
|
|
|
|
{
|
2018-12-12 15:25:04 +01:00
|
|
|
|
if (vinfo->isgraphic)
|
|
|
|
|
{
|
|
|
|
|
if (x1 < 0)
|
|
|
|
|
{
|
|
|
|
|
if (x2 < 0)
|
|
|
|
|
return;
|
|
|
|
|
x1 = 0;
|
|
|
|
|
}
|
|
|
|
|
else if (x1 > vinfo->currentwidth)
|
|
|
|
|
x1 = vinfo->currentwidth - 1;
|
|
|
|
|
if (x2 < 0)
|
|
|
|
|
x2 = 0;
|
|
|
|
|
else if (x2 > vinfo->currentwidth)
|
|
|
|
|
{
|
|
|
|
|
if (x1 > vinfo->currentwidth)
|
|
|
|
|
return;
|
|
|
|
|
x2 = vinfo->currentwidth - 1;
|
|
|
|
|
}
|
|
|
|
|
if (x1 > vinfo->currentwidth)
|
|
|
|
|
x1 = vinfo->currentwidth - 1;
|
|
|
|
|
if (x2 > x1)
|
|
|
|
|
mem_to_video(color,
|
|
|
|
|
(vinfo->currentdepth >> 3) * x1 +
|
|
|
|
|
vinfo->currentpitch * y, x2 - x1,
|
|
|
|
|
false);
|
|
|
|
|
else
|
|
|
|
|
mem_to_video(color,
|
|
|
|
|
(vinfo->currentdepth >> 3) * x2 +
|
|
|
|
|
vinfo->currentpitch * y, x1 - x2,
|
|
|
|
|
false);
|
|
|
|
|
}
|
2018-10-26 14:09:43 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
|
/* Affiche un pixel <20> l'<27>cran */
|
|
|
|
|
|
2018-12-12 15:25:04 +01:00
|
|
|
|
void v_writepxl(vertex2d * A, u32 color)
|
2018-10-26 14:09:43 +02:00
|
|
|
|
{
|
2018-12-12 15:25:04 +01:00
|
|
|
|
writepxl(A->x, A->y, color);
|
2018-10-26 14:09:43 +02:00
|
|
|
|
}
|
|
|
|
|
|
2018-11-08 22:12:51 +01:00
|
|
|
|
void writepxl(s16 x, s16 y, u32 color)
|
2018-10-26 14:09:43 +02:00
|
|
|
|
{
|
2018-12-12 15:25:04 +01:00
|
|
|
|
if (vinfo->isgraphic)
|
|
|
|
|
{
|
|
|
|
|
if (x > 0 && y > 0 && x < vinfo->currentwidth
|
|
|
|
|
&& y < vinfo->currentheight)
|
|
|
|
|
{
|
|
|
|
|
u32 addr =
|
|
|
|
|
(vinfo->currentdepth >> 3) * x +
|
|
|
|
|
vinfo->currentpitch * y;
|
|
|
|
|
mem_to_video(color, addr, 1, false);
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-10-26 14:09:43 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
|
/* Affiche une ligne entre les points sp<73>cifi<66>s */
|
|
|
|
|
|
2018-12-12 15:25:04 +01:00
|
|
|
|
void v_line(vertex2d * A, vertex2d * B, u32 color)
|
2018-10-26 14:09:43 +02:00
|
|
|
|
{
|
|
|
|
|
line(A->x, A->y, B->x, B->y, color);
|
|
|
|
|
}
|
|
|
|
|
|
2018-11-08 22:12:51 +01:00
|
|
|
|
void line(s16 x1, s16 y1, s16 x2, s16 y2, u32 color)
|
2018-10-26 14:09:43 +02:00
|
|
|
|
{
|
2018-12-12 15:25:04 +01:00
|
|
|
|
s16 dx, dy, sdx, sdy;
|
|
|
|
|
float a, b;
|
|
|
|
|
s16 i, dxabs, dyabs, x, y, px, py;
|
2018-10-26 14:09:43 +02:00
|
|
|
|
|
|
|
|
|
dx = x2 - x1; /* distance horizontale de la line */
|
2018-11-08 22:12:51 +01:00
|
|
|
|
dy = y2 - y1; /* distance verticale de la line */
|
|
|
|
|
|
2018-12-12 15:25:04 +01:00
|
|
|
|
if (x1 < 0)
|
|
|
|
|
{
|
|
|
|
|
a = 1.0f * dy / dx;
|
|
|
|
|
b = y1 - a * x1;
|
|
|
|
|
x1 = 0;
|
|
|
|
|
y1 = b;
|
|
|
|
|
if (x2 < 0)
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
else if (x2 < 0)
|
|
|
|
|
{
|
|
|
|
|
a = 1.0f * dy / dx;
|
|
|
|
|
b = y2 - a * x2;
|
|
|
|
|
x2 = 0;
|
|
|
|
|
y2 = b;
|
|
|
|
|
}
|
|
|
|
|
if (y1 < 0)
|
|
|
|
|
{
|
|
|
|
|
a = 1.0f * dy / dx;
|
|
|
|
|
b = y1 - a * x1;
|
|
|
|
|
y1 = 0;
|
|
|
|
|
x1 = -b / a;
|
|
|
|
|
if (y2 < 0)
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
else if (y2 < 0)
|
|
|
|
|
{
|
|
|
|
|
a = 1.0f * dy / dx;
|
|
|
|
|
b = y2 - a * x2;
|
|
|
|
|
y2 = 0;
|
|
|
|
|
x2 = -b / a;
|
|
|
|
|
}
|
|
|
|
|
if (x1 > vinfo->currentwidth)
|
|
|
|
|
{
|
|
|
|
|
a = 1.0f * dy / dx;
|
|
|
|
|
b = y1 - a * x1;
|
|
|
|
|
x1 = vinfo->currentwidth - 1;
|
|
|
|
|
y1 = a * x1 + b;
|
|
|
|
|
if (x2 > vinfo->currentwidth)
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
else if (x2 > vinfo->currentwidth)
|
|
|
|
|
{
|
|
|
|
|
a = 1.0f * dy / dx;
|
|
|
|
|
b = y2 - a * x2;
|
|
|
|
|
x2 = vinfo->currentwidth - 1;
|
|
|
|
|
y2 = a * x2 + b;
|
|
|
|
|
}
|
|
|
|
|
if (y1 > vinfo->currentheight)
|
|
|
|
|
{
|
|
|
|
|
a = 1.0f * dy / dx;
|
|
|
|
|
b = y1 - a * x1;
|
|
|
|
|
y1 = vinfo->currentheight - 1;
|
|
|
|
|
x1 = (y1 - b) / a;
|
|
|
|
|
if (y2 > vinfo->currentheight)
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
else if (y2 > vinfo->currentheight)
|
|
|
|
|
{
|
|
|
|
|
a = 1.0f * dy / dx;
|
|
|
|
|
b = y2 - a * x2;
|
|
|
|
|
y2 = vinfo->currentheight - 1;
|
|
|
|
|
x2 = (y2 - b) / a;
|
|
|
|
|
}
|
2018-10-26 14:09:43 +02:00
|
|
|
|
dxabs = abs(dx);
|
|
|
|
|
dyabs = abs(dy);
|
|
|
|
|
sdx = sgn(dx);
|
|
|
|
|
sdy = sgn(dy);
|
|
|
|
|
x = dyabs >> 1;
|
|
|
|
|
y = dxabs >> 1;
|
|
|
|
|
px = x1;
|
|
|
|
|
py = y1;
|
|
|
|
|
|
|
|
|
|
writepxl(px, py, color);
|
|
|
|
|
|
2018-12-12 15:25:04 +01:00
|
|
|
|
if (dxabs >= dyabs)
|
|
|
|
|
{ /* la ligne est plus horizontale que verticale */
|
|
|
|
|
for (i = 0; i < dxabs; i++)
|
|
|
|
|
{
|
2018-10-26 14:09:43 +02:00
|
|
|
|
y += dyabs;
|
2018-12-12 15:25:04 +01:00
|
|
|
|
if (y >= dxabs)
|
|
|
|
|
{
|
2018-10-26 14:09:43 +02:00
|
|
|
|
y -= dxabs;
|
|
|
|
|
py += sdy;
|
|
|
|
|
}
|
|
|
|
|
px += sdx;
|
|
|
|
|
writepxl(px, py, color);
|
|
|
|
|
}
|
2018-12-12 15:25:04 +01:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{ /* la ligne est plus verticale que horizontale */
|
2018-10-26 14:09:43 +02:00
|
|
|
|
|
2018-12-12 15:25:04 +01:00
|
|
|
|
for (i = 0; i < dyabs; i++)
|
|
|
|
|
{
|
2018-10-26 14:09:43 +02:00
|
|
|
|
x += dxabs;
|
2018-12-12 15:25:04 +01:00
|
|
|
|
if (x >= dyabs)
|
|
|
|
|
{
|
2018-10-26 14:09:43 +02:00
|
|
|
|
x -= dyabs;
|
|
|
|
|
px += sdx;
|
|
|
|
|
}
|
|
|
|
|
py += sdy;
|
|
|
|
|
writepxl(px, py, color);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
|
/* Affiche un triangle rempli entre les points sp<73>cifi<66>s */
|
|
|
|
|
|
|
|
|
|
void trianglefilled(vertex2d * AA, vertex2d * BB, vertex2d * CC, u32 color)
|
|
|
|
|
{
|
|
|
|
|
vertex2d *A, *B, *C, *TEMP;
|
2018-12-12 15:25:04 +01:00
|
|
|
|
u32 a, b, y, last;
|
|
|
|
|
int dx1, dx2, dx3, dy1, dy2, dy3, sa, sb;
|
2018-10-26 14:09:43 +02:00
|
|
|
|
A = AA;
|
|
|
|
|
B = BB;
|
|
|
|
|
C = CC;
|
2018-12-12 15:25:04 +01:00
|
|
|
|
while (A->y > B->y || B->y > C->y || A->y == C->y)
|
|
|
|
|
{
|
2018-10-26 14:09:43 +02:00
|
|
|
|
if (A->y > B->y)
|
|
|
|
|
swapvertex(A, B);
|
|
|
|
|
if (B->y > C->y)
|
|
|
|
|
swapvertex(B, C);
|
|
|
|
|
if (A->y > C->y)
|
|
|
|
|
swapvertex(A, C);
|
|
|
|
|
}
|
2018-12-12 15:25:04 +01:00
|
|
|
|
if (A->y == C->y)
|
|
|
|
|
{ //meme ligne
|
2018-10-26 14:09:43 +02:00
|
|
|
|
a = b = A->x;
|
|
|
|
|
if (B->x < a)
|
|
|
|
|
a = B->x;
|
|
|
|
|
else if (B->x > b)
|
|
|
|
|
b = B->x;
|
|
|
|
|
if (C->x < a)
|
|
|
|
|
a = C->x;
|
|
|
|
|
else if (C->x > b)
|
|
|
|
|
b = C->x;
|
|
|
|
|
hline(a, b, A->y, color);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
dx1 = B->x - A->x;
|
|
|
|
|
dy1 = B->y - A->y;
|
|
|
|
|
dx2 = C->x - A->x;
|
|
|
|
|
dy2 = C->y - A->y;
|
|
|
|
|
dx3 = C->x - B->x;
|
|
|
|
|
dy3 = C->y - B->y;
|
|
|
|
|
sa = 0;
|
|
|
|
|
sb = 0;
|
|
|
|
|
|
|
|
|
|
if (B->y == C->y)
|
|
|
|
|
last = B->y;
|
|
|
|
|
else
|
|
|
|
|
last = B->y - 1;
|
|
|
|
|
|
2018-12-12 15:25:04 +01:00
|
|
|
|
for (y = A->y; y <= last; y++)
|
|
|
|
|
{
|
2018-10-26 14:09:43 +02:00
|
|
|
|
a = A->x + sa / dy1;
|
|
|
|
|
b = A->x + sb / dy2;
|
|
|
|
|
sa += dx1;
|
|
|
|
|
sb += dx2;
|
|
|
|
|
hline(a, b, y, color);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sa = dx3 * (y - B->y);
|
|
|
|
|
sb = dx2 * (y - A->y);
|
2018-12-12 15:25:04 +01:00
|
|
|
|
for (; y <= C->y; y++)
|
|
|
|
|
{
|
2018-10-26 14:09:43 +02:00
|
|
|
|
a = B->x + sa / dy3;
|
|
|
|
|
b = A->x + sb / dy2;
|
|
|
|
|
sa += dx3;
|
|
|
|
|
sb += dx2;
|
|
|
|
|
hline(a, b, y, color);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void swapvertex(vertex2d * A, vertex2d * B)
|
|
|
|
|
{
|
|
|
|
|
vertex2d temp = *A;
|
|
|
|
|
*A = *B;
|
|
|
|
|
*B = temp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
|
/* Affiche un triangle entre les points sp<73>cifi<66>s */
|
|
|
|
|
|
|
|
|
|
void triangle(vertex2d * AA, vertex2d * BB, vertex2d * CC, u32 color)
|
|
|
|
|
{
|
|
|
|
|
v_line(AA, BB, color);
|
|
|
|
|
v_line(BB, CC, color);
|
|
|
|
|
v_line(CC, AA, color);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
|
/* FONCTIONS VIDEO TEXTE AFFICHAGE */
|
|
|
|
|
|
|
|
|
|
/*******************************************************************************/
|
|
|
|
|
/* affiche une chaine de caract<63>re a l'<27>cran */
|
2018-12-14 01:06:37 +01:00
|
|
|
|
/* SYSCALL
|
|
|
|
|
{
|
|
|
|
|
"ID":2,
|
|
|
|
|
"LIBRARY":"libvideo",
|
|
|
|
|
"NAME":"print",
|
|
|
|
|
"INTERNALNAME":"print",
|
|
|
|
|
"DESCRIPTION":"Show a string on the screen",
|
|
|
|
|
"ARGS": [
|
|
|
|
|
{"TYPE":"u8*","NAME":"string","DESCRIPTION":"string to show in ascii format"}
|
|
|
|
|
],
|
|
|
|
|
"RETURN":"u32"
|
|
|
|
|
}
|
2018-12-27 14:24:47 +01:00
|
|
|
|
END-SYSCALL */
|
2018-10-26 14:09:43 +02:00
|
|
|
|
|
|
|
|
|
u32 print(u8 * string)
|
|
|
|
|
{
|
2018-12-12 15:25:04 +01:00
|
|
|
|
u8 *source;
|
|
|
|
|
u32 i = 0;
|
2018-10-26 14:09:43 +02:00
|
|
|
|
source = string;
|
2018-12-12 15:25:04 +01:00
|
|
|
|
while (*source != 0)
|
|
|
|
|
{
|
2018-10-26 14:09:43 +02:00
|
|
|
|
putchar(*source++);
|
|
|
|
|
i++;
|
|
|
|
|
}
|
|
|
|
|
return i;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*******************************************************************************/
|
|
|
|
|
/* Fonction d'affichage (pour printf) */
|
|
|
|
|
|
2018-12-12 15:25:04 +01:00
|
|
|
|
u32 printstr(u8 * src, u8 ** dest, u32 len)
|
|
|
|
|
{
|
|
|
|
|
if (*(src) == '\000')
|
|
|
|
|
return;
|
|
|
|
|
for (u32 i = 0; i < len; i++)
|
2018-10-26 14:09:43 +02:00
|
|
|
|
putchar(*(src++));
|
|
|
|
|
return len;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*******************************************************************************/
|
|
|
|
|
/* Fonction d'enregistrement dans une variable (pour sprintf) */
|
|
|
|
|
|
2018-12-12 15:25:04 +01:00
|
|
|
|
u32 storestr(u8 * src, u8 ** dest, u32 len)
|
|
|
|
|
{
|
|
|
|
|
memcpy(src, *dest, len, 1);
|
|
|
|
|
*dest = *dest + len;
|
|
|
|
|
return len;
|
2018-10-26 14:09:43 +02:00
|
|
|
|
}
|
|
|
|
|
|
2018-12-27 14:24:47 +01:00
|
|
|
|
/* EXPORT
|
|
|
|
|
{
|
|
|
|
|
"LIBRARY":"libsys"
|
|
|
|
|
}
|
|
|
|
|
*/
|
2018-10-26 14:09:43 +02:00
|
|
|
|
#define maxbuffersize 4096
|
|
|
|
|
|
|
|
|
|
/*******************************************************************************/
|
|
|
|
|
/* affiche une chaine de caract<63>re format<61> a l'ecran */
|
|
|
|
|
|
|
|
|
|
u32 printf(const u8 * string, ...)
|
|
|
|
|
{
|
|
|
|
|
va_list args;
|
|
|
|
|
va_start(args, string);
|
2018-12-12 15:25:04 +01:00
|
|
|
|
vprintf(string, args);
|
|
|
|
|
va_end(args);
|
2018-10-26 14:09:43 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*******************************************************************************/
|
|
|
|
|
/* met une chaine de caract<63>re format<61> dans une variable */
|
|
|
|
|
|
2018-12-12 15:25:04 +01:00
|
|
|
|
u32 sprintf(u8 * variable, const u8 * string, ...)
|
2018-10-26 14:09:43 +02:00
|
|
|
|
{
|
|
|
|
|
va_list args;
|
|
|
|
|
va_start(args, string);
|
2018-12-12 15:25:04 +01:00
|
|
|
|
vsprintf(variable, string, args);
|
|
|
|
|
va_end(args);
|
2018-10-26 14:09:43 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*******************************************************************************/
|
|
|
|
|
/* met une chaine de caract<63>re format<61> dans une variable de taille fix<69>e */
|
|
|
|
|
|
2018-12-12 15:25:04 +01:00
|
|
|
|
u32 snprintf(u8 * variable, u32 maxsize, const u8 * string, ...)
|
2018-10-26 14:09:43 +02:00
|
|
|
|
{
|
|
|
|
|
va_list args;
|
|
|
|
|
va_start(args, string);
|
2018-12-12 15:25:04 +01:00
|
|
|
|
vsnprintf(variable, maxsize, string, args);
|
|
|
|
|
va_end(args);
|
2018-10-26 14:09:43 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*******************************************************************************/
|
|
|
|
|
/* affiche une chaine de caract<63>re format<61> a l'ecran depuis vararg */
|
|
|
|
|
|
|
|
|
|
u32 vprintf(const u8 * string, va_list args)
|
|
|
|
|
{
|
2018-12-12 15:25:04 +01:00
|
|
|
|
format(string, args, maxbuffersize, &printstr, NULL);
|
2018-10-26 14:09:43 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*******************************************************************************/
|
|
|
|
|
/* met une chaine de caract<63>re format<61> dans une variable depuis vararg */
|
|
|
|
|
|
2018-12-12 15:25:04 +01:00
|
|
|
|
u32 vsprintf(u8 * variable, const u8 * string, va_list args)
|
2018-10-26 14:09:43 +02:00
|
|
|
|
{
|
2018-12-12 15:25:04 +01:00
|
|
|
|
format(string, args, maxbuffersize, &storestr, variable);
|
2018-10-26 14:09:43 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*******************************************************************************/
|
|
|
|
|
/* met une chaine de caract<63>re format<61> dans une variable de taille fix<69>e depuis vararg */
|
|
|
|
|
|
2018-12-12 15:25:04 +01:00
|
|
|
|
u32 vsnprintf(u8 * variable, u32 maxsize, const u8 * string, va_list args)
|
2018-10-26 14:09:43 +02:00
|
|
|
|
{
|
2018-12-12 15:25:04 +01:00
|
|
|
|
format(string, args, maxsize, &storestr, variable);
|
2018-10-26 14:09:43 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*******************************************************************************/
|
|
|
|
|
/* affiche une chaine de caract<63>re format<61> a l'ecran */
|
|
|
|
|
|
2018-12-12 15:25:04 +01:00
|
|
|
|
u32 format(const u8 * string, va_list args, u32 maxsize,
|
|
|
|
|
u32(*fonction) (u8 * src, u8 ** dest, u32 len), u8 * dest)
|
2018-10-26 14:09:43 +02:00
|
|
|
|
{
|
2018-12-12 15:25:04 +01:00
|
|
|
|
u64 sizes[] = { 0xFF, 0xFFFF, 0xFFFFFFFF, 0xFFFFFFFFFFFFFFFF };
|
|
|
|
|
u8 units[][4] =
|
|
|
|
|
{ "o\000\000", "kio", "mio", "gio", "tio", "pio" };
|
|
|
|
|
u8 strbase2[] = "0xb\000";
|
|
|
|
|
u8 strbase8[] = "0xo\000";
|
|
|
|
|
u8 strbase16[] = "0x\000";
|
|
|
|
|
u8 hexadecimal[] = "*0x\000";
|
|
|
|
|
u8 achar, temp;
|
2018-12-27 14:24:47 +01:00
|
|
|
|
u8 asize=2;
|
|
|
|
|
u8 charadd=0xFF;
|
|
|
|
|
u8 unit = 0;
|
|
|
|
|
u8 precisioni = 0;
|
|
|
|
|
u8 precisionf = 0;
|
2018-12-12 15:25:04 +01:00
|
|
|
|
u8 buffer[maxbuffersize];
|
|
|
|
|
u8 *bufferend;
|
|
|
|
|
u32 buffersize;
|
|
|
|
|
u8 *str = string;
|
|
|
|
|
u8 *strtemp;
|
|
|
|
|
u32 i = 0, counter = 0;
|
2018-12-27 14:24:47 +01:00
|
|
|
|
u64 num = 0;
|
2018-12-12 15:25:04 +01:00
|
|
|
|
bool flag = false, intok = false, decok = false;
|
|
|
|
|
|
|
|
|
|
for (achar = *str; achar != '\000'; i++, achar = *(str + i))
|
|
|
|
|
{
|
|
|
|
|
if (achar != '%' && !flag)
|
|
|
|
|
{
|
|
|
|
|
fonction((str + i), &dest, 1);
|
2018-10-26 14:09:43 +02:00
|
|
|
|
counter++;
|
|
|
|
|
asize = 2;
|
2018-12-12 15:25:04 +01:00
|
|
|
|
precisioni = 0;
|
|
|
|
|
precisionf = 0;
|
|
|
|
|
intok = false;
|
|
|
|
|
decok = false;
|
2018-10-26 14:09:43 +02:00
|
|
|
|
charadd = 0xFF;
|
2018-12-12 15:25:04 +01:00
|
|
|
|
}
|
|
|
|
|
else if (achar == '%' || flag)
|
|
|
|
|
{
|
2018-10-26 14:09:43 +02:00
|
|
|
|
if (!flag)
|
|
|
|
|
++i;
|
|
|
|
|
achar = *(str + i);
|
2018-12-12 15:25:04 +01:00
|
|
|
|
switch (achar)
|
|
|
|
|
{
|
|
|
|
|
case 'z':
|
|
|
|
|
charadd = achar;
|
|
|
|
|
flag = true;
|
|
|
|
|
break;
|
|
|
|
|
case ' ':
|
|
|
|
|
charadd = achar;
|
|
|
|
|
flag = true;
|
|
|
|
|
break;
|
|
|
|
|
case 'h':
|
|
|
|
|
asize--;
|
|
|
|
|
if (asize < 0)
|
|
|
|
|
asize = 0;
|
|
|
|
|
flag = true;
|
|
|
|
|
break;
|
|
|
|
|
case 'l':
|
|
|
|
|
asize++;
|
|
|
|
|
if (asize > 3)
|
|
|
|
|
asize = 3;
|
|
|
|
|
flag = true;
|
|
|
|
|
break;
|
|
|
|
|
case '.':
|
|
|
|
|
intok = true;
|
|
|
|
|
decok = false;
|
|
|
|
|
flag = true;
|
|
|
|
|
break;
|
|
|
|
|
case '0':
|
|
|
|
|
case '1':
|
|
|
|
|
case '2':
|
|
|
|
|
case '3':
|
|
|
|
|
case '4':
|
|
|
|
|
case '5':
|
|
|
|
|
case '6':
|
|
|
|
|
case '7':
|
|
|
|
|
case '8':
|
|
|
|
|
case '9':
|
|
|
|
|
if (!intok)
|
|
|
|
|
{
|
|
|
|
|
if (!decok)
|
|
|
|
|
{
|
|
|
|
|
precisioni =
|
|
|
|
|
achar -
|
|
|
|
|
'0';
|
|
|
|
|
decok = true;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
precisioni *= 10;
|
|
|
|
|
precisioni +=
|
|
|
|
|
achar -
|
|
|
|
|
'0';
|
|
|
|
|
decok = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (!decok)
|
|
|
|
|
{
|
|
|
|
|
precisionf =
|
|
|
|
|
achar -
|
|
|
|
|
'0';
|
|
|
|
|
decok = true;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
precisionf *= 10;
|
|
|
|
|
precisionf +=
|
|
|
|
|
achar -
|
|
|
|
|
'0';
|
|
|
|
|
decok = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
flag = true;
|
|
|
|
|
break;
|
|
|
|
|
case 'f':
|
|
|
|
|
case 'e':
|
|
|
|
|
if (achar == 'e')
|
|
|
|
|
{
|
|
|
|
|
precisioni = 1;
|
|
|
|
|
precisionf = 8;
|
|
|
|
|
}
|
|
|
|
|
if (asize == 0)
|
|
|
|
|
{
|
|
|
|
|
num = (u64) va_arg(args,
|
|
|
|
|
u8);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
else if (asize == 1)
|
|
|
|
|
{
|
|
|
|
|
num = (u64) va_arg(args,
|
|
|
|
|
u16);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
else if (asize == 2)
|
|
|
|
|
bufferend =
|
|
|
|
|
rtoasingle((float)
|
|
|
|
|
va_arg
|
|
|
|
|
(args,
|
|
|
|
|
double),
|
|
|
|
|
&buffer,
|
|
|
|
|
precisioni,
|
|
|
|
|
precisionf);
|
|
|
|
|
else
|
|
|
|
|
bufferend =
|
|
|
|
|
rtoadouble((double)
|
|
|
|
|
va_arg
|
|
|
|
|
(args,
|
|
|
|
|
double),
|
|
|
|
|
&buffer,
|
|
|
|
|
precisioni,
|
|
|
|
|
precisionf);
|
|
|
|
|
buffersize =
|
|
|
|
|
bufferend - &buffer[0];
|
|
|
|
|
counter +=
|
|
|
|
|
fonction(&buffer, &dest,
|
|
|
|
|
buffersize);
|
|
|
|
|
flag = false;
|
|
|
|
|
break;
|
|
|
|
|
case 'u':
|
|
|
|
|
if (asize == 0)
|
|
|
|
|
num = (u64) va_arg(args,
|
|
|
|
|
u8);
|
|
|
|
|
else if (asize == 1)
|
|
|
|
|
num = (u64) va_arg(args,
|
|
|
|
|
u16);
|
|
|
|
|
else if (asize == 2)
|
|
|
|
|
num = (u64) va_arg(args,
|
|
|
|
|
u32);
|
|
|
|
|
else
|
|
|
|
|
num = (u64) va_arg(args,
|
|
|
|
|
u64);
|
|
|
|
|
if (charadd == 0xFF)
|
|
|
|
|
charadd = '0';
|
|
|
|
|
bufferend =
|
|
|
|
|
itoa(num, &buffer, 10,
|
|
|
|
|
sizes[asize],
|
|
|
|
|
charadd);
|
|
|
|
|
buffersize =
|
|
|
|
|
bufferend - &buffer[0];
|
|
|
|
|
counter +=
|
|
|
|
|
fonction(&buffer, &dest,
|
|
|
|
|
buffersize);
|
|
|
|
|
flag = false;
|
|
|
|
|
break;
|
|
|
|
|
case 'o':
|
|
|
|
|
if (asize == 0)
|
|
|
|
|
num = (u64) va_arg(args,
|
|
|
|
|
u8);
|
|
|
|
|
else if (asize == 1)
|
|
|
|
|
num = (u64) va_arg(args,
|
|
|
|
|
u16);
|
|
|
|
|
else if (asize == 2)
|
|
|
|
|
num = (u64) va_arg(args,
|
|
|
|
|
u32);
|
|
|
|
|
else
|
|
|
|
|
num = (u64) va_arg(args,
|
|
|
|
|
u64);
|
|
|
|
|
if (charadd == 0xFF)
|
|
|
|
|
charadd = '0';
|
|
|
|
|
counter +=
|
|
|
|
|
fonction(&strbase8, &dest,
|
|
|
|
|
1);
|
|
|
|
|
bufferend =
|
|
|
|
|
itoa(num, &buffer, 8,
|
|
|
|
|
sizes[asize],
|
|
|
|
|
charadd);
|
|
|
|
|
buffersize =
|
|
|
|
|
bufferend - &buffer[0];
|
|
|
|
|
counter +=
|
|
|
|
|
fonction(&buffer, &dest,
|
|
|
|
|
buffersize);
|
|
|
|
|
flag = false;
|
|
|
|
|
break;
|
|
|
|
|
case '%':
|
|
|
|
|
fonction(&achar, string, 1);
|
|
|
|
|
counter++;
|
|
|
|
|
flag = false;
|
|
|
|
|
break;
|
|
|
|
|
case 'c':
|
|
|
|
|
temp = (u8) va_arg(args, u8);
|
|
|
|
|
fonction(&temp, string, 1);
|
|
|
|
|
counter++;
|
|
|
|
|
flag = false;
|
|
|
|
|
break;
|
|
|
|
|
case 'H':
|
|
|
|
|
if (asize == 0)
|
|
|
|
|
num = (u64) va_arg(args,
|
|
|
|
|
u8);
|
|
|
|
|
else if (asize == 1)
|
|
|
|
|
num = (u64) va_arg(args,
|
|
|
|
|
u16);
|
|
|
|
|
else if (asize == 2)
|
|
|
|
|
num = (u64) va_arg(args,
|
|
|
|
|
u32);
|
|
|
|
|
else
|
|
|
|
|
num = (u64) va_arg(args,
|
|
|
|
|
u64);
|
|
|
|
|
if (charadd == 0xFF)
|
|
|
|
|
charadd = ' ';
|
|
|
|
|
while (num > 1024 * 10)
|
|
|
|
|
{
|
|
|
|
|
num = num >> 10;
|
|
|
|
|
unit++;
|
|
|
|
|
}
|
|
|
|
|
bufferend =
|
|
|
|
|
sitoa(num, &buffer,
|
|
|
|
|
sizes[asize]);
|
|
|
|
|
buffersize =
|
|
|
|
|
bufferend - &buffer[0];
|
|
|
|
|
counter +=
|
|
|
|
|
fonction(&buffer, &dest,
|
|
|
|
|
buffersize);
|
|
|
|
|
counter +=
|
|
|
|
|
fonction(&units[unit],
|
|
|
|
|
&dest, 3);
|
|
|
|
|
flag = false;
|
|
|
|
|
break;
|
|
|
|
|
case 'd':
|
|
|
|
|
case 'i':
|
|
|
|
|
if (asize == 0)
|
|
|
|
|
num = (u64) va_arg(args,
|
|
|
|
|
u8);
|
|
|
|
|
else if (asize == 1)
|
|
|
|
|
num = (u64) va_arg(args,
|
|
|
|
|
u16);
|
|
|
|
|
else if (asize == 2)
|
|
|
|
|
num = (u64) va_arg(args,
|
|
|
|
|
u32);
|
|
|
|
|
else
|
|
|
|
|
num = (u64) va_arg(args,
|
|
|
|
|
u64);
|
|
|
|
|
if (charadd == 0xFF)
|
|
|
|
|
charadd = ' ';
|
|
|
|
|
bufferend =
|
|
|
|
|
sitoa(num, &buffer,
|
|
|
|
|
sizes[asize]);
|
|
|
|
|
buffersize =
|
|
|
|
|
bufferend - &buffer[0];
|
|
|
|
|
counter +=
|
|
|
|
|
fonction(&buffer, &dest,
|
|
|
|
|
buffersize);
|
|
|
|
|
flag = false;
|
|
|
|
|
break;
|
|
|
|
|
case 's':
|
|
|
|
|
strtemp =
|
|
|
|
|
(u8 *) va_arg(args, u8 *);
|
|
|
|
|
counter +=
|
|
|
|
|
fonction(strtemp, &dest,
|
|
|
|
|
strlen(strtemp));
|
|
|
|
|
flag = false;
|
|
|
|
|
break;
|
|
|
|
|
case 'p':
|
|
|
|
|
num = (u32) va_arg(args, int);
|
|
|
|
|
if (charadd == 0xFF)
|
|
|
|
|
charadd = '0';
|
|
|
|
|
counter +=
|
|
|
|
|
fonction(&hexadecimal,
|
|
|
|
|
&dest, 3);
|
|
|
|
|
bufferend =
|
|
|
|
|
itoa(num, &buffer, 16,
|
|
|
|
|
sizes[asize], '0');
|
|
|
|
|
buffersize =
|
|
|
|
|
bufferend - &buffer[0];
|
|
|
|
|
counter +=
|
|
|
|
|
fonction(&buffer, &dest,
|
|
|
|
|
buffersize);
|
|
|
|
|
flag = false;
|
|
|
|
|
break;
|
|
|
|
|
case 'x':
|
|
|
|
|
case 'X':
|
|
|
|
|
case 'y':
|
|
|
|
|
case 'Y':
|
|
|
|
|
if (asize == 0)
|
|
|
|
|
num = (u64) va_arg(args,
|
|
|
|
|
u8);
|
|
|
|
|
else if (asize == 1)
|
|
|
|
|
num = (u64) va_arg(args,
|
|
|
|
|
u16);
|
|
|
|
|
else if (asize == 2)
|
|
|
|
|
num = (u64) va_arg(args,
|
|
|
|
|
u32);
|
|
|
|
|
else
|
|
|
|
|
num = (u64) va_arg(args,
|
|
|
|
|
u64);
|
|
|
|
|
if (charadd == 0xFF)
|
|
|
|
|
charadd = '0';
|
|
|
|
|
if (achar == 'X')
|
|
|
|
|
counter +=
|
|
|
|
|
fonction
|
|
|
|
|
(&strbase16, &dest,
|
|
|
|
|
2);
|
|
|
|
|
bufferend =
|
|
|
|
|
itoa(num, &buffer, 16,
|
|
|
|
|
sizes[asize],
|
|
|
|
|
charadd);
|
|
|
|
|
buffersize =
|
|
|
|
|
bufferend - &buffer[0];
|
|
|
|
|
if (achar == 'X' || achar == 'Y')
|
|
|
|
|
strtoupper(&buffer);
|
|
|
|
|
counter +=
|
|
|
|
|
fonction(&buffer, &dest,
|
|
|
|
|
buffersize);
|
|
|
|
|
flag = false;
|
|
|
|
|
break;
|
|
|
|
|
case 'b':
|
|
|
|
|
if (asize == 0)
|
|
|
|
|
num = (u64) va_arg(args,
|
|
|
|
|
u8);
|
|
|
|
|
else if (asize == 1)
|
|
|
|
|
num = (u64) va_arg(args,
|
|
|
|
|
u16);
|
|
|
|
|
else if (asize == 2)
|
|
|
|
|
num = (u64) va_arg(args,
|
|
|
|
|
u32);
|
|
|
|
|
else
|
|
|
|
|
num = (u64) va_arg(args,
|
|
|
|
|
u64);
|
|
|
|
|
if (charadd == 0xFF)
|
|
|
|
|
charadd = '0';
|
|
|
|
|
counter +=
|
|
|
|
|
fonction(&strbase2, &dest,
|
|
|
|
|
2);
|
|
|
|
|
bufferend =
|
|
|
|
|
itoa(num, &buffer, 2,
|
|
|
|
|
sizes[asize],
|
|
|
|
|
charadd);
|
|
|
|
|
buffersize =
|
|
|
|
|
bufferend - &buffer[0];
|
|
|
|
|
counter +=
|
|
|
|
|
fonction(&buffer, &dest,
|
|
|
|
|
buffersize);
|
|
|
|
|
flag = false;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
2018-10-26 14:09:43 +02:00
|
|
|
|
}
|
2018-10-13 11:25:55 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
2018-12-12 15:25:04 +01:00
|
|
|
|
buffer[0] = '\000';
|
|
|
|
|
fonction(&buffer, &dest, 1);
|
2018-10-26 14:09:43 +02:00
|
|
|
|
return counter;
|
2018-10-12 20:37:26 +02:00
|
|
|
|
}
|
|
|
|
|
|
2018-10-26 14:09:43 +02:00
|
|
|
|
/*******************************************************************************/
|
|
|
|
|
/* converti un r<>el sign<67> en chaine de caract<63>re */
|
2018-10-12 20:37:26 +02:00
|
|
|
|
|
2018-12-12 15:25:04 +01:00
|
|
|
|
u8 *rtoadouble(double num, u8 * str, u8 precisioni, u8 precisionf)
|
2018-10-12 20:37:26 +02:00
|
|
|
|
{
|
2018-12-12 15:25:04 +01:00
|
|
|
|
s8 power10;
|
|
|
|
|
u8 *pointer = str;
|
|
|
|
|
u8 i, j, integerpart, fracpart;
|
|
|
|
|
if (precisioni == 0)
|
|
|
|
|
precisioni = 12;
|
|
|
|
|
if (precisionf == 0)
|
|
|
|
|
precisionf = 8;
|
|
|
|
|
double round = 0.5;
|
|
|
|
|
for (i = 0; i < precisionf; i++)
|
|
|
|
|
round /= 10;
|
|
|
|
|
num += round;
|
|
|
|
|
bool intok = false;
|
|
|
|
|
if (num < 0)
|
|
|
|
|
{
|
|
|
|
|
num = -num;
|
|
|
|
|
*(pointer++) = '-';
|
|
|
|
|
}
|
|
|
|
|
power10 = 0;
|
|
|
|
|
{
|
|
|
|
|
while (num >= 10.0)
|
|
|
|
|
{
|
|
|
|
|
num /= 10;
|
|
|
|
|
power10++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (power10 < precisioni)
|
|
|
|
|
{
|
|
|
|
|
fracpart = power10;
|
|
|
|
|
power10 = 0;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
fracpart = precisioni;
|
|
|
|
|
power10 = power10 - precisioni + 1;
|
|
|
|
|
}
|
|
|
|
|
if (power10 == 0)
|
|
|
|
|
{
|
|
|
|
|
if (num != 0.0)
|
|
|
|
|
{
|
|
|
|
|
while (num < 1.0)
|
|
|
|
|
{
|
|
|
|
|
num *= 10;
|
|
|
|
|
power10--;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
i = j = 0;
|
|
|
|
|
while (num > 0)
|
|
|
|
|
{
|
|
|
|
|
if (!intok & (i > fracpart || i >= precisioni))
|
|
|
|
|
{
|
|
|
|
|
*(pointer++) = '.';
|
|
|
|
|
intok = true;
|
|
|
|
|
}
|
|
|
|
|
if (intok && j >= precisionf)
|
|
|
|
|
break;
|
|
|
|
|
num -= (integerpart = num);
|
|
|
|
|
*(pointer++) = integerpart + '0';
|
|
|
|
|
num *= 10.0;
|
|
|
|
|
if (!intok)
|
|
|
|
|
i++;
|
|
|
|
|
else
|
|
|
|
|
j++;
|
|
|
|
|
}
|
|
|
|
|
while ((*(pointer - 1)) == '0' && pointer > str + 1)
|
|
|
|
|
pointer--;
|
|
|
|
|
if ((*(pointer - 1)) == '.')
|
|
|
|
|
pointer--;
|
|
|
|
|
if (abs(power10) > 0)
|
|
|
|
|
{
|
|
|
|
|
*(pointer++) = 'e';
|
|
|
|
|
if (power10 < 0)
|
|
|
|
|
{
|
|
|
|
|
power10 = -power10;
|
|
|
|
|
*(pointer++) = '-';
|
|
|
|
|
}
|
|
|
|
|
*(pointer++) = (power10 / 10 + '0');
|
|
|
|
|
*(pointer++) = (power10 % 10 + '0');
|
|
|
|
|
}
|
|
|
|
|
*(pointer++) = 0;
|
2018-10-13 11:25:55 +02:00
|
|
|
|
}
|
|
|
|
|
|
2018-10-26 14:09:43 +02:00
|
|
|
|
/*******************************************************************************/
|
|
|
|
|
/* converti un r<>el sign<67> en chaine de caract<63>re */
|
2018-10-12 20:37:26 +02:00
|
|
|
|
|
2018-12-12 15:25:04 +01:00
|
|
|
|
u8 *rtoasingle(float num, u8 * str, u8 precisioni, u8 precisionf)
|
|
|
|
|
{
|
|
|
|
|
return rtoadouble((double) num, str, precisioni, precisionf);
|
2018-10-12 20:37:26 +02:00
|
|
|
|
}
|
2018-10-13 11:25:55 +02:00
|
|
|
|
|
2018-10-26 14:09:43 +02:00
|
|
|
|
/*******************************************************************************/
|
|
|
|
|
/* converti un entier non sign<67> en chaine de caract<63>re */
|
2018-10-14 19:14:19 +02:00
|
|
|
|
|
2018-12-12 15:25:04 +01:00
|
|
|
|
u8 *itoa(u64 orignum, u8 * str, u8 base, u64 dim, u8 achar)
|
2018-10-14 19:14:19 +02:00
|
|
|
|
{
|
2018-12-12 15:25:04 +01:00
|
|
|
|
u8 *pointer = str, i, size = 0;
|
|
|
|
|
u64 num = orignum;
|
|
|
|
|
if (dim >= 0xFF)
|
|
|
|
|
{
|
|
|
|
|
num &= dim;
|
|
|
|
|
if ((num == 0) && (achar == 0))
|
|
|
|
|
{
|
|
|
|
|
*(pointer++) = '0';
|
|
|
|
|
*pointer = '\000';
|
|
|
|
|
return pointer;
|
|
|
|
|
}
|
|
|
|
|
switch (base)
|
|
|
|
|
{
|
|
|
|
|
case 2:
|
|
|
|
|
size = log2(dim);
|
|
|
|
|
break;
|
|
|
|
|
case 8:
|
|
|
|
|
size = log2(dim) / 2;
|
|
|
|
|
break;
|
|
|
|
|
case 10:
|
|
|
|
|
size = log10(dim);
|
|
|
|
|
break;
|
|
|
|
|
case 16:
|
|
|
|
|
size = log2(dim) / 4;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
size = dim;
|
|
|
|
|
for (i = 0; i < size; i++)
|
|
|
|
|
{
|
|
|
|
|
if (num == 0)
|
|
|
|
|
{
|
|
|
|
|
if (i == 0)
|
|
|
|
|
*(pointer++) = '0';
|
|
|
|
|
else
|
|
|
|
|
*(pointer++) = achar;
|
|
|
|
|
if (achar == 0)
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
u64 result = num % (u32) base;
|
|
|
|
|
*(pointer++) =
|
|
|
|
|
(result >
|
|
|
|
|
9) ? (result - 10) + 'a' : result + '0';
|
|
|
|
|
num = num / (u32) base;
|
|
|
|
|
}
|
2018-10-26 14:09:43 +02:00
|
|
|
|
}
|
|
|
|
|
*pointer = '\000';
|
|
|
|
|
strinvert(str);
|
|
|
|
|
return pointer;
|
2018-10-14 19:14:19 +02:00
|
|
|
|
}
|
|
|
|
|
|
2018-10-26 14:09:43 +02:00
|
|
|
|
/*******************************************************************************/
|
|
|
|
|
/* converti un entier en chaine de caract<63>re */
|
2018-10-14 19:14:19 +02:00
|
|
|
|
|
2018-12-12 15:25:04 +01:00
|
|
|
|
u8 *sitoa(u64 num, u8 * str, u64 dim)
|
2018-10-14 19:14:19 +02:00
|
|
|
|
{
|
2018-12-12 15:25:04 +01:00
|
|
|
|
u8 *pointer = str;
|
|
|
|
|
bool isNegative = false;
|
2018-10-26 14:09:43 +02:00
|
|
|
|
num &= dim;
|
2018-12-12 15:25:04 +01:00
|
|
|
|
if (num == 0)
|
|
|
|
|
{
|
2018-10-26 14:09:43 +02:00
|
|
|
|
*(pointer++) = '0';
|
|
|
|
|
*pointer = '\000';
|
|
|
|
|
return pointer;
|
|
|
|
|
}
|
2018-12-12 15:25:04 +01:00
|
|
|
|
if ((((dim + 1) >> 1) & num) > 0)
|
|
|
|
|
{
|
2018-10-26 14:09:43 +02:00
|
|
|
|
isNegative = true;
|
2018-12-12 15:25:04 +01:00
|
|
|
|
num = (~num & dim) + 1;
|
2018-10-26 14:09:43 +02:00
|
|
|
|
}
|
2018-12-12 15:25:04 +01:00
|
|
|
|
while (num != 0)
|
|
|
|
|
{
|
|
|
|
|
u64 result = num % 10;
|
2018-10-26 14:09:43 +02:00
|
|
|
|
*(pointer++) =
|
2018-12-12 15:25:04 +01:00
|
|
|
|
(result > 9) ? (result - 10) + 'a' : result + '0';
|
2018-10-26 14:09:43 +02:00
|
|
|
|
num = num / 10;
|
|
|
|
|
}
|
|
|
|
|
if (isNegative)
|
|
|
|
|
*(pointer++) = '-';
|
|
|
|
|
*pointer = '\000';
|
|
|
|
|
strinvert(str);
|
|
|
|
|
return pointer;
|
2018-10-14 19:14:19 +02:00
|
|
|
|
}
|
2018-12-27 14:24:47 +01:00
|
|
|
|
|
|
|
|
|
/* END-EXPORT */
|