Autor Thema: Eigene Codepage im eigenen OS  (Gelesen 9832 mal)

NoeTrimm

  • Beiträge: 36
    • Profil anzeigen
Gespeichert
« am: 30. May 2013, 22:55 »
Moinsen,

ich habe in den letzten Monaten an meinem OS gearbeitet und bin soweit ganz gut voran gekommen (bootloader, kernel und eine Shell sind soweit ok). Die ausgabe von Text erfolgt ganz normal über die Standard_Codepage von Intel. Ist es möglich diese zu ändern und mit eigenen Zeichen zu belegen? Wenn ich z.B ein anderes Symbol für den Buchstaben "A" habe diesen als Standard beim Laden des OS zu etablieren, sodass beim schreiben des Codes für das Zeichen A in den Grafikspeicher eben mein Symbol angezeigt wird.

Für Ansätze wäre ich dankbar.

greetz

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #1 am: 30. May 2013, 23:15 »
Ja, du kannst eine andere Schriftart laden. Nach dem, was ich auf die Schnelle gefunden habe, ist die in VGA-Plane 2 gespeichert, du musst also wohl ein paar VGA-Register schreiben um dahin zu wechseln und dann kannst du die Zeichen im Video-RAM verändern und anschließend wieder in den normalen Modus zurückwechseln und sie benutzen. Ansatzpunkte wären:

http://www.osdever.net/FreeVGA/vga/vgatext.htm#fonts
http://wiki.osdev.org/VGA_Fonts#Set_VGA_fonts
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

NoeTrimm

  • Beiträge: 36
    • Profil anzeigen
Gespeichert
« Antwort #2 am: 30. May 2013, 23:30 »
OK. Danke. Der zweite Link scheint am hilfreichsten. Allerdings verstehe ich das so, dass ich einen bereich festlege in dem ich eine Art PixelMap anlege (font) und diese dann in den Videospeicher schreibe. Oder war mein erstes überfliegen und übersetzen so fehlerhaft?

Das ich meine Zeichen also in 8x16 Pixel schreiben muss ist klar. Nur wie ich diese dann als codepage ablege verstehe ich noch nicht. Es muss ja sowas wie einen BIOS Int geben mit dem ich das machen kann, um jedes einzelne zeichen byte für byte von einem register per int in die codepage schreibe. Wenn es das gibt, kann ja mein Bootloader das noch gleich im Realmode erledigen mit den BIOS-Ints und erst dann in den Protected Mode springen...

Vielleicht denk ich mich auch grad vor eine Wand  :mrgreen:

EDIT: Doch nicht gegen die Wand gedacht. Also dein Link hat mich über einige Int-Lists letztlich zu BIOS Int 10h gebracht. Da ist anscheind einiges möglich und ich werde mal lesen. Sollte ich einen funktionierenden Assembler Quelltext zusammen bekommen der die Codepage manipuliert und auch meine Symbole ausgeben kann, gibt es den hier im Post.

Wenn noch jemand einen Ansatz oder sogar schon eine Lösung hat, wäre ich dankbar für weitere Anregungen.

Danke kevin
« Letzte Änderung: 31. May 2013, 00:17 von Kanasaru »

Svenska

  • Beiträge: 1 792
    • Profil anzeigen
Gespeichert
« Antwort #3 am: 31. May 2013, 02:11 »
Bedenke, dass du im Real-Mode den int 10h nicht benutzen kannst.

Du legst einen 4k-Bereich im Speicher fest, in den du deinen Font legst. Anschließend kopierst du den an eine bestimmte Stelle in die Grafikkarte und bist fertig. Assembler-Beispielcode steht im OSDev-Wiki.

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #4 am: 31. May 2013, 09:55 »
OK. Danke. Der zweite Link scheint am hilfreichsten.
Ist er aber nicht. Er erklärt nämlich nicht, was man machen muss, sondern knallt nur unerklärten Beispielcode hin, mit dem man den Font auslesen kann. Wenn man weiß, was da eigentlich getan wird (das erklärt der erste Link), dann kann man sich daraus aber ableiten, wie man einen neuen Font setzt (nämlich indem man in den Speicher schreibt statt ihn zu lesen).

Bedenke, dass du im Real-Mode den int 10h nicht benutzen kannst.
Protected Mode meinst du.
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

NoeTrimm

  • Beiträge: 36
    • Profil anzeigen
Gespeichert
« Antwort #5 am: 31. May 2013, 15:33 »
Bedenke, dass du im Real-Mode den int 10h nicht benutzen kannst.

Du legst einen 4k-Bereich im Speicher fest, in den du deinen Font legst. Anschließend kopierst du den an eine bestimmte Stelle in die Grafikkarte und bist fertig. Assembler-Beispielcode steht im OSDev-Wiki.

Wie Kevin schon sagte, im Protected Mode den BIOS Int 10h aufzurufen dürfte schwierig werden  8-)

Und der Beispielcode dafür steht nicht im Wiki. Nicht so, dass man ihn adaptieren kann. Außerdem geht es mit nicht um eine spezielle Font (wenn ich es so lösen kann ist das erstmal ok), sondern das direkte ändern der Codepage durch das BIOS. Sollte allerdings die VGA-Font umsetzung leichter zu realisieren sein, würde ich mich damit auch zufrieden geben. Zumal ich bei der reservierung des 4k speichers und das schreiben meiner font die 512 Byte Marke für meinen Bootloader (in dem ich ja noch im Real Mode lebe) "etwas" sprenge.

XanClic

  • Beiträge: 261
    • Profil anzeigen
    • github
Gespeichert
« Antwort #6 am: 01. June 2013, 04:16 »
http://pastebin.com/qnWF2JGL ist eh die beste Codepage von allen. Und ist mit 60 Bytes auch noch sehr sparsam!

MNemo

  • Beiträge: 547
    • Profil anzeigen
Gespeichert
« Antwort #7 am: 01. June 2013, 11:23 »
Außerdem geht es mit nicht um eine spezielle Font […], sondern das direkte ändern der Codepage durch das BIOS.
Was verstehst du denn genau unter Codepage? Der/Die/Das Font ordnet dir zu jedem Byte-Wert eine Pixelgraphik zu, ist das nicht genau das was du haben willst? Dein Symbol als Pixelgraphik für Wert 0x41.
„Wichtig ist nicht, besser zu sein als alle anderen. Wichtig ist, besser zu sein als du gestern warst!“

Svenska

  • Beiträge: 1 792
    • Profil anzeigen
Gespeichert
« Antwort #8 am: 02. June 2013, 00:30 »
Asche auf mein Haupt. Natürlich geht int 10h im Real-Mode prima und im Protected Mode nicht. :|

Soweit ich den Code im OSDev-Wiki verstanden habe, muss man nur an zwei Stellen "esi" durch "edi" ersetzen und statt auf den 4k-Puffer auf den Font zeigen. Wenn du nur einzelne Zeichen in deinem Bootloader ersetzen möchtest, dann kannst du den im OSDev beschriebenen Weg gehen, dass du den VGA-Font aus der Grafikkarte in den Speicher kopierst, dein Zeichen veränderst und dann wieder zurückkopierst.

Eine Codepage ist nur eine Tabelle von "Zahlenwert" auf "Zeichen", sozusagen ein Vertrag zwischen den Programmen und dem Ausgabegerät. Bei MDA/CGA ist dieser Vertrag per ROM festgeschrieben (deswegen kennt das BIOS auch das Konzept einer Codepage nicht), ab EGA lässt er sich in Software ändern.

Was willst du eigentlich genau erreichen? Statt Codepages für jede einzelne Sprachfamilie hat sich Unicode durchgesetzt, allerdings ist das auf Text-Terminals nicht wirklich gut umsetzbar.

Gruß,
Svenska

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #9 am: 02. June 2013, 19:00 »
Außerdem geht es mit nicht um eine spezielle Font (wenn ich es so lösen kann ist das erstmal ok), sondern das direkte ändern der Codepage durch das BIOS.
Was genau ist an dem Teil mit "durch das BIOS" so wichtig, dass es Teil deiner Zielbeschreibung ist?
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

NoeTrimm

  • Beiträge: 36
    • Profil anzeigen
Gespeichert
« Antwort #10 am: 02. June 2013, 20:42 »
Außerdem geht es mit nicht um eine spezielle Font (wenn ich es so lösen kann ist das erstmal ok), sondern das direkte ändern der Codepage durch das BIOS.
Was genau ist an dem Teil mit "durch das BIOS" so wichtig, dass es Teil deiner Zielbeschreibung ist?

Diese Bedingung lag an meinem falschen Verständnis von Codepages und Fonts. Jetzt habe ich mich mal durch so ziemlich alles, was ich finden konnte, durchgelesen udn es bleiben noch zwei drei Fragen.

Ich befinde mich nach dem laden des Kernels im Protected Mode, mit TextMode 80x25. Das heißt mein Videospeicher beginnt bei 0xB8000 und ist 4000 Bytes lang. Meine Zeichen, die ich anstelle der Standard ASCII-Zeichen verwenden möchte muss ich Pixel für Pixel definieren. Das macht beim TextMode mit 80x25 eine Zeichengröße von 8x16 Pixel, die per 16 Bytes (eines für jede Pixelzeile) definiert werden. Dies muss ich für alle 256 Zeichen machen, was also eine Größe von 16 x 256 Byte = 4096 Bytes (4KB) ergibt, die ich im Speicher hinterlegen muss. Soweit dürfte mein Gedankengang richtig sein.

Nun hab ich gelesen, dass diese Font in den Videospeicher gehört und ich, wie Svenska richtig andeutete, lediglich den Zeiger so ändern muss, dass er auf die Startadresse meiner Font zeigt. Aber mein Videospeiche rist doch nur 4000Bytes lang und theoretisch müsste die Font dahinter, oder sehe ich das mal wieder falsch. Wo kann ich die 4kb am besten hinpacken und wenn cih schon im Kernel bin, wie ändere ich dann den zeiger? Reicht da wirklich das esi edi getausche oder nicht?

Wenn ich mal wieder Mist stammle, dann seit nachsichtig  :roll:

Für alle die es interessiert, warum ich das überhaupt ändern will:
Ich habe mal eine eigene Sprache (keine Geheimsprache oder Ähnliches) entwickelt, die mit anderen Zeichen arbeitet. Allerdings nicht so, dass ein "a" nur ersetzt wird durch eines meiner Zeichen und wenn man "Auto" schreiben will, einfach 4 Zeichen meiner Sprache zusammensetzen muss. Es gibt eine eigene Grammatik, andere Laute und Worte, die durch derzeit 19 Zeichen und ihre kombinationen dargestellt werden + Zeichen für die Zahlen 0 - 9. Diese Sprache möchte ich gerne in meinem OS nutzen, was es aber nötig macht, dass die Zeichen hinterlegt sind, da sich die Worte mit lateinischen Buchstaben nur so darstellen lassen wie sie ausgesprochen werden und dadurch sehr lang werden können. Das nur mal zur Info. Auf die Frage, warum ich überhaupt eine eigene Sprache entwickle, kann man genauso antworten, wie auf die Frage warum ein eigenes OS: Weil es geht!
« Letzte Änderung: 02. June 2013, 20:46 von Kanasaru »

Svenska

  • Beiträge: 1 792
    • Profil anzeigen
Gespeichert
« Antwort #11 am: 02. June 2013, 21:20 »
Hallo,

VGA hat 256 KB Grafikspeicher. Das heißt, neben deinem 80x25 Textmodus ist auch noch Platz für einen Font und weitere 80x25-Textmodi. Im Adaptersegment (d.h. dem Speicher zwischen 640 KB und 1 MB) ist aber nicht genug Platz für das alles, deswegen blendest du mit Hilfe bestimmter Register ein Fenster des Grafikspeichers z.B. ab Adresse 0xA0000 ein. Eine Adresse kann also - abhängig vom Zustand dieser Register - auf verschiedene Grafikspeicherzellen zeigen.

Der OSDev-Assemblercode blendet also die Bitplane 2 ab 0xA0000 ein, kopiert den Font von esi (Zeiger auf Grafikspeicher) nach edi (Zeiger auf RAM) und stellt den ursprünglichen Zustand wieder her. Wenn du esi und edi vertauschst, sollte er deinen Font in die Grafikkarte kopieren - getestet habe ich das aber nicht.

Ob sich z.B. Tengwar besonders gut in ein 8x16-Raster pressen lassen, ... schön wird es eher nicht werden. Außerdem sind 256 Glyphen nicht so besonders viel, mit einem Grafikmodus könntest du auch mehrere Schriftsysteme gleichzeitig darstellen, statt nur Untermengen davon.

Gruß,
Svenska

NoeTrimm

  • Beiträge: 36
    • Profil anzeigen
Gespeichert
« Antwort #12 am: 02. June 2013, 21:50 »
Ok, danke erstmal. Also einfach in den Videospeicher. Gut. GrafikModus möchte ich erstmal nicht nutzen. Wieso ist zwischen 640KB und 1 MB nicht genug Platz? Ich brauch doch bloß 4 KB für den Font und 4000 Bytes für die 80x25 Textmodi.

Ich verstehe auch nicht ganz was du mit mehreren Text-Modi meinst. Also ich verstehe es schon, aber so langsam wird es verwirrend für mich. Wenn mein Kernel geladen wurde, liegt doch der begin des Videospeichers bei 0xB8000 und jedes Byte was ich da reinschriebe, wird auf dem monitor angezeigt. Jetzt kann ich also 4000 Bytes weiter beginnen meinen Font rein zu schrieben und dann irgendeinen zeiger zu ändern der dann auf den start von der Font zeigt?! Ich glaub ich seh grad alles wieder komplizierter als es ist.


EDIT:

Wer ein OS schreiben will, sollte sich mit der Hardware beschäftigen  :-D Nachdem ich mir also die VGA Hardware angesehen habe, verstehe ich auch was mit den BitPlanes gemeint ist und das in der Plane 2, die Font drin steht, die aktuell verwendet wird, wenn ich ein Zeichen in ein Byte der Plane 0 schreibe. Damit macht auch die Addressierung mit 0xA0000 sinn; ist ja der Anfang der Plane 2. Nachdem ich nun auch weiß, dass die Plane 2 für den textmodus dort jedes Zeichen in 8x32 Pixel, also in 32 Bytes speichert und die ersten 16 Bytes für mich wichtig sind, kann ich also mit Hilfe des artikels von OSdev da ganze realisieren. Ich verstehe nur noch nciht ganz die Verwendung von "esi" und "edi" im zusammenhang mit movsd. Im Quelltext von OSdev, ist ja hinter dem movsd Befehl kein Quell- und Zieloperand angegeben, weshalb ich nciht verstehe, wie dann in edi die Bitmap liegen soll. Das ich Quell und zieloperand nur tauschen muss um meine Bitmap nach 0xA0000 zu kopieren ist nun klar, aber die modifizierung macht von der theorie für mich keinen Sinn. Dort wird doch nur von 0xA0000 beginnend der Inhalt in "esi" abgelegt und nicht in "edi". Wieso soll danach aber die Bitmap dann in "edi" stehen und nicht in "esi"???

Also ich vermute dann in etwa so?

;copy charmap
mov esi, 0A0000h ;<--Tauschen zu 0A0000h, esi
mov ecx, 256
;copy 16 bytes to bitmap
@@: movsd
movsd
movsd
movsd
;skip another 16 bytes
add esi, 16
loop @b
;restore VGA state to normal operation

Wenn ja, dann muss in edi meine font rein? Aber warum?
« Letzte Änderung: 02. June 2013, 23:30 von Kanasaru »

Svenska

  • Beiträge: 1 792
    • Profil anzeigen
Gespeichert
« Antwort #13 am: 02. June 2013, 23:35 »
Zwischen 640K und 1M sind nur 384K Freiraum, den sich alle Geräte aus dem Ursprungs-PC teilen müssen. Jedes Gerät, was im Real Mode angesprochen werden möchte, muss sich dort verewigen. Da findest du also neben dem BIOS auch die BIOS-Erweiterungen der ganzen Hardware und Register, mit denen man diese konfigurieren kann.

ESI = Extended Source Index
EDI = Extended Destination Index
Diese beiden Register werden von dem MOVSD benutzt und geben Quelle (DS:ESI) und Ziel (ES:EDI) der Kopiererei an. In die Register kommt auch nicht dein Font rein (passt eh nicht), sondern nur Adressen.

NoeTrimm

  • Beiträge: 36
    • Profil anzeigen
Gespeichert
« Antwort #14 am: 02. June 2013, 23:51 »
ESI = Extended Source Index
EDI = Extended Destination Index
Diese beiden Register werden von dem MOVSD benutzt und geben Quelle (DS:ESI) und Ziel (ES:EDI) der Kopiererei an. In die Register kommt auch nicht dein Font rein (passt eh nicht), sondern nur Adressen.

einmal an den Kopf geklatscht. Danke. also kommt nach EDI 0xA0000 und nach ESI die Anfangsadresse von meiner Font. Wenn ich die als Array in C deklariere, kann ich das dann so übergeben, dass der die Start-Adresse des Arrays übergibt? Oder bleiben wir bei ASM. Wie kann ich dort ein 4KB großes Datenpaket deklarieren um dann an ESI die Anfangsadresse zu übergeben?

Svenska

  • Beiträge: 1 792
    • Profil anzeigen
Gespeichert
« Antwort #15 am: 03. June 2013, 00:00 »
Wenn du deinen Font als Array in C deklarierst, kannst du auch gleich C benutzen, um ihn in die Grafikkarte zu stopfen. Das hat außerdem auch den Vorteil, dass du verstehen musst, was du da tust. :-D

NoeTrimm

  • Beiträge: 36
    • Profil anzeigen
Gespeichert
« Antwort #16 am: 03. June 2013, 00:10 »
Wenn du deinen Font als Array in C deklarierst, kannst du auch gleich C benutzen, um ihn in die Grafikkarte zu stopfen. Das hat außerdem auch den Vorteil, dass du verstehen musst, was du da tust. :-D

Daran hab ich auch schon gedacht. Und den Wink mit dem, naja, ZAUN, nehm ich mal hin. War wirklich eine schwere Geburt. Also meine Font als Array in C und dann per inline ASM die entsprechenden Vorarbeiten und in einer Schleife das Array von 0xA0000 an bis 0xA0000 + 256*32 Bits reinkloppen...Richtig?!  8-) Nur fällt mir dann grad nichts anderes ein um den Kopiervorgang von esi/edi zu ersetzen, außer für jedes Byte die Adresse berechnen zu lassen an die das nächste Byte aus dem Array kopiert werden soll. Meintest du deswegen, dass ich wissen muss, was ich tue?...Da scheint ja direkt ASM sinnvoller, bevor mein C-Kernel geladen wird  :-P

Svenska

  • Beiträge: 1 792
    • Profil anzeigen
Gespeichert
« Antwort #17 am: 03. June 2013, 10:04 »
Deine Signatur lautet "Assembler wo es nötig ist. C wo es möglich ist."
Assembler brauchst du nur für das out (outw), alles andere lässt sich direkt in C erledigen. Stichwort memcpy().
Außerdem musst du trotzdem aufpassen, dass du eben nicht den ganzen Speicherblock am Stück kopierst, sondern immer erst 16 Bytes kopieren, 16 Bytes überspringen, ...

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #18 am: 03. June 2013, 18:41 »
Viel interessanter als das Zeichensatzzeug fände ich es ja, die Conlang zu sehen. :-D
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

 

Einloggen