Na początku były zdjęcia. Żeby zrobić zdjęcie, trzeba było zanieść komputer i monitor do ciemni Poldka Dzikowskiego w budynku Sztandaru Młodych i tam wszystko rozstawić. Dużo zachodu, a jakość pozostawiała sporo do życzenia, więc było oczywiste, że nie tędy droga.
Kilka razy próbowaliśmy skopiować zawartość ekranu na drukarkę. Efekty bywały niezłe, ale po pierwsze widać było, że to wydruk, a po drugie ta sztuczka udawała się rzadko i tylko w dość specyficznych sytuacjach. Z tych prób wyniknęło jedno – żeby cokolwiek zrobić, trzeba znać zawartość pamięci ekranu i umieć przetłumaczyć ją na obrazek.
Pecet miał tę zaletę, że wszystkie karty graficzne miały klasyczny frame buffer, każdy piksel był opisany przez zawartość pamięci. Co nie znaczy, że było łatwo; o ile Hercules był trywialny, wystarczyło zrobić zrzut pamięci ekranu i każdy bit odpowiadał jednemu pikselowi, o tyle CGA, EGA i VGA dzieliły obraz między kilka bitplanów i żeby odtworzyć zawartość ekranu, trzeba się czasem było mocno wgryźć w ustawienia karty. Na szczęście od pewnego momentu na karcie VGA większość gier działała w najprostszym trybie 13h, czyli 320x200x256, z liniowym adresowaniem pamięci.
Inne pracowały w tak zwanym trybie x-mode i z nimi było dużo trudniej; rozdzielczość i sposób adresowania trzeba było odczytać z ustawień karty, a zrzucenie zawartości pamięci wymagało przełączania między czterema przeplatającymi się na ekranie bankami. Jeszcze później przyszły karty SVGA i zrobił się straszny bałagan, bo każdy producent miał swój standard i przez jakiś czas programy wyposażane były w dziesiątki sterowników. Na tym etapie gry rzadko korzystały z trybów o wyższych rozdzielczościach (poza x-mode) i zaczęły to robić, dopiero kiedy upowszechnił się standard VESA i zrobił jako taki porządek. Dla mnie osobiście życie stało się prostsze dopiero w momencie, w którym przez file echo w sieci FIDO dotarła do mnie specyfikacja standardu. Szczęśliwie od pewnego momentu rynek kart SVGA (przynajmniej w naszej okolicy) został zdominowany przez S3 i Cirrus Logic, które oprogramowywało się stosunkowo łatwo.
W przypadku komputerów ośmiobitowych, z ich wymyślnymi rozwiązaniami pozwalającymi wycisnąć jak najwięcej z ograniczonej pamięci, tłumaczenie pamięci ekranu na obraz bywało znacznie trudniejsze. Puste fragmenty obrazu mogły nie mieć swojego odpowiednika w pamięci, poszczególne fragmenty ekranu mogły być w różnych, przełączanych przez procesor w trakcie wyświetlania trybach graficznych, a sprajty były generowane i nakładane na obraz osobno. Choć jakość cierpiała, zrobienie zdjęcia albo skorzystanie ze sprzętowego frame grabbera bywało prostszym rozwiązaniem (kilka lat później ten sam frame grabber przydał się, kiedy pojawiły się na większą skalę konsole). Podobne kłopoty były z Amigą.
Ale organizacja pamięci ekranu to tylko wierzchołek góry lodowej. Najczęściej problem nie polegał na jej przetłumaczeniu na obraz, ale na dotarciu do jego zawartości. Trzeba pamiętać, że mówimy o systemach operacyjnych jednozadaniowych, w których działający program miał prawo przejąć pełną kontrolę nad komputerem, uniemożliwiając działanie wszystkim innym.
Na pewnym poziomie dotarcie do zawartości pamięci jest trywialne – za pomocą odpowiedniego sprzętu można przejąć kontrolę nad komputerem, zamrozić wykonywanie programu i zajrzeć do pamięci (a czasem i portów IO). Commodorowcy i amigowcy mieli Action Replaya i – przynajmniej teoretycznie – już w latach osiemdziesiątych mogli używać go do zrzucania screenów, choć z przyczyn opisanych wyżej, często wymagało to dodatkowej gimnastyki. Na pececie nie było tak łatwo. Action Replay na peceta owszem, powstał, ale dopiero w 1994 roku i nikt go nigdy na oczy nie widział. Istniały również debuggery sprzętowe (na przykład marki Periscope), ale kosztowały tyle co drugi komputer, więc były poza naszym zasięgiem. Na przełomie lat osiemdziesiątych i dziewięćdziesiątych trzeba było więc rzeźbić w tym, co było dostępne.
Najbardziej oczywiste rozwiązanie opierało się na wykorzystaniu wbudowanego w peceta mechanizmu obsługi klawiatury (nie, nie klawisza PrtScr, który wbrew pozorom jest bezużyteczny). Naciśnięcie dowolnego klawisza generowało przerwanie (int 9), a kiedy występuje przerwanie, procesor rzuca to, co robił i zaczyna je obsługiwać. 8086 (i następne procesory Intela z tej rodziny) wczytują w tym celu ze znajdującej się na samym początku pamięci tablicy adres obsługującej przerwanie procedury i wywołują ją. Tablica przerwań była inicjowana przez BIOS (który większość z nich obsługiwał sam), ale potem można było ją dowolnie modyfikować. Można więc było przekierować przerwanie klawiatury do własnej procedury umieszczonej w programie rezydentnym (TSR). Oczywiście nikt nie pisał własnej procedury obsługującej klawiaturę, wystarczyło zacząć obsługę przerwania wywołaniem oryginalnej procedury z BIOS-u, a potem sprawdzić, czy naciśnięty klawisz to ten, któremu przypisaliśmy zapisanie screenu na dysku i jeśli tak, zareagować.
Brzmi prosto, ale po drodze było kilka pułapek. Po pierwsze, jak już wspomniałem, DOS nie był systemem wielobieżnym. Jeśli przerwanie klawiaturowe wystąpiło w czasie, kiedy gra korzystała z plików (doczytując albo zapisując dane) próba wywołania DOS-u w celu zapisania czegoś na dysku gwarantowała kłopoty. Po drugie gra mogła przejąć przerwanie klawiatury i obsługiwać je sama. Pół biedy, kiedy zrobiła to elegancko (podmiana adresu następowała z użyciem zalecanych, „legalnych” metod, wbudowanych w BIOS i DOS), ale zdarzały się gry, które odcinały stare przerwania, idąc na skróty, co uniemożliwiało śledzenie dokonanych zmian.
Pierwszy problem dawało się obejść, przejmując nie tylko przerwanie klawiatury, ale i dokładając do DOS-u nakładkę, która zapamiętywała, czy DOS coś robi, czy jest wolny. Można to było zrobić w prawie identyczny sposób, jak ten użyty do przejęcia przerwania klawiatury; wywoływanie funkcji DOS-u też opierało się na tablicy adresów przerwań, tylko nie były one generowane przez sprzęt, a wywoływane programowo. Z drugim było znacznie gorzej. Można było powiesić się na przerwaniu zegara i co jakiś czas sprawdzać, czy nie zmienił się adres obsługi przerwania klawiatury. Można było od tych przerwań kręćka dostać…
Ale to działało. Na ogół. Na samym początku korzystaliśmy w redakcji z programów, które w tym celu pisałem sam. Tak na przykład powstała w 1991 roku mapa do Prince of Persia. Nie żeby rzecz była trywialna – o ile nie myli mnie pamięć, standardowe sposoby sprawdzania, jaki klawisz został naciśnięty, nie działały. Na szczęście BIOS prawidłowo raportował stany klawiszy SHIFT, ALT i CRTL, i to jakiejś ich kombinacji przypisałem zrzut ekranu. Różne warianty tego samego programu służyły nam lepiej lub gorzej w początkach Top Secretu. Ponieważ wiedziałem, co siedzi w środku, mogłem go modyfikować, kiedy pojawiały się kłopoty.
Przez jakiś czas bardzo poważnym problemem był format zapisu obrazków. Wybór był mniejszy niż dzisiaj. Definicja JPG została zaakceptowana dopiero we wrześniu 1992 roku, zresztą kompresja stratna się do tamtej grafiki nie nadaje, PNG też jeszcze nie istniał (specyfikacja powstała w 1996 roku), pozostawały więc PCX, GIF i BMP. Od wielkiego dzwonu trafiały się obrazki w formatach TIF i TGA. Amigowcy przynosili screeny we własnym formacie LBM (albo IFF). Długi czas nie mieliśmy specyfikacji żadnego formatu (nie było ani googla, ani internetu), więc trzeba było strasznie kombinować (mapa PoP była zrobiona i oprogramowana na moich własnych formatach, które najprościej by było określić jako RAW). W końcu Marek Sawicki (Giant) znalazł w bibliotece na Politechnice specyfikację bitmapy z jakiejś dokumentacji Microsoftu – wprawdzie, o ile pamiętam, nie samego formatu pliku, tylko struktur używanych przez Windowsy w pamięci operacyjnej, ale większość danych znajdowała się tu i tu w dokładnie tej samej formie. Przez długie lata bitmapa była dla mnie formatem wyjściowym, choć nie akceptowały jej bezpośrednio programy do DTP. Na szczęście narzędzi do konwersji nie brakowało, zwłaszcza DOS-owy GWS (Graphic Workshop) oddał nieocenione usługi podczas prac nad kolejnymi numerami.
W pewnym momencie zaczęły się pojawiać programy komercyjne (zazwyczaj shareware) do zrzucania screenów. Testowaliśmy kilka, najlepszy okazał się w 1993 roku Screen Thief. Zawodził bardzo rzadko, dawał sobie radę w sytuacjach, w których inne nie zrzucały nic, albo zrzucały śmieci, nie potrafiąc prawidłowo odczytać konfiguracji karty VGA. U podstaw jego sukcesu leżało przeprogramowanie kontrolera przerwań. Większość gier nie wchodziła tak głęboko, ale niektóre potrafiły zablokować i Screen Thiefa.
Pewnego dnia przyszło olśnienie. Rozwiązanie było proste – potrzebowaliśmy karty ISA, generującej przerwanie na żądanie gracza. Pecet nie wykorzystywał wszystkich przerwań sprzętowych, a na niewykorzystanych można było powiesić, co się chciało. Poszedłem na drugi koniec korytarza, do redakcji Bajtka, składającej się w znaczącej części z elektroników i następnego dnia miałem w ręku prototyp. Prototyp był toporny, jak większość prototypów, nie miał śledzia, bo i po co, a do generowania przerwania (na którego wybór pozwalał za pomocą zworek) wykorzystywał przełącznik typu Isostat, przylutowany na końcu przewodu w miarę wygodnie sięgającego do blatu biurka. Co najważniejsze, działał!
Zmodyfikowanie mojej wersji programu tak, żeby wywoływało go przerwanie z karty, zajęło dosłownie kilka minut. To było to. Gdzie nie dawał rady Screen Thief, zrzucaliśmy screeny kartą. Czasem wymagało to współpracy dwóch osób: jedna grała, druga pstrykała isostatem. Kiedyś, nie mogąc znaleźć nikogo do pomocy, dorobiłem z dwóch kawałków listwy, blachy z puszki i mikroprzełącznika pedał, który pozwalał zrzucać screeny bez pomocy trzeciej ręki. Pedał wyglądał jak coś, co spadło z wózka zbieraczy złomu i wywołał w redakcji falę radości, nawet z Bajtka przychodziły pielgrzymki, żeby go obejrzeć, ale pełnił swoją rolę.
Kolejna fala problemów przyszła wraz z Windows 95, ale to już zupełnie osobny temat.
Artykuł ukazał się w Pixelu #20, którego nakład został już wyczerpany. Zapraszamy jednak do sklepu Pixela po inne wydania drukowanego magazynu.