Zestaw znaków Commodore 64 to 256 pozycji po osiem na osiem pikseli. Nie ma w nim ani jednego polskiego znaku — i nigdy nie było. Opowieść o tym, gdzie w takiej matrycy zmieścić ogonek, dlaczego Ź i Ż potrafią wyglądać identycznie, i jak zrobić to tak, żeby nie ukraść cudzej pracy.

Osiem na osiem, ani jednego więcej

Zestaw znaków Commodore 64 siedzi w ROM-ie i ma dokładnie 2048 bajtów: 256 znaków po 8 bajtów, każdy bajt to jeden wiersz matrycy o szerokości ośmiu pikseli. Rejestr $D018 pozwala wskazać VIC-II inny obszar pamięci, więc własny krój to jedna z pierwszych rzeczy, których uczy się każdy, kto pisze na tę maszynę cokolwiek poza listingiem z gazety.

Czego w tym zestawie nie ma, tego nie ma na zawsze: PETSCII nie zna polskich liter. Ani ą, ani ę, ani ł. Na maszynie z 1982 roku, sprzedawanej w Kalifornii, nikogo to nie dziwiło. Dziwi dziś, kiedy ten sam krój — w wiernej rekonstrukcji jako font TrueType — wraca na ekran współczesnego komputera i okazuje się, że nadal nie da się w nim napisać „żółw".

Ten tekst jest o tym, jak dorysować brakujące dziewięć liter (plus dziewięć wielkich) tak, żeby nikt nie poznał, że nie było ich w oryginale. I o tym, czego nauczyła mnie po drodze litera Ż.

Pikselowy font w przebraniu krzywych

Najwierniejszą dziś rekonstrukcją charsetu C64 jest C64 Pro Mono — font TrueType, w którym każdy znak to nie krzywe Béziera, tylko zwykłe prostokąty ułożone na siatce. To kluczowa właściwość, bo pozwala zrobić rzecz, która w normalnym kroju byłaby wandalizmem.

Font ma 2048 jednostek na firet (em). Osiem pikseli na 2048 jednostek daje 256 jednostek na piksel — okrągłą liczbę, nie żaden ułamek. Znak da się więc zrasteryzować z powrotem do bitmapy 8×8 bezstratnie: wystarczy sprawdzić, czy środek każdego piksela leży wewnątrz konturu.

Wielka litera „O" po takiej konwersji wygląda dokładnie tak, jak wyglądała w ROM-ie:

........
..####..
.##..##.
.##..##.
.##..##.
.##..##.
.##..##.
..####..
........

I tu przychodzi obserwacja, która rozwiązała cały problem: pierwszy wiersz jest pusty. Wielkie litery zajmują w tym kroju wiersze od pierwszego do siódmego, małe od trzeciego do siódmego. Nad każdą wielką literą zostaje jeden wolny wiersz, a pod linią bazową — drugi.

Dokładnie tyle, ile trzeba na kreskę nad Ó i na ogonek pod Ą. Bez skracania liter, bez rozpychania wierszy.

Dziewiętnaście znaków, których nie było

Reszta jest już mechaniką: bierzemy literę bazową, dokładamy akcent jako piksele, składamy znak z powrotem z prostokątów. Cztery przykłady gotowego wyniku:

      Ó              Ż              Ł              Ą
   ....##..       ...#....       ........       ........
   ..####..       .######.       .##.....       ...##...
   .##..##.       .....##.       .##.....       ..####..
   .##..##.       ....##..       .##.....       .##..##.
   .##..##.       ...##...       ####....       .######.
   .##..##.       ..##....       .##.....       .##..##.
   .##..##.       .##.....       .##.....       .##..##.
   ..####..       .######.       .######.       .##..##.
   ........       ........       ........       ....##..

Ł nie jest akcentem tylko poprzeczką na literze, więc dostaje własną regułę. Ogonki schodzą do wiersza pod linią bazową — tego samego, w którym normalnie mieszkają descendery „g" i „y".

Efekt liczbowo: yMax gotowego fontu wynosi 2048, czyli równo jeden firet. Cały znak — z akcentem i ogonkiem — mieści się w komórce. To nie jest kosmetyka. Gdyby akcent wystawał choćby o piksel, terminal albo ucinałby mu górę, albo trzeba by rozsuwać wiersze, a wtedy ekran przestaje wyglądać jak ekran C64 i zaczyna wyglądać jak edytor tekstu.

Ź kontra Ż, czyli różnica, której nie widać

Pierwsza wersja miała wadę, którą zobaczyłem dopiero na renderze — nie w kodzie, nie w liczbach, dopiero na obrazku.

Ź i Ż różniły się przesunięciem akcentu o jeden piksel w bok. Kreska stała w czwartej kolumnie, kropka w trzeciej. Na wydruku bitmapy różnica jest oczywista, bo widać siatkę. Na ekranie, przy dwunastu punktach, nie ma jej wcale.

Poprawka polegała na zmianie grubości, nie położenia: kreska ma dwa piksele i biegnie w prawo, kropka ma jeden i stoi na środku. Małe litery mają zapas dwóch wolnych wierszy, więc dostały porządny ukośny akcent, na jaki wielkie nie mają miejsca.

Wniosek jest szerszy niż ten jeden font i wart zapamiętania przy każdej robocie w małej rozdzielczości — przy ośmiu pikselach różnicę trzeba projektować tak, żeby ją było widać, a nie tak, żeby dała się policzyć. Sprite'y wrogów w grach rządzą się dokładnie tym samym prawem.

Przy okazji doszły znaki, których oryginał nie ma, a polszczyzna ich potrzebuje: cudzysłów otwierający „, przecinek górny ‚, wielokropek …, półpauza – i myślnik —. Cudzysłowy powstały z przesunięcia istniejących w dół o cztery wiersze; w tym kroju rysuje się je jako dwie grube kreski, więc pasują bez retuszu.

Dlaczego nie dostaniecie gotowego pliku

I tu część, która wymagała więcej namysłu niż kod.

Licencja C64 Pro Mono zabrania dwóch rzeczy naraz: rozpowszechniania pliku i jakiejkolwiek jego modyfikacji. Każde dozwolone użycie ma w niej dopisek „without any modification". Font z dorysowanymi ogonkami jest modyfikacją, więc wypada poza wszystko, na co autor kiedykolwiek się zgodził.

Dlatego w repozytorium nie ma pliku fontu i nigdy nie będzie. Instalator pobiera oryginał prosto ze strony autora, a polskie znaki dorysowuje już na komputerze użytkownika, do jego własnego użytku. Rozdawany jest generator, nie font.

Brzmi drobiazgowo. Ale to jest różnica między „szanujemy pracę autora" a „bierzemy cudze i zmieniamy nazwę" — a w tej branży żyjemy z tego, że ktoś kiedyś zrobił kawał świetnej roboty i udostępnił ją za darmo na jasnych warunkach.

Co z tym zrobić

Wynikiem jest terminal, który wygląda jak ekran C64 i mówi po polsku — paleta VIC-II, migający kursor-blok, ekran powitalny BASIC V2 i zachęta w postaci LOAD"...",8,1. Kod, instalator i dokumentacja leżą tutaj:

👉 github.com/arekbr/c64-terminal-pl

Instalator sam rozpoznaje dystrybucję, robi kopię zapasową plików, które zmienia, i ma tryb --dry-run, jeśli ktoś woli najpierw zobaczyć, co się stanie. Powstał i był testowany na Debianie; konfiguracje dla pozostałych terminali są napisane według ich dokumentacji, ale nieprzeklikane — i tak jest to napisane wprost w opisie projektu.

Sam pomysł nie jest nowy: temat polskich czcionek wraca na scenowych forach od lat — choćby w tym wątku na c64scene.pl. Nowe jest to, że tym razem znaki nie lądują w emulatorze, tylko w oknie, w którym pracuje się codziennie.

Krótszą wersję tej historii — bez rozbierania fontu na czynniki pierwsze — opublikowaliśmy też na stronie SMOK-a.

A jeśli macie ochotę na kolejny krój: Amstrad CPC, ZX Spectrum i Atari czekają w kolejce. Ta sama metoda, inna siatka.