Bonvenon al alia afiŝo pri kiel krei nian propran operaciumon, ĉi-kaze NextDivel.
Se ni reiros al la kodo de unua afiŝo fine de ĉio ni devus elpensi ion tian:
Se ĉi tio ĝustas, ni povas daŭrigi. Mi uzos la sistemon kaj strukturon, kiujn mi havas ĉe GitHub (http://github.com/AdrianArroyoCalle/next-divel) ĉar ĝi estas pli komforta por mi kaj vi. Kiel vi vidas, la teksto estas baza teksto, ĝi ne estas alloga. Eble ŝajnas io eksterordinara. Sed kiel oni diras, gustumi kolorojn, kaj en nia operaciumo estos koloroj. La unuaj koloroj, kiujn ni povos meti, estos tiuj, kiuj difinas la kartojn VGA kaj ili estas 0:
- negro
- Blua
- Verda
- cian
- Ruĝa
- magenta
- Bruna
- Lumo griza
- Malhelgriza
- Luma bluo
- Helverda
- Cejana klara
- Helruĝa
- Hela magento
- Helbruna
- Blanka
Ni difinos ĉi tiujn kolorojn en kaplinio por havi ĝin pli oportuna kaj eble estonte fariĝos parto de la sistemo API. Do ni kreas la dosieron ND_Colors.hpp en la sekva inkluziva NextDivel.
#ifndef ND_COLOR_HPP
#define ND_COLOR_HPP
typedef enum ND_Color{
ND_COLOR_BLACK = 0,
ND_COLOR_BLUE = 1,
ND_COLOR_GREEN = 2,
ND_COLOR_CYAN = 3,
ND_COLOR_RED = 4,
ND_COLOR_MAGENTA = 5,
ND_COLOR_BROWN = 6,
ND_COLOR_LIGHT_GREY = 7,
ND_COLOR_DARK_GREY = 8,
ND_COLOR_LIGHT_BLUE = 9,
ND_COLOR_LIGHT_GREEN = 10,
ND_COLOR_LIGHT_CYAN = 11,
ND_COLOR_LIGHT_RED = 12,
ND_COLOR_LIGHT_MAGENTA = 13,
ND_COLOR_LIGHT_BROWN = 14,
ND_COLOR_WHITE = 15
} ND_Color;
#endif
Samtempe ni difinos novajn funkciojn por skribi sur la ekrano pli komforte (ne, ni ankoraŭ ne efektivigos printf, mi scias, ke vi volas ĝin). Ni kreos dosieron kaj ĝian titolon por aro de ekranaj rilataj funkcioj (ND_Screen.cpp kaj ND_Screen.hpp). En ili ni kreos funkciojn por: ŝanĝi la koloron de la literoj kaj la fono, skribi frazojn kaj literojn, purigi la ekranon kaj moviĝi ĉirkaŭ la ekrano. Ni daŭre uzas la ekranojn VGA sed nun ni uzos kelkajn bajtojn, kiuj donos la koloron. ND_Screen.cpp aspektus kiel:
/**
* @file ND_Screen.cpp
* @author Adrián Arroyo Calle
* @brief Implements four easy functions for write strings directly
*/
#include <ND_Types.hpp>
#include <ND_Color.hpp>
#include <ND_Screen.hpp>
uint16_t *vidmem= (uint16_t *)0xB8000;
ND_Color backColour = ND_COLOR_BLACK;
ND_Color foreColour = ND_COLOR_WHITE;
uint8_t cursor_x = 0;
uint8_t cursor_y = 0;
/**
* @brief Gets the current color
* @param side The side to get the color
* */
ND_Color ND::Screen::GetColor(ND_SIDE side)
{
if(side==ND_SIDE_BACKGROUND){
return backColour;
}else{
return foreColour;
}
}
/**
* @brief Sets the color to a screen side
* @param side The side to set colour
* @param colour The new colour
* @see GetColor
* */
void ND::Screen::SetColor(ND_SIDE side, ND_Color colour)
{
if(side==ND_SIDE_BACKGROUND)
{
backColour=colour;
}else{
foreColour=colour;
}
}
/**
* @brief Puts the char on screen
* @param c The character to write
* */
void ND::Screen::PutChar(char c)
{
uint8_t attributeByte = (backColour << 4) | (foreColour & 0x0F);
uint16_t attribute = attributeByte << 8; uint16_t *location; if (c == 0x08 && cursor_x) { cursor_x--; }else if(c == '\r') { cursor_x=0; }else if(c == '\n') { cursor_x=0; cursor_y=1; } if(c >= ' ') /* Printable character */
{
location = vidmem + (cursor_y*80 + cursor_x);
*location = c | attribute;
cursor_x++;
}
if(cursor_x >= 80) /* New line, please*/
{
cursor_x = 0;
cursor_y++;
}
/* Scroll if needed*/
uint8_t attributeByte2 = (0 /*black*/ << 4) | (15 /*white*/ & 0x0F);
uint16_t blank = 0x20 /* space */ | (attributeByte2 << 8); if(cursor_y >= 25)
{
int i;
for (i = 0*80; i < 24*80; i++)
{
vidmem[i] = vidmem[i+80];
}
// The last line should now be blank. Do this by writing
// 80 spaces to it.
for (i = 24*80; i < 25*80; i++)
{
vidmem[i] = blank;
}
// The cursor should now be on the last line.
cursor_y = 24;
}
}
/**
* @brief Puts a complete string to screen
* @param str The string to write
* */
void ND::Screen::PutString(const char* str)
{
int i=0;
while(str[i])
{
ND::Screen::PutChar(str[i++]);
}
}
/**
* @brief Cleans the screen with a color
* @param colour The colour to fill the screen
* */
void ND::Screen::Clear(ND_Color colour)
{
uint8_t attributeByte = (colour /*background*/ << 4) | (15 /*white - foreground*/ & 0x0F);
uint16_t blank = 0x20 /* space */ | (attributeByte << 8);
int i;
for (i = 0; i < 80*25; i++)
{
vidmem[i] = blank;
}
cursor_x = 0;
cursor_y = 0;
}
/**
* @brief Sets the cursor via software
* @param x The position of X
* @param y The position of y
* */
void ND::Screen::SetCursor(uint8_t x, uint8_t y)
{
cursor_x=x;
cursor_y=y;
}
La kaplinio estos tre baza, do mi ne inkluzivas ĝin ĉi tie, sed reliefigas la difinon de la tipo ND_SIDE
typedef enum ND_SIDE{
ND_SIDE_BACKGROUND,
ND_SIDE_FOREGROUND
} ND_SIDE;
Menciu ankaŭ, ke ni uzas la kaplinion ND_Types.hpp, ĉi tiu kaplinio difinas iujn bazajn tipojn por uint8_t, uint16_t, ktp bazitaj sur char kaj int. Fakte ĉi tiu kaplinio estas tiu en la normo C99 kaj fakte mia ND_Types.hpp estas kopio / gluo de la dosiero el Linukso, do vi povas interŝanĝi ilin kaj nenio okazus (ekzistas nur difinoj, neniuj funkcioj).
Por provi ĉu ĉi tiu kodo funkcias, ni modifos la eniran punkton C de la kerno:
ND::Screen::Clear(ND_COLOR_WHITE);
ND::Screen::SetColor(ND_SIDE_BACKGROUND,ND_COLOR_WHITE);
ND::Screen::SetColor(ND_SIDE_FOREGROUND,ND_COLOR_GREEN);
ND::Screen::PutString("NextDivel\n");
ND::Screen::SetColor(ND_SIDE_FOREGROUND,ND_COLOR_BLACK);
ND::Screen::PutString("Licensed under GNU GPL v2");
Kaj se ni sekvos ĉi tiujn paŝojn, ni ricevus ĉi tiun rezulton
Danke al ĉi tiuj kreitaj funkcioj, ni povas komenci fari malgrandajn GUI-ojn, ekzemple kernan panikon, kiun ni montros ĉiufoje, kiam estas nerekonebla eraro. Io tia:
Kaj ĉi tiun malgrandan GUI ni kreis ĝin nur per ĉi tiuj funkcioj:
void ND::Panic::Show(const char* error)
{
ND::Screen::Clear(ND_COLOR_RED);
ND::Screen::SetColor(ND_SIDE_BACKGROUND, ND_COLOR_WHITE);
ND::Screen::SetColor(ND_SIDE_FOREGROUND, ND_COLOR_RED);
ND::Screen::SetCursor(29,10); //(80-22)/2
ND::Screen::PutString("NextDivel Kernel Error\n");
ND::Screen::SetCursor(15,12);
ND::Screen::PutString(error);
}
Kaj jen la afiŝo. Mi memorigas vin pri la instrukcioj kompili la sistemon de 0:
git clone http://github.com/AdrianArroyoCalle/next-divel
cd next-divel
mkdir build && cd build
cmake ..
make
make DESTDIR=next install
chmod +x iso.sh
./iso.sh
qemu-system-i386 nextdivel.iso
Kaj mi profitas ĉi tiun okazon por danki vin pro la bonega akcepto, kiun havis la unua afiŝo.
5 komentoj, lasu la viajn
Bonega amiko, malgraŭ tio mi mortigas mian kaskon komprenante la kodon en c ++.
Salutojn.
ĉi tiuj aĵoj estas bonegaj. Ili denove vekis mian scivolemon pri la malaltnivela agado de la procesoroj.
eble se mi havos tempon, mi ekludos kun next-divel.
Mi delonge ne sendas artikolon. jam bezonata
Bone, tiel estas la maniero.
Mi delonge volis scii kiel konstrui operaciumon.
Atendante vian sekvan afiŝon. Saluton
Bonega amiko!
Mi nur havas unu problemon, ĉu iu povas transdoni al mi C-dosieron de ĉi tiu ekzemplo?
Ĝi ĉiam sendas al mi erarojn en la fina stacio