Format MacPaint to jedno z kluczowych dziedzictw wczesnej cyfrowej grafiki, które łączy w sobie innowacyjne metody kompresji i reprezentacji obrazu, takie jak kodowanie run-length (RLE) oraz algorytm ditheringu opracowany przez Billa Atkinsona. Odkrycie starych plików w tym formacie, zawierających skomplikowane, cyfrowo wymieszane zrealizowane prace artystyczne, otwiera fascynującą perspektywę na sposób, w jaki już pod koniec lat 80. i na początku 90. rozwijano cyfrową estetykę, łącząc techniki analogowe z cyfrowymi manipulacjami. Wartość tych plików może wykraczać poza zwykłą ciekawostkę historyczną — mogą być one pozostałością po pracach wybitnego artysty Roberta W. Fichtera lub kogoś inspirowanego jego twórczością, co podkreśla rolę MacPaint jako narzędzia nie tylko technicznego, ale i artystycznego.

Bill Atkinson, twórca MacPaint, jest postacią, której wkład w rozwój grafiki komputerowej i interfejsów użytkownika trudno przecenić. Jego praca nad QuickDraw, systemem graficznym dla komputerów Lisa i Macintosh, ukształtowała fundamenty wizualnej prezentacji danych na komputerach osobistych. Atkinson był również twórcą HyperCard — prekursora współczesnego hipertekstu i internetu, który stanowił pierwsze doświadczenie „sieciowe” dla wielu użytkowników już w latach 80.

Algorytm ditheringu Atkinsona, pierwotnie prawdopodobnie stosowany w urządzeniach skanujących do wprowadzania obrazów do MacPaint, jest przykładem prostego, lecz skutecznego rozwiązania problemu ograniczonej palety kolorów. W czasach, gdy sprzęt miał niewielkie możliwości graficzne i ograniczoną liczbę kolorów, dithering pozwalał na tworzenie iluzji szerszej gamy barw poprzez rozproszone wzory punktów. Ta technika, choć stara, wciąż znajduje zastosowanie w nowoczesnych urządzeniach z ograniczoną kolorystyką, takich jak czytniki e-booków czy przenośne konsole do gier.

Kodowanie run-length, które stosuje MacPaint, jest kolejnym elementem wyrafinowanej optymalizacji przechowywania danych graficznych. Dzięki temu możliwe było efektywne kompresowanie obrazów zawierających powtarzające się fragmenty, co było niezbędne w erze ograniczonej pamięci masowej i niskiej przepustowości. Technika ta nie ogranicza się jednak do MacPaint — jej idee przetrwały w nowoczesnych algorytmach kompresji, takich jak DEFLATE używany w popularnych formatach ZIP.

Warto zauważyć, że w procesie tworzenia oprogramowania Atkinson kładł nacisk na prostotę i klarowność. Usuwanie nadmiarowych funkcji, które mogłyby komplikować interfejs i utrudniać użytkowanie, było dla niego kluczowe. To podejście do projektowania, stawiające na minimalizm i efektywność, jest nadal aktualne i stanowi cenną lekcję dla twórców oprogramowania.

MacPaint i jego algorytmy są przykładem, jak technologie z przeszłości mogą inspirować i być wykorzystywane w nowych kontekstach — czy to przez odtworzenie klasycznych formatów w nowoczesnych aplikacjach, czy przez eksperymenty z różnymi wariantami ditheringu, które rozwijają i wzbogacają dzisiejszą grafikę cyfrową.

Ważne jest, aby czytelnik rozumiał, że techniki takie jak dithering czy kodowanie run-length nie są jedynie historycznymi ciekawostkami, lecz fundamentami, na których opiera się współczesna grafika komputerowa. Wiedza o nich pozwala dostrzec, jak ograniczenia sprzętowe z przeszłości kształtowały innowacje techniczne i artystyczne. Ponadto zrozumienie podejścia Atkinsona do projektowania — eliminowania niepotrzebnych funkcji dla poprawy przejrzystości i efektywności — daje uniwersalne wskazówki dotyczące tworzenia zarówno oprogramowania, jak i interfejsów użytkownika.

Jak działa system wyświetlania grafiki w NES: PPU, tabele wzorców i zarządzanie pamięcią

W systemie NES, pamięć graficzna była zarządzana za pomocą układu PPU (Picture Processing Unit). PPU był odpowiedzialny za wyświetlanie grafiki na ekranie, pobierając dane z ROM-u i RAM-u karty. Jednakże, w przeciwieństwie do współczesnych systemów graficznych, w NES nie istniała zintegrowana pamięć graficzna, w której dane byłyby zawsze dostępne. Zamiast tego, w zależności od potrzeby, grafiki były ładowane do pamięci CHR RAM z ROM-u PRG. W niektórych rzadkich grach zarówno pamięć CHR ROM, jak i CHR RAM znajdowały się w różnych bankach pamięci.

Pamięć ta była podzielona na tzw. „tabele wzorców”, które były podzielone na dwie 4KB sekcje, z których każda zawierała 256 16-bajtowych kafelków. Każdy kafelek zdefiniowany w tabeli wzorców reprezentował potencjalne grafiki dla regionu ekranu o rozmiarze 8x8 pikseli. Kafelki w tabelach wzorców były wykorzystywane do odwzorowania różnorodnych elementów graficznych gry, takich jak postacie, tekst czy tło. Często wiele z tych kafelków pozostawało pustych, co dawało twórcom gier większą przestrzeń na grafiki, niż było to rzeczywiście potrzebne.

Warto zaznaczyć, że NES, podobnie jak inne urządzenia tej generacji, korzystał z palety kolorów ograniczonej do zaledwie czterech kolorów na pojedynczy kafelek. Z tych czterech, jeden był zawsze ustawiony na kolor tła lub przezroczysty, a pozostałe trzy były wybrane przez programistę. Paleta kolorów nie była częścią tabeli wzorców, co wyjaśnia, dlaczego w niektórych narzędziach emulacyjnych, jak np. FCEUX, kafelki wyświetlane są w odcieniach szarości.

W przypadku NES każdy kafelek był zdefiniowany przez dwa zestawy bitów, znane jako „płaszczyzny bitowe”. Każdy piksel w kafelku miał przypisane dwa bity, a kombinacja bitów z obu płaszczyzn decydowała o jego ostatecznym kolorze. Pierwsza płaszczyzna bitowa odpowiadała za zerowy bit każdego piksela, druga za pierwszy bit. Po połączeniu tych dwóch płaszczyzn powstawał pełny obrazek, definiując ostateczny kolor piksela.

Nametables, czyli tablice nazw, były miejscem, w którym przechowywane były informacje o tym, jakie kafelki tworzyły tło na ekranie. Każda tablica reprezentowała pojedynczy ekran gry i miała rozmiar 32 kafelki szerokości oraz 30 kafelków wysokości, co dawało 960 miejsc w jednej tablicy. Każde z tych miejsc było zapisane jako indeks, wskazujący na dany kafelek w tabeli wzorców. Dzięki temu, tło gry mogło być dokładnie kontrolowane, a każda zmiana w tablicy nazw skutkowała natychmiastową modyfikacją wyświetlanego obrazu.

Niestety, PPU NES miał tylko 2KB pamięci, co pozwalało na załadowanie tylko dwóch tablic nazw w jednej chwili. Te tablice mogły być „lustrzane” – czyli kopie siebie nawzajem – przez co system miał cztery logiczne tablice nazw, co w teorii podwajało dostępne zasoby. Każda tablica, będąc 960 bajtów, wykorzystywała zaledwie niewielką część dostępnej pamięci, jednak to ograniczenie miało swoje konsekwencje w projektowaniu gier. Z tego powodu projektanci musieli rozważnie zarządzać przestrzenią pamięciową, aby jak najlepiej wykorzystać dostępne zasoby.

Kolejnym istotnym elementem był sposób, w jaki wybierano kolory dla tła. PPU miał pamięć palety, która definiowała cztery różne palety kolorów dla tła. Ponieważ każdy kafelek mógł zawierać tylko trzy kolory (oprócz tła lub przezroczystości), każda z palet definiowała zestaw trzech kolorów, które mogły zostać użyte do wyświetlenia grafiki. Każda tablica nazw była wspomagana przez „tabelę atrybutów”, której zadaniem było przypisanie odpowiedniej palety kolorów do grupy czterech kafelków. Tabela atrybutów była 8x8, a każdy wpis zajmował jeden bajt. Co ważne, każdy bajt w tabeli atrybutów dotyczył 2x2 obszaru kafelków, co oznaczało, że wszystkie cztery kafelki w takim obszarze musiały korzystać z tej samej palety kolorów. Praca artystów w tamtym czasie była więc nie lada wyzwaniem – musieli oni tworzyć grafiki w taki sposób, by ich kolory były spójne w całych obszarach ekranu, mimo że palety kolorów były niezwykle ograniczone.

Dzięki temu systemowi, NES był w stanie wyświetlać obrazy na ekranie przy minimalnych zasobach pamięciowych, co w tamtych czasach stanowiło przełom w technologii. Zrozumienie tego mechanizmu jest kluczowe dla lepszego poznania, jak działały ówczesne konsole i jak programiści musieli myśleć o każdej pojedynczej pikseli, by optymalnie wykorzystać dostępną pamięć i ograniczenia sprzętowe.