Dzięki! Oczywiście że rzucę okiem. A za chwilę wrzucę ostatnią część "przeklętej sagi" ;-)

No poprawki zrobiłem w "loaderze" który znajdował się przed grami Silent Service, Fantastic Soccer i World Soccer. Co ciekawe ten "efekt" uboczny z tym nieszczęsnym wywołaniem CLOSE występuje tylko na oprogramowaniu od MUEL, inne wersje oprogramowania do Turbo 2000F na których testowałem wcześniej (te siedzące pod OS-ROM) nie miałby problemu z tym dziwnym wywołaniem CLOSE.

Zatem wychodzi na to że ktoś to przygotował tę kasetę i nagrywał jej zawartość musiał mieć własnie tę wersję systemu i rozwiązał problem przed dodanie "śmieci" w pilocie. W sumie to nie rozumiem czemu tych gier nie zapisano po prostu w "new format", ten loader załadowałby te gry bez problemu.

The Klątwa Set - Pars II et dimidia: Zemsta HATABS

No to jednak będzie mała aktualizacja i korekta tego, co pisałem wcześniej. Nie dawały mi spokoju te "pyknięcia" w tonach pilotujących. Przyjrzałem się im bliżej i okazało się, że są zbyt regularne, zbyt powtarzalne. Początkowo zakładałem, że taka była uroda magnetofonu, na którym dokonano zapisu, jednak dokładniejsza analiza tych miejsc wykazała, że owe "pyknięcia" nie powstały przez przypadek. To, co wcześniej przedstawiłem jako przykład, czyli fragment tonu synchronizującego przerwanego jakimś "trzaskiem", okazało się celowym zabiegiem. Dla przypomnienia wrzucę to jeszcze raz:

pwmc 00151 46 584 12 1 23 1 46 3463 ; count=4

To, co opisałem jako "potknięcia" a8cas-util, okazało się finalnie moim "potknięciem" i nadinterpretacją faktów. Z mojego wcześniejszego opisu wynikało, że widoczny tam fragment powinien być jednostajnym tonem synchronizującym, przerwanym jakimś "śmieciem". Okazało się jednak, że była to błędna interpretacja całej sytuacji. Po sprawdzeniu kilku plików zobaczyłem, że wszędzie wygląda to tak samo, czyli w rzeczywistości ta sekwencja składała się z:

  • początkowej serii impulsów pilota

  • impulsu reprezentującego "0"

  • impulsu reprezentującego "1"

  • końcowej serii impulsów pilota

Początkowo wszystkie testy robiłem w emulatorze i w wersji systemu Turbo 2000F, który wykładał się na tych "śmieciach" w środku pilota. Uznałem więc, jak wspominałem wyżej, że jest to niedoskonałość urządzenia zapisującego. Poprawiłem wszystkie te "uszkodzone" miejsca i uznałem sprawę za rozwiązaną, ponieważ wszystko zaczęło wczytywać się poprawnie. Przetestowałem zarówno pliki w formacie "new", jak i te nagrane w starym formacie, również te z dodanym loaderem, który tak naprawdę był wersją systemu turbo lokującą się w dolnej przestrzeni pamięci - nazwijmy go LoMem_Ldr.

Wszystko wydawało się działać idealnie, aż do momentu, gdy zacząłem ponownie sprawdzać całość podczas pisania drugiej części tej "przeklętej" sagi. Robiąc porządki w tekście i chcąc dodać linki do wszystkich istotnych materiałów, dorzuciłem także odnośnik do oryginalnej wersji Turbo 2000F sygnowanej przez MUEL, czyli tej lokującej się pod OS-ROM.

Post opublikowałem na forum, po czym coś mnie tknęło i zacząłem testować wszystko ponownie, tym razem wykorzystując już pliki ściągnięte bezpośrednio z mojego posta.

Jakież było moje zdziwienie, gdy zobaczyłem, że Silent Service, Fantastic Soccer i World Soccer nie wczytują się poprawnie. Loader najwyraźniej nie "załapywał" nazwy programu nagranego za nim, przez co reszta bloków nie była ładowana wcale. "Loader" nadal oczekiwał na blok zawierający nazwę wczytywanego programu.

Na szybko spróbowałem wczytać pliki .hex niezawierające moich "normalizacji" i "korekt". Te ładowały się bez problemu, mimo że zawierały owe "pyknięcia"! Po odkryciu tego faktu zorientowałem się, że te "pyknięcia" w tonie synchronizującym są konieczne, aby "LowMem_Ldr" był w stanie poprawnie zinterpretować nazwę nagranego za nim programu.

Po odkryciu tego faktu postanowiłem wyjaśnić sprawę do końca. Początkowo szybko zaktualizowałem problematyczne pliki hex/cas w archiwum, dodając im sekwencję dwóch bitów "0" i "1" występujących w trakcie trwania pilota, a potem zacząłem grzebać, aby dociec, o co właściwie chodzi. Jeżeli to czytacie, to znaczy, że udało mi się dojść do tego, co tak naprawdę tam się działo ;-)

Zacząć musimy od analizy samego loadera. Będę się starał opisać to w miarę prosto, jednak będzie niestety trochę asemblera, trochę opisu struktury plików i trochę działania loadera plików binarnych Atari DOS (.XEX).

Zatem popatrzmy, jak wygląda struktura bloków samego loadera (LoMem_Ldr):

chkxex t2kf_lomem_ldr.xex 

Input file is t2kf_lomem_ldr.xex and the file size is 1797 bytes.

Header is: $ffff
block 001: $1700-$1df6 ($06f7)
block 002: $02e0-$02e3 ($0004) --->  RUN/INIT $1d9d/$1d9d

File t2kf_lomem_ldr.xex is OK!

^^^ Na pierwszy rzut oka nie widać tutaj niczego niepokojącego. Owszem, plik ładuje się dość nisko, ale w przypadku nadrzędnego systemu, z którego jest ładowany, nie ma to znaczenia, bo mamy MemLo na poziomie $0800. Ładowanie od adresu $1700 w niczym nie przeszkadza. Nietypowa wydaje się jednak sekwencja RUN/INIT, czyli jednoczesne ustawienie wektorów RUN i INIT na ten sam adres startu.

Niby czemu miałoby to przeszkadzać? Po prostu program zostanie uruchomiony przez INIT, a nie przez RUN, więc teoretycznie nie powinno to mieć żadnego znaczenia. Okazuje się jednak, że w tym wypadku ma to znaczenie - ale o tym będę mógł opowiedzieć za chwilę, gdy wyjaśnię, jak działa loader plików .XEX/.COM/.EXE w takim systemie jak Turbo 2000F/KSO.

System turbo instaluje w systemie sterownik urządzenia. W tym wypadku jest to urządzenie "D:", aby zachować "zgodność" z programami, które odwołują się do "D:" tak, jak do stacji dysków. W systemie znajduje się więc sterownik, do którego można się odwołać przez CIO. Działają więc wszystkie operacje typu OPEN, CLOSE, GET, PUT. Loader plików binarnych zawarty w oprogramowaniu turbo bazuje właśnie na odwołaniach do urządzenia "D:" przez CIO, a więc używa funkcji OPEN, GET, CLOSE itd.

Przebieg ładowania pliku .XEX przez taki loader wygląda mniej więcej tak:

open_file(filename);

while_not_eof
{
   get_block_header();
   load_block();
   init_segment();
}

close_file();
jmp_to_run_vector();

Czyli loader otwiera urządzenie "D:" do odczytu funkcją OPEN i próbuje odnaleźć blok danych z nazwą pliku. Gdy mu się to uda, rozpoczyna ładowanie bloków danych. W kolejnych krokach loader odczytuje bajty nagłówka pliku, oblicza długość bloku i zaczyna ładować poszczególne bloki w odpowiednie miejsca pamięci. Po załadowaniu każdego bloku sprawdzane jest, czy blok nie był segmentem typu INIT. Jeżeli wektor INITAD ($2e2-$2e3) zawiera wartość niezerową, wykonywany jest skok pod adres, na który INITAD wskazuje. Wszystko dzieje się w pętli aż do napotkania końca pliku, czyli ładowane są kolejne bloki danych. Gdy osiągnięty zostanie koniec pliku, wykonywany jest skok pod adres określony przez RUNAD ($2e0-$2e1). Jeżeli wektor RUNAD nie został ustawiony w pliku, następuje skok pod adres pierwszego z ładowanych segmentów.

Pewnie znowu zastanawiacie się, z jakiego powodu zanudzam was takimi szczegółami technicznymi. Niestety jest to konieczne do zrozumienia mechanizmu, który za chwilę zacznę opisywać. Będzie to opis tego, co właściwie zaczyna się dziać po załadowaniu segmentu danych ($2e0-$2e3), czyli segmentu, który jednocześnie ustawia wektory INIT i RUN.

Przyjrzyjmy się zatem temu, co dzieje się, gdy loader plików zawarty w systemie 2000F (MUEL) skoczy pod adres $1d9d wskazywany przez wektor INITAD ($2e2-$2e3):

; kasujemy poprzedni wpis dla urządzenia "D:" w HATABS
; (na ślepo, zakładamy że on tam jest, )
; (i że jest dokładnie w tym miejscu, tzn. pod adresem HATABS+$0F)

    1D9D: A2 02             LDX #$02
    1D9F: A9 00             LDA #$00
    1DA1: 9D 29 03          STA HATABS+$0F,X
    1DA4: CA                DEX
    1DA5: 10 FA             BPL $1DA1
    
; przygotowujemy się do przepisania załadowanego kodu
; z lokacji $1700 do lokacji  $0700
    1DA7: A9 17             LDA #$17
    1DA9: 85 31             STA $31
    1DAB: A9 07             LDA #$07
    1DAD: 85 33             STA $33
    1DAF: A9 00             LDA #$00
    1DB1: 85 30             STA $30
    1DB3: 85 32             STA $32

; pętla kopiujące dane
    1DB5: A2 0E             LDX #$0E
    1DB7: B1 30             LDA ($30),Y
    1DB9: 91 32             STA ($32),Y
    1DBB: C8                INY
    1DBC: D0 F9             BNE $1DB7
    1DBE: E6 31             INC $31
    1DC0: E6 33             INC $33
    1DC2: E4 33             CPX $33
    1DC4: D0 F1             BNE $1DB7

; ustawiamy wektory     
    1DC6: A9 C2             LDA #$C2
    1DC8: 85 02             STA CASINI
    1DCA: 85 0C             STA DOSINI
    1DCC: A9 08             LDA #$08
    1DCE: 85 03             STA CASINI+1
    1DD0: 85 0D             STA DOSINI+1
    
; skok do procedury instalującej handler "D:"
    
    1DD2: 20 C2 08          JSR $08C2

; inicjalizacja wskaźnika stosu, etc.
    1DD5: A2 FF             LDX #$FF
    1DD7: 9A                TXS
    1DD8: A9 01             LDA #$01
    1DDA: 85 09             STA $09

; bezpośredni skok do procedury "screen open" w OS-ROM
    1DDC: A9 00             LDA #$00
    1DDE: 85 2B             STA ICAX2Z
    1DE0: A9 0C             LDA #$0C
    1DE2: 85 2A             STA ICAX1Z
    1DE4: 20 8E EF          JSR $EF8E

; zamykamy kanał IOCB#1 (używając CIO)
; (poprzednio otwarty przez stary handler "D:")
;
; !!! UWAGA! (w tej chwili wpisy w HATABS wskazują już na nowy handler!)
; !!! UWAGA! (to jest piękny przepis na katastrofę!                    )
;
    1DE7: A2 10             LDX #$10
    1DE9: A9 0C             LDA #$0C
    1DEB: 9D 42 03          STA ICCMD,X
    1DEE: 20 56 E4          JSR CIOV

; ustaw flagę oznaczającą "LOAD & RUN"
    1DF1: 38                SEC
    1DF2: 66 48             ROR $48
    
; skocz do procedury ładującej plik binarny (.XEX)
; (mówimy o świeżo załadowanej wersji systemu)
    1DF4: 4C FE 08          JMP $08FE

Teraz, mając już całość jak na talerzu, mogę spróbować wyjaśnić, dlaczego programy nagrane za tym loaderem miały w trakcie tonu pilotującego wrzucone dwa dodatkowe bity danych (0,1), które traktowałem jako przypadkowe śmieci. Istotne okazały się dwie rzeczy. Po pierwsze, ten "loader" jest uruchamiany tak naprawdę przez wektor INITAD ($2e2-$2e3). Po drugie, w procedurze startu tego loadera znajduje się sekwencja zamknięcia kanału IOCB#1, czyli kanału otwartego wcześniej przez poprzedni loader jako kanał do odczytu danych. Tak się ciekawie składa, że w chwili, gdy ten kod zostaje uruchomiony przez wektor INITAD, kanał jest cały czas otwarty.

Teoretycznie, gdyby uruchomić ten kod przez wektor RUNAD ($2e0-$2e1), nadrzędny loader zamknąłby kanał IOCB#1 przed uruchomieniem wczytanego programu, a ponowne otwarcie kanału IOCB#1 przez nowy loader odbyłoby się bez problemów.

W tym wypadku dzieje się jednak inaczej. Bez wchodzenia jeszcze głębiej w szczegóły: wywołanie polecenia CLOSE dla IOCB#1 powoduje błędną reakcję procedury obsługującej CLOSE. Dlaczego? Ponieważ kanał IOCB#1 był otwarty przez poprzednią wersję handlera, czyli tę rezydującą pod OS-ROM, a tutaj program podmienia wpisy w HATABS w locie i instaluje swój nowy handler. W efekcie CLOSE #1 powoduje wywołanie procedury CLOSE już z nowego handlera! Wszystkie komórki dotyczące statusu kanału są ustawione przez inny handler, a nagle odpalany jest CLOSE tak naprawdę z innej wersji systemu. Normalnie powinno dojść do sytuacji, w której kanał zostaje zamknięty. Tutaj natomiast wywołanie CLOSE powoduje, że handler próbuje wczytać następny blok danych zamiast zakończyć odczyt.

I to właśnie jest problemem, bo przy standardowym formacie danych następny blok jest blokiem zawierającym nazwę pliku. Wywołanie CLOSE odczytuje więc ten blok, a następny "czysty" OPEN, wykonywany już przez właściwy loader, nie znajduje bloku nazwy. Wczytywanie programu tak naprawdę nigdy się nie zaczyna.

Ktoś wpadł na pomysł, aby dodać te dwa bity w trakcie pilota - bity, na których procedura odczytu bloku wywołana przez CLOSE się wysypie. Status błędu CLOSE nie jest sprawdzany, więc niczym to nie grozi. Dzięki temu następny OPEN poprawnie odczyta nazwę i loader zadziała prawidłowo.

Co ciekawe, rozwiązaniem tego problemu było tak naprawdę uruchamianie tego loadera przez wektor RUNAD. Wtedy, jak wspominałem, loader zawarty w MUEL przed wywołaniem kodu loadera po prostu zamykałby kanał IOCB#1, a ponowne wywołanie CLOSE przez nowy loader na zamkniętym kanale nie generowałoby już skutków ubocznych.

Warto jednak zaznaczyć, że efekt opisany wyżej występuje tylko w przypadku oprogramowania MUEL, które dołączałem do poprzedniego odcinka sagi o klątwie.

Zaczynam zastanawiać się, czy było to działanie celowe. Czy była to jakaś dziwna forma zabezpieczenia "z epoki", powodująca, że wszystko poprawnie działało tylko z cartridge'em od MUEL? A może był to efekt uboczny kombinowania przez kogoś już w czasach nowożytnych, zaś "pyknięcia" wstawione w pilota były obejściem problemu, które zadziałało trochę "przez przypadek"?

Mogę jedynie gdybać i snuć domysły. Nie mam jednak żadnej pewności, że te przypuszczenia są trafione. Coraz bardziej skłaniam się jednak do teorii, że kaseta i zapis na niej nie są tak stare, jak początkowo przypuszczałem.

Aby nie tworzyć kolejnych problemów, postanowiłem poprawić strukturę pliku loadera i usunąć "pyknięcia" z pilotów. Dodaję więc nową wersję plików w archiwum (v1.2).

Poprawka loadera (LoMem_Ldr) polega, tak jak wspominałem, na zamianie ostatniego segmentu danych z $2e0-$2e3 na zwykły segment RUNAD ($2e0-$2e1). Tak zmodyfikowany loader działa poprawnie z kilkoma wersjami softu Turbo 2000F, które miałem pod ręką.

Heh, no i zamiast odcinka III sagi wyszedł odcinek 2.5. Zatem przyjdzie wam jeszcze chwilę poczekać na obiecaną część III - trzecią i ostatnią :P Zaktualizowane archiwum znajduje się w poście z opisem części II.

tOri napisał/a:

@Seban - nie próbowałeś ratować karty E-mu stawiając siódemkę na maszynie wirtualnej?

Ja nadal mam ten stary komputer w którym siedzi E-MU 1212M, mam na nim multi-boot, więc mogę uruchomić "Windows 7", mam tam trochę archaicznego softu do wiekowych CPLD/FPGA, czy innych archaicznych sprzętów, więc trzymam ten system, tyle że niezbyt często uruchamiam już tego Windows 7, ale karta nadal działa. Co prawda Linux już ma sterownik pod dla chipa EMU-10K1, ale w przypadku EMU-1212M działa tylko podstawowa funkcjonalność (play/rec) nie ma rozbudowanego mixera czy też pluginów dla DSP.

The Klątwa Set - Part II: Tajemnice przeklętej taśmy

Wstęp, czyli zanim zacznie się właściwa klątwa

To był spokojny majowy wieczór 2026 roku. Dość dziwny był ten maj, bo całkiem chłodny, i nic nie zapowiadało wydarzeń, które miały za chwilę nastąpić...

No dobra, żartuję sobie trochę ;P, ale nie mogę obiecać, że dalej będzie "normalniej". Tematy, które tutaj poruszam, nie są przeznaczone dla ludzi "normalnych" - takie rzeczy tylko dla retro-świrów ;) Zatem zapnijcie pasy i jedziemy z tematem. Jak to u mnie bywa, zanim dopłynę do brzegu, poruszę pewnie masę tematów pobocznych i będę opowiadał o sprawach, które mój mózg jakoś łączy w jedność, choć większość ludzi nie zobaczy w tym żadnego "wspólnego mianownika" ani spójnej, logicznej całości... Wybaczcie, ja już tak mam ;-) Nie da się mnie naprawić.

Sprzęt do zgrywania, czyli dlaczego SHARP i Tascam

Operacja zgrywania kasety zaczęła się jak zwykle: stary deck SHARP, rejestrator cyfrowy Tascam DR-05X. Dlaczego taki zestaw do zgrywania? To zaraz się wyjaśni. Na początku chciałem jednak pokrótce opisać drogę, którą przeszedłem przy zgrywaniu taśm. Być może w jakiś sposób pomoże to komuś w przyszłości, jeśli zechce powalczyć ze starymi kasetami.

Wiem, że czekacie na opis zawartości kasety, ale skoro już jestem w fazie "lania wody", to wykorzystam ten moment "twórczego amoku" mojej słabości do opisania paru faktów z przeszłości. Liczę, że może kogoś zachęci to do zgrywania kaset, które ma pod ręką. Nigdy nie wiadomo, czy nie ma tam jakichś ciekawych artefaktów z przeszłości.

Zaczynałem - nazwijmy to może dość łagodnie - od "przerostu formy nad treścią", a potem stopniowo upraszczałem swoją konfigurację. Piszę o tym tylko dlatego, abyście nie sądzili, że do takich operacji potrzebna jest jakaś superkosmiczna konfiguracja i studyjny sprzęt za grube pieniądze. W 99% przypadków wystarczą proste i tanie rozwiązania. Ja mogę służyć tutaj jako "anty-przykład", z tym że ja ten sprzęt miałem już wcześniej i wykorzystywałem go do innych celów. To nie było tak, że kupiłem go specjalnie na potrzeby zgrywania kaset.

Początkowo do zgrywania kaset używałem komputera PC, karty "E-MU 1212M" oraz decka Technics RS-BX501. Ta konfiguracja była jednak zdecydowanie "przewymiarowana" i zupełnie niepotrzebna. Do tego miała poważną wadę: konstrukcja samego decka oraz jego mechanizmu z obrotową głowicą (auto-reverse) była zupełnie nieprzystosowana do łatwej regulacji głowicy przez użytkownika. Kasety zgrywałem zatem z fabrycznym ustawieniem głowicy, co w przypadku niektórych kaset stanowiło problem, ponieważ były one nagrane na różnych rozklekotanych sprzętach, często z "losowym" ustawieniem głowicy.

Z czasem trafiłem na takiego taniutkiego SHARP-a z lat 80., w którym bardzo łatwo można było zdjąć osłonę szuflady, do której wkłada się kasetę. Dzięki temu mam łatwy dostęp do śruby regulującej skos głowicy, co umożliwiało mi indywidualne dobranie skosu głowicy do każdej kasety, która wpadała w moje ręce.

Warto jednak krótko wyjaśnić, że w przypadku kaset w kiepskim stanie, nagranych na magnetofonach z rozjechaną/rozregulowaną głowicą, taki zabieg pozwalał mi wyciągnąć największą możliwą stromość zboczy odczytywanego sygnału. Każda odchyłka głowicy od idealnego środka ścieżki magnetycznej powodowała utratę tonów wysokich, a co za tym idzie - zmniejszenie stromości zboczy sygnału reprezentującego zapisane dane.

Ten stary SHARP, w którym mogłem bez problemu kręcić głowicą, sprawdził się o wiele lepiej niż jakiś Technics z garścią dodatkowych systemów na pokładzie - zupełnie nieużytecznych w przypadku zgrywania "surowych danych" z kaset, które przez "naście" lat leżały często w mało komfortowych warunkach.

A skąd w ogóle pomysł na E-MU? To nie była moja fanaberia ani wymysł, że potrzebuję super jakości 24-bit/192 kHz, aby zgrywać stare kasety. Karta była wykorzystywana przeze mnie wcześniej, gdy pomagałem Xray-owi w przygotowywaniu różnych materiałów dla Radia UXA. A to zgrywałem jakieś kawałki z OPL3/Adlib, C64/SID czy też paru innych platform. Karta sprawdziła się znakomicie w tej roli. Wcześniejszy Behringer BCA-2000 umarł śmiercią naturalną wraz z Windows XP, na którym producent postanowił zakończyć jego wsparcie - no ale dość dygresji. Chodziło mi jedynie o wyjaśnienie, że nie kupowałem E-MU 1212M tylko po to, aby zgrywać stare kasety z programami dla Atari ;-) Zapewne w większości przypadków sprawdzi się dowolna karta dźwiękowa, nawet ta wbudowana w system, którego używacie.

Początkowo, gdy używałem E-MU 1212M, a były to czasy, gdy królował jeszcze Windows 7 (E-MU działało sprawnie jedynie pod Windows), wszystko sprawdzało się idealnie. Soft dołączony do karty świetnie sprawdzał się przy zgrywaniu danych, nie gubił żadnych próbek, sterowniki ASIO działały znakomicie, a cały proces zgrywania materiału mógł działać w tle, podczas gdy ja wykorzystywałem komputer do robienia innych rzeczy. Z czasem kolejne poprawki dla systemu Windows powodowały coraz większe problemy z działaniem E-MU. Firmę "E-MU Systems" kupił Creative Labs, co skończyło się porzuceniem produktu i jego naturalną śmiercią: brakiem aktualizacji sterowników, coraz większymi problemami z zapewnieniem jakości zgrywanego strumienia danych itd.

Ja jeszcze przez jakiś czas próbowałem eksperymentów z innymi rozwiązaniami, ale szybko doszedłem do wniosku, że mam dość walki z tym wszystkim (uśmiercaniem produktów poprzez brak wsparcia i aktualizacji sterowników przez producentów) i że jedyną sensowną drogą jest jakieś urządzenie, które działa niezależnie, nie potrzebuje aktualizacji i po zakupie nie może zostać uśmiercone przez producenta przez brak sterowników czy zakończenie wsparcia. Zacząłem się przyglądać różnym rozwiązaniom dostępnym na rynku.

Początkowo co prawda wymyśliłem sobie, że sam mogę zrobić jakiś rodzaj rejestratora - ale wiecie co, zacząłem grzebać i szybko mi się znudziło. W dodatku zobaczyłem, że są gotowe rozwiązania, dostępne od ręki. Zacząłem się przyglądać różnym rejestratorom cyfrowym i koniec końców mój wybór padł na TASCAM DR-05X. Czemu akurat ten? Bo trafiłem na niego, gdy był dostępny w jakiejś promocji, w całkiem rozsądnej cenie.

Użycie niezależnego rejestratora cyfrowego umożliwiło mi "uwolnienie" komputera od procesu zgrywania kaset. Nie musiałem już pilnować, czy coś dzieje się w tle, nie musiałem również uważać, aby nie zrobić restartu albo nie spowodować takiego dociśnięcia CPU, że program zgrywający dane zacznie się "dusić" i pominie jakieś próbki ze strumienia danych napływającego z karty dźwiękowej.

Wrzucałem kasetę, regulowałem głowicę (albo na ucho, albo z użyciem oscyloskopu), wciskałem REC na rejestratorze i mogłem zająć się czymś innym. Po kilkudziesięciu minutach plik audio był bezpiecznie zapisany na karcie micro-SD.

Powrót do przeklętej kasety

Ufff! Teraz chyba możemy wrócić do przerwanego wcześniej wątku...

Operacja zgrywania kasety zaczęła się jak zwykle: stary deck SHARP, rejestrator cyfrowy Tascam DR-05X, ustawienie głowicy "na słuch", wciśnięcie "REC" na rejestratorze, ustawienie poziomów i zajęcie się czymś innym na najbliższe 45 minut. Kaseta SKC, na której były zapisane programy, miała bowiem 90 minut długości (po ~45 minut na stronę).

Pierwsze objawy klątwy

Po zgraniu strony A przeniosłem plik audio (WAV, 48 kHz, 16-bit), szybko wrzuciłem go do Audacity i zacząłem słuchać oraz "oglądać" kształty zgranych fal. Wtedy zacząłem dostrzegać pierwsze oznaki "klątwy".

Tymi oznakami były nietypowe pyknięcia w sygnale pilotującym. Po drugie, natychmiast zauważyłem, że już pierwsze nagranie nie jest zapisane w standardowym formacie "Turbo 2000". Pierwszy blok był standardowy, jednak to, co następowało dalej po pierwszym bloku danych, nie było dalszymi standardowymi rekordami danych. "Na słuch" początkowo wyglądało to jak coś w stylu "*Speedy 2700/*AJEK", jednak po chwili słuchania dotarło do mnie, że to nie jest "Speedy 2700". Ten format danych brzmiał inaczej. Wyglądało na to, że pomiędzy impulsami 0/1 występują tony brzmiące jak "sync/pilot". Wtedy zaczęło mi coś majaczyć w pamięci: że kiedyś na giełdzie przy ul. Saskiej chłopaki wspominały o nowym formacie zapisu i nowej wersji oprogramowania systemowego dla Turbo 2000F.

Mając plik wave już na dysku, mogłem zacząć robić szybkie eksperymenty z użyciem emulatora. Do dyspozycji miałem Atari800 5.2.0 zmodyfikowany przez FUJI-ego tak, aby wspierał obsługę systemów turbo, lub Altirra, którą musiałem uruchamiać z użyciem Wine (używam Linuksa jako systemu operacyjnego "codziennego użytku").

Aby już nie przedłużać tego wywodu, powiem tylko, że chwilę mi zajęło, zanim zorientowałem się, czemu nie mogę poprawnie wczytać żadnego programu zgranego z tej kasety. Albo pojawiał się błąd 140 przy próbie wczytywania pierwszego bloku, albo - gdy już udało się to zrobić - następowało natychmiastowe wysypanie się komputera. Praca na emulatorze przyspieszyła zorientowanie się, co i gdzie się sypie oraz dlaczego. Szybko odkryłem, że pierwszy blok to loader, który próbuje ładować się bardzo nisko, przez co nadpisuje system turbo ulokowany w pamięci (używałem obrazu zrzuconego z cartridge'a "Klątwa"). Następne kroki polegały na użyciu wersji systemu Turbo 2000F od MUEL, który lokował się pod OS-ROM. Dzięki temu mogłem sprawdzić poprawność wczytywania programów zapisanych w "nowym formacie".

Co udało się odczytać ze strony A

Po wstępnej analizie zgranego materiału ze strony A okazało się, że ktoś przeprowadzał sobie na tej taśmie jakieś eksperymenty. Część gier została nadpisana inną zawartością, część była ucięta, a fragmenty niektórych nagrań były nieczytelne (pozostałości po starym/poprzednim zapisie). Zacznijmy może zatem od spisu tego, co udało mi się z tej kasety odczytać - oto "spis treści":

[NEW] Little Devil
[NEW] Decathlon
[NEW] Skateboard
[OLD] Tutunkhamun
[NEW] Jet Set Willy
[OLD] Kick Off [loader only]
[OLD] Hans Kloss
[---] nieczytelne pozostałości starego nagrania (Kick Off?)
[NEW] Screaming Wings
[NEW] Draconus (obcięty koniec nagrania)
[NEW] Rechnung Simulation
[NEW] TOTO-SYSTEM
[---] nieczytelne pozostałości
[OLD] Silent Service (LO-MEM SYS / loader)
[OLD] Silent Service (main program)
[NEW] Sex Test
[NEW] Moon Patrol
[NEW] Nadral
[NEW] Aztec
[NEW] Da'FUZZ
[NEW] Spellbound
[NEW] Zaxxon
[NEW] Taipei
[NEW] Draconus
[NEW] Super Cobra
[OLD] Fantastic Soccer (LO-MEM SYS / loader)
[OLD] Fantastic Soccer (main program)
[NEW] Yogi Bear and Friends in the Greed Monster
[NEW] Stack Up
[---] nieczytelne pozostałości poprzedniego nagrania
[NEW] World Soccer

Teraz mogę dodać krótki komentarz do powyższego spisu. [NEW]/[OLD] oznaczają format, w jakim zapisano daną grę/program. Pozycje oznaczone [---] to nieczytelne fragmenty.

Część "oryginalnych" pozycji na kasecie została nadpisana innymi programami. Np. gra "Kick Off" została ewidentnie nadpisana grą "Hans Kloss". Idąc dalej: końcówka gry "Draconus" (tej nagranej zaraz za Screaming Wings) została uszkodzona, tzn. ostatni segment gry, zawierający wektor RUN, jest ucięty, przez co loader "new format" nie uruchamia gry, tylko wraca do nadrzędnego systemu turbo.

Przyglądając się pozycjom Silent Service, Fantastic Soccer, World Soccer i analizując dodany "loader", z całą pewnością można potwierdzić, że ta kaseta była stworzona/nagrana dla systemu Turbo 2000F lokującego się pod OS-ROM. Skąd to stwierdzenie? Otóż ten "loader" to nic innego jak wersja systemu Turbo 2000F, która po załadowaniu lokuje się w niskich regionach pamięci (od $0700), ustawiając MEMLO na $199D (o ile dobrze zapamiętałem). Zresztą bardzo łatwo się o tym przekonać: po załadowaniu takiego loadera wciskamy RESET i lądujemy w wersji systemu Turbo 2000F, który siedzi na dole pamięci.

Ten właśnie "loader" nagrano przed grami, które podczas wczytywania ładowały się do pamięci pod OS-ROM. Właśnie stąd wniosek, że owa kaseta była używana z wersją cartridge'a, który zawierał soft dla Turbo 2000F ładujący się pod OS-ROM.

To jednoznacznie potwierdza, że cartridge "Klątwa" nie mógł poprawnie załadować większości programów zapisanych na tej kasecie. Żadna pozycja zapisana w "new format" nie miała szans, bo loader "nie współpracował" z softem zaszytym w karcie. Byłaby natomiast szansa na wczytanie pozycji "Hans Kloss", "Silent Service" czy "Fantastic Soccer", gdyby nie "pyknięcia" obecne w tonie pilotującym, których nie trawi wersja softu z "Klątwy".

Krótki bilans odzysku

Finalnie udało się odzyskać wszystko, co nie było na taśmie fizycznie zniszczone albo realnie nadpisane inną zawartością. Pliki, które sprawiały problemy, potraktowałem różnymi  metodami korekcji, filtracji i wzmocnienia sygnału - dałoby się o tym napisać kolejne kilkadziesiąt kilobajtów, ale to już temat na osobny wpis, a nie na tę część sagi.

Przetwarzanie WAV do HEX

No ale kurczę, do brzegu... do brzegu... Płynąc dalej, mogę napisać parę słów o tym, jak wyglądał proces przetworzenia zgranego pliku dźwiękowego. W tym wypadku, ponieważ zgrałem całą stronę jako jeden plik, używając emulatora i obrazu carta Turbo 2000F, próbowałem wczytywać "na żywca" poszczególne pliki, jednocześnie zaznaczając w projekcie miejsca, gdzie zaczynają się i kończą poszczególne nagrania. Po zakończeniu obróbki wyglądało to mniej więcej tak:

https://pigwa.code32.org/uicr0bee/tapes/skc_new_format/pics/audacity_cursed_tape_prj.png

Mając już tak "obrobiony" projekt, bardzo łatwo mogłem dokonać eksportu poszczególnych fragmentów nagrania do oddzielnych plików ".wav". Potem do akcji wkraczał a8cas-util.pl, który rozpoznaje zarówno klasyczny format Turbo 2000/F/KSO, jak i pojedyncze bloki danych zapisane niezależnie. Konwersja przebiegała mniej więcej w ten sposób:

a8cas-util.pl conv -t turbo2000 05_jest_set_willy_05.14_07.08.dlt.wav 05_jest_set_willy_05.14_07.08.dlt.hex
Starting ecasound... started.
SUMMARY: Data blocks: 29 (0 Errors).
62 HEX blocks stored in file 05_jest_set_willy_05.14_07.08.dlt.hex.

Oczywiście zdarza się, że plik nie poddaje się konwersji bez różnych problemów. Wtedy przyglądam się plikowi w Audacity i stosuję różne korekcje albo zmiany parametrów konwersji.

Konwersję wykonuję zwykle do plików .hex, aby móc szybko obejrzeć strukturę przetworzonego nagrania. Gdy już otrzymam "paczkę" plików *.hex, które udało się skonwertować bez błędów, to teoretycznie mógłbym uznać sprawę za zakończoną i takie pliki opublikować. Najpierw chciałbym jednak, abyśmy przyjrzeli się strukturze takiego pliku "HEX", zawierającego opis struktury pliku po konwersji z pliku .wav.

Anatomia pliku HEX

Zapytacie: po co? To stanie się jasne nieco później. Na początek przykład na fragmencie pliku z kasety "Klątwy". Jest to gra "Jet Set Willy", zapisana w nowym formacie. Oczywiście powycinałem masę danych nieistotnych dla problemu, który chcę naświetlić. "..." reprezentują wycięte dane nieistotne dla tego przykładu.

A8CAS-HEX
FUJI 
pwms msb_first rising_edge_first 48000
pwmc 00093 46 4024 ; count=1
pwmd 12 23 00 ff 50 52 4f 47 52 41 4d 3a 35 20 a6 ; block no=1 ; length=13 ; checksum(modulo256)=a6 OK
pwmc 00000 46 1 ; count=1
pwmc 00151 46 584 12 1 23 1 46 3463 ; count=4
pwmd 12 23 f5 01 ff ff 06 08 ee 09 a9 80 8d 21 09 a9 00 ... 00 00 a9 ; block no=2 ; length=3075 ; checksum(modulo256)=a9 OK
pwmc 00000 46 1 46 1792 ; count=2
pwmd 12 23 ff ff 00 0c b4 19 d7 00 ; block no=3 ; length=8 ; checksum(modulo256)=d7 OK
pwmc 00000 46 11 ; count=1
pwmd 12 23 00 00 00 00 00 00 00 00 00 00 00 e0 f0 38 ... 01 70 00 ; block no=4 ; length=3511 ; checksum(modulo256)=70 OK
pwmc 00001 46 6 ; count=1
pwmd 12 23 00 20 75 29 be 00 ; block no=5 ; length=6 ; checksum(modulo256)=be OK
pwmc 00000 46 11 ; count=1

Zatem co widzimy w takim pliku? Nie wnikając w format zapisanych danych, chodzi mi tylko o fizyczną budowę takiego pliku HEX opisującego to, co "działo się" na taśmie.

Na początku mamy prosty nagłówek identyfikujący plik:

A8CAS-HEX
FUJI 

Po nagłówku następuje sekcja "pwms", która mówi o tym, jak traktować i interpretować dane oraz bloki (np. pwmc, pwmd) występujące dalej w pliku:

pwms msb_first rising_edge_first 48000

^^^ to mówi nam, że transmitowane bity są w kolejności od najstarszego (msb_first), potem że jako pierwsza leci narastająca krawędź zbocza (rising_edge_first), a następnie mamy określoną częstotliwość próbkowania. Ta częstotliwość jest kluczowa dla wyznaczenia czasu trwania impulsów, które reprezentują poszczególne stany (np. pilot, 0, 1).

Teraz warto zastanowić się, co tak naprawdę reprezentują bloki pwmc i pwmd. Zacznijmy może od bloku "pwmc":

pwmc 00093 46 4024 ; count=1

Co oznaczają te liczby?

  • 00093 oznacza długość "ciszy" występującej przed rozpoczęciem sekwencji danych (w tym wypadku 93 ms).

  • 46 oznacza długość pojedynczego impulsu (długość wyrażona w próbkach danych, tzw. samples). Aby obliczyć czas trwania, musimy pomnożyć długość impulsu przez odwrotność częstotliwości próbkowania (określonej w bloku pwms). W tym wypadku 46 próbek * (1/48 kHz) = 0,958 ms. Patrząc na specyfikację struktury zapisu dla formatu Turbo 2000, możemy domyślić się, że ta długość jest po prostu pilotem/tonem synchronizującym.

  • 4024 - ta liczba określa liczbę impulsów, które zostaną wygenerowane.

Zestawiając to ze specyfikacją formatu, ten blok opisuje wstępny ton pilotujący, który powinien zawierać 4096 impulsów o długości 1 ms. Teoria teorią, a rzeczywistość rzeczywistością... Jak widać, po pierwsze długość impulsu nie wynosi dokładnie 1 ms, a po drugie a8cas-util wyliczył tylko 4024 impulsy zamiast 4096. Oczywiście jest to zupełnie normalne zjawisko. Po pierwsze, prędkości obrotowe silników zarówno magnetofonu zapisującego, jak i odczytującego mogą się nieznacznie różnić. Po drugie, będzie występowała nieliniowość przesuwu taśmy. Po trzecie, start silnika powoduje, że początkowe impulsy nie będą miały odpowiedniej długości i nie będą traktowane jako ton pilota. Wszystko to będzie powodowało, że każdy z takich zdekodowanych bloków będzie miał nieco inne parametry (w tym wypadku mozolnie obliczane przez a8cas-util).

Oczywiście procedury odczytu danych są na te wszystkie "niedoskonałości" zapisu przygotowane i wykazują się dużą tolerancją na tego rodzaju odchyłki. Dlatego to wszystko działa mimo tego, iż sam zapis magnetyczny, jak i taśma, na której jest on dokonywany, są dalekie od doskonałości.

Dodam jeszcze szybko opis bloku pwmd:

pwmd 12 23 00 ff 50 52 4f 47 52 41 4d 3a 35 20 a6 ; block no=1 ; 

^^^ ta sekcja zawiera 3 znaczące części: pierwsze dwie liczby (uwaga! są w formacie dziesiętnym!) określają długości impulsów reprezentujących stany logiczne dla "0" i "1", a dalej występuje blok bajtów zapisanych jako ciąg cyfr hex, znajdujący się w danym bloku danych. W tym wypadku:

  • 12 - oznacza długość impulsu kodującego logiczne "0" --> 12 * (1/48 kHz) = 0,25 ms

  • 23 - oznacza długość impulsu kodującego logiczne "1" --> 23 * (1/48 kHz) = 0,497 ms

  • następne bajty to zawartość danego bloku danych

Jak widać na ww. przykładzie, długości impulsów "0" i "1" mieszczą się prawie idealnie w specyfikacji dla formatu Turbo 2000, czyli:

  • "0" - impuls 0,25 ms

  • "1" - impuls 0,5 ms

  • "pilot" - impulsy o długości 1 ms

Normalizacja i ręczne egzorcyzmy

Teraz możemy wrócić do powodu, dla którego o tym wszystkim piszę. Teoretycznie wystarczyłoby te pliki .hex zamienić na .cas albo od razu konwertować je do formatu .cas, jednak uznałem, że skoro dokonujemy odczytu i odzyskiwania plików z kaset nierzadko w stanie agonalnym, to warto takie pliki po konwersji przywrócić do stanu "idealnego", tzn. zgodnego ze specyfikacją danego formatu (czy to będzie Turbo 2000, Blizzard, AST, etc.).

Pisząc "stan idealny", mam na myśli np. wyrównanie długości wszystkich impulsów, wyrównanie długości tonów sync/pilot, etc.

Idąc za ciosem: wyżej widać było, że długość impulsu pilota wynosiła 46 próbek (wartość idealna w przypadku plików 48 kHz to 48, gdyż 48 * (1/48 kHz) = 1 ms), "0" --> 12 (wszystko ok), "1" --> 23 (niewielka odchyłka, bo wartość idealna to 24).

Dlatego po takiej konwersji w większości przypadków "normalizuję" takie pliki, korygując wszystkie odchylenia od wartości standardowych.

Cały powyższy opis i tłumaczenie znaczenia poszczególnych liczb w pliku .hex miały na celu ułatwienie wam zrozumienia całego procesu i sposobu mojego postępowania. Być może zainspiruje to też kogoś do rozpoczęcia takich działań we własnym zakresie.

Jakie narzędzia wykorzystuję do tego celu? Początkowo robiłem to "półautomatycznie", używając edytora tekstowego i funkcji search&replace, jednak z czasem stało się to na tyle monotonne, że obecnie automatyzuję cały proces. Często wystarczy sed/awk, czasem prosty skrypt w Perlu, a coraz częściej jakiś skrypt w Pythonie. Początkowo walczyłem dzielnie i pisałem sobie jakieś dziwne wyrażenia regularne, jednak w dzisiejszych czasach, jeżeli dobrze napisze się prompt, to dowolny LLM bez problemu poradzi sobie z takim zadaniem, generując np. odpowiedni skrypt w Pythonie do przetworzenia wszystkich plików .hex do określonej, "znormalizowanej" postaci.

Jak było w tym wypadku? Wszystkiego po trochu. W niektórych przypadkach również "ręczna" edycja plików .hex i poprawki w krytycznych miejscach (np. uszkodzone bloki z nazwami plików), czasami jakiś skrypt w Perlu. Tutaj np. jeden z Perl-owych przykładów zmieniający długość pilota występującego po loaderze:

perl -pi.bak -e 's/^(pwmc 0000[01] 48 )2048(\s*;.*)?$/${1}2560${2}/' *.hex

^^^ zmieniamy długości wszystkich tonów pilotujących o długości 2048 impulsów na takie, które mają 2560 impulsów. Na wszelki wypadek tworzymy sobie od razu kopię plików (.bak).

Czasami nie da się zautomatyzować całego procesu i pozostaje ręczne dłubanie. Dotyczy to np. nagrań uszkodzonych lub taśm słabej jakości, z których mało co da się wycisnąć na poziomie automatycznego odzyskania czytelnego zapisu. Wtedy pozostaje ręczne dłubanie, zgadywanie i uzupełnianie brakujących fragmentów zapisu albo bajtów w wynikowym pliku .hex.

Po doprowadzeniu wszystkiego do jakiego takiego porządku i przetestowaniu, że wszystko się wczytuje, można dokonać konwersji na pliki .cas.

Od jakiegoś czasu uznałem, że nie ma sensu publikować oryginalnych ("surowych") plików .wav, bo po pierwsze zajmuje to dużo miejsca na serwerze, a po drugie często te pliki nie mają wartości bez odpowiedniej obróbki czy korekty. Byłyby kolejnym śmieciem w internecie, na który ktoś po latach by trafił i zmagał się z takim artefaktem, nie wiedząc, co się właściwie dzieje. Jeżeli uważacie inaczej, dajcie znać - mogę wrzucać i "surowe" zrzuty, o ile pigwa wytrzyma ;D

A i jeszcze jedno. Wcześniej pisałem o tych "pyknięciach" występujących w tonie pilotującym, które rozkładały na łopatki procedurę odczytu, powodując błąd 140. Tak wyglądało to w surowym pliku po konwersji:

pwmc 00151 46 584 12 1 23 1 46 3463 ; count=4

^^^ Jak widać, na tych "pyknięciach" potykał się "trochę" a8cas-util. Interpretując powyższy blok pwmc, widzimy, że:

  • na początku mamy 151 ms ciszy

  • 584 impulsy tonu pilota (długość imp. 46)

  • jeden impuls "0" (długość imp. = 12)

  • jeden impuls "1" (długość imp. = 23)

  • 3463 impulsy tonu pilota (długość imp. 46)

Jak widać, śmieć na taśmie był interpretowany przez a8cas-util jako sekwencja bitów 0 i 1 następujących po sobie. To wystarczyło, aby procedura odczytu potraktowała te impulsy 0,1 jako początek bloku danych (skończył się już sync tone). Jednak po chwili znowu pojawiały się impulsy o długości tonu pilota, co powodowało, że procedura odczytu protestowała, bo po dwóch bitach danych pojawiał się impuls o długości, której procedura odczytu już nie dopuszczała po jej zdaniem "poprawnej" synchronizacji. To kończyło się błędem odczytu nr 140.

Co z tym zrobić? Najłatwiej poprawić takie bloki pwmc ręcznie, zastępując tę całą serię jednostajnym tonem pilotującym:

pwmc 00151 48 4096 ; count=1

Pliki CAS i wymagany system Turbo 2000F

Nie przynudzając dalej, nie pozostaje mi nic innego, jak wrzucić linki do plików CAS, które zostały już poprawione, "znormalizowane" i oczyszczone z większości zbędnego śmiecia (przynajmniej tego, który zauważyłem): "The Klątwa Tape" - archiwum zawiera pliki hex/cas. Wszystkie pliki są w takim stanie, w jakim były na oryginalnej taśmie (pozostawiłem oryginale loadery, nie podmieniałem żadnych plików), a więc pliki w "new format" zawierają oryginalny loader, który wymaga odpowiedniej wersji Turbo 2000F.

Dodać należy, że są to pliki "znormalizowane" i oczyszczone (mówię tutaj o długościach impulsów, pilotów, etc. zero ingerencji w dane zapisane na taśmie), jednak nadal pozostaje problem: jak je wczytać? W pierwszej części opisywałem, że loader "new format" wymaga konkretnej wersji systemu Turbo 2000F - tej lokującej się pod OS-ROM i mającej MEMLO na poziomie $0800. Taką wersją systemu jest np. wersja, którą dystrybuowała ze swoim Turbo 2000F firma MUEL. Poniżej w archiwum znajduje się zarówno obraz cartridge'a, jak i wersja .XEX, którą można uruchomić z dowolnie wybranego medium. Plik .bin (obraz carta) należy uruchamiać jako typ "Blizzard 4K cartridge". Zmodyfikowałem minimalnie kod procedury startowej, aby sama odłączała cartridge, co ułatwia testy pod emulatorem. Archiwum do pobrania tutaj: Muel Turbo 2000F - wersja rezydująca pod OS-ROM.

Strona B

A co ze stroną B? Otóż strona B nie zawierała sensownej zawartości. Ktoś próbował nagrać sobie kilka razy grę "Snowball". Przyznam, że jakość tego materiału była na tyle mało warta uwagi, że zupełnie się nim nie zajmowałem.

Ciekawostka crack-scenowa

Może poruszę jeszcze jeden temat. Na taśmie znajdują się dwie interesujące pozycje, biorąc pod uwagę atarowską crack-scenę, mianowicie:

Yogi Bear and Friends in the Greed Monster oraz Stack Up to releasy sygnowane przez Bloody Coders - taka ciekawostka historyczna. Pliki spakowane są za pomocą Power Packer-a z Amigi.

Co dalej?

Na dziś to chyba na tyle. Pozostaje mi do napisania część trzecią, w której udostępnię kod źródłowy nowej wersji loadera - takiej, która zadziała z każdą wersją cartridge'a. Dodatkowo udostępnię pliki .cas zawierające "odklątwioną" wersję plików z tej kasety. Te pliki CAS będzie można ładować używając dowolnego cartridge'a zawierającego system z serii 200X (2000F, 2001, KSO). Trzecia część chyba będzie najkrótsza. Muszę tylko nieco uporządkować źródła i wrzucić repo na GitHub.

PS: kolejny objaw klątwy

Już przy ostatnim teście dopadła mnie kolejna część klątwy. Zauważyłem, że pozycje Silent Service, Fantastic Soccer oraz World Soccer, do których dołączony jest loader - a właściwie cały system Turbo lokujący się na dole pamięci - mają problem z uruchomieniem. Ściślej mówiąc, problem dotyczy uruchomienia tego loadera w systemie Turbo 2000F od MUEL, do którego linkowałem powyżej. Tego problemu nie ma natomiast w przypadku użycia Turbo 2000 (pozycja 1 z menu) z cartridge'a od SONIX, o którym wspominałem w pierwszej części. Nie wnikałem co jest powodem bo wyszło mi to dosłownie przed chwilą,  ale ponieważ chcę już opublikować ten post, zostawiam wszystko w takim stanie jak jest. Tym bardziej, że za chwilę będę wrzucał "poprawioną" wersję plików z tej kasety - czyli wszystko w formacie "NEW", z nowym loaderem, który powinien uruchomić się z każdej wersji systemu.

ps2) część tej klątwy (MUEL) wyjaśniona, powodem był problem z tym że w emu miałem włączone urządzenie "H:", a loader w ciemno zakładał standardową konfigurację i zerował część tablicy HTABS "na ślepo", co powodowało że usuwał wpis dotyczący urządzenia "H:", zamiast "D:", a ponowa próba instalacji handlera dla urządzenia "D:" kończyła się niepowodzeniem.

@baktra: No było dokładnie tak jak piszesz. Wszystko zależne od wszystkiego, albo od konfiguracji piszącego dany kod. Zero uniwersalności, czysty "hack" na "hacku" ;-) ... nie raz sam tak pisałem mając "naście" lat... wtedy nie do końca i tak rozumiałem co robię, ale to nie było dla mnie żadną przeszkodą! Na szczęście moje programy tego typu nie rozeszły się po świecie, pewnie nawet już taśmy na których się znajdowały nie nadają się do odczytu :D

tOri napisał/a:

Chapeau bas!

Bardzo dziękuję za miłe słowa! Ja również chylę głowę przed Twoimi projektami i całą inżynierią wsteczną którą praktykujesz i dzielisz się ze światem. Przy Twoich osiągnięciach moje zabawy z magnetofonami, cartami i kasetami to jest wręcz poziom "przedszkola" :)

x_angel napisał/a:

Ja miałem jakieś 14-15 lat i swoje montowałem sam. Kieszonkowego ledwo na Turbo wystarczyło nie było mowy o montażu :)

Ja też mogłem mieć jakieś 14-15 lat, nie bardzo pamiętam już czy to był początek lat '90 czy jeszcze czas tuż przed '90. Niestety nie pamiętam już dokładnie szczegółów, ale ten człowiek który mi montował to turbo, albo wcale nie wziął ode mnie pieniędzy, albo to były jakieś grosze. Czasy były jakie były... jako dzieciak nie dysponowałem żadnymi znaczącymi środkami pieniężnymi które mogłem przeznaczyć na takie wydatki. Zresztą na pewno obawiałbym się sam dłubać w tym XC12 na który tak długo czekałem :) potem oczywiście rozkręciłem ten magnetofon jak popatrzyłem jak ten człowiek to montuje to wtedy dopiero nabrałem odwagi do własnoręcznego dłubania.

Hrw napisał/a:

Cartridge miał chyba jakiś kopier z obsługą N: właśnie do zapisu bez przerw.

A widzisz! Ciekawa i cenna informacja! To ja pierwszy raz kopier który zapisuje w "new format" zobaczyłem na dopiero jak w tym wątku pojawił się ten cart od SONIX. Na saskiej mieli co prawda dwie odmiany softu systemowego dla Turbo 2000F (stary lokujący się nisko w RAM i ten oznaczony literą "N", lokujący się po OS-ROM). Ale żaden z tych systemów czy cartów nie posiadał wbudowanego kopiera dla "nowego formatu". Również na kasecie "systemowej" nie było nic takiego dostępne. Być może piraci giełdowi trzymali to rozwiązanie dla siebie, bo trafiałem gry zapisane w tym formacie od czasu do czasu.

x_angel napisał/a:

Turbo było na drugi port joysticka, w zestawie była płytka z kabelkiem, taka instrukcja-kserówka i chyba zamawiało się od razu jakąś kasetę.

Ja też miałem takie turbo, czyli tzw. "KSO Turbo 2000" dokładnie tę wersję z kablem do drugiego portu joysticka. Tyle że w moim wypadku ten interface zamontował mi człowiek mający swoje stanowisko na giełdzie komputerowej w technikum chemicznym na ulicy Saskiej. On chyba po prostu miał dość jak prosiłem go o nagrywanie mi programów na kasety w "normalu" ;-) Mam ten magnetofon do dziś... pewnie kiedyś przyjdzie pora na opis również tego "zabytku" :D

The Klątwa Set - Part I: Anatomia przeklętego zestawu

To będzie pierwsza część nieco dłuższej opowieści o kasecie dołączonej do zestawu "Klątwa". W tej części opisuję sam zestaw, problem z kompatybilnością różnych wersji software dla Turbo 2000F oraz powód, dla którego ta konkretna konfiguracja praktycznie nie miała prawa działać. W kolejnej części przejdę już do samej zawartości kasety i tego, co udało się z niej odzyskać.

Pewnie pamiętacie, jak parę postów temu opisywałem cartridge dla "Turbo 2000F" z doklejonym napisem "Klątwa". Do kompletu do tego cartridge'a był również magnetofon z przeróbką "Turbo 2000F" oraz kaseta z programami zapisanymi w Turbo 2000F, która teoretycznie powinna się wczytywać z użyciem magnetofonu oraz cartridge'a przeznaczonego dla tego systemu.

Po przywróceniu magnetofonu do życia mogłem wreszcie przetestować całą konfigurację. Naprawa objęła dołożenie brakującego kabelka SIO, wymianę wzmacniacza operacyjnego LM324, zastąpienie połamanych styków czujnikami Halla - o czym też wkrótce napiszę - wymianę kilku kondensatorów, pasków oraz licznika. Ten ostatni był połamany i wcześniej zalany czymś lepkim i żrącym.

Do przetestowania miałem więc następujący komplet:

  • magnetofon CA12 z Turbo 2000F,

  • cartridge z systemem "Turbo 2001",

  • kasetę z programami zapisanymi w systemie Turbo 2000F.

Teoretycznie wszystko powinno zadziałać. Przed rozpoczęciem prób na realnym sprzęcie zgrałem jednak kasetę do postaci cyfrowej, żeby mieć kopię na wypadek jakiejś nieplanowanej katastrofy - na przykład wkręcenia taśmy, gdyby CA12 postanowił zrobić sobie psikusa. :P

Już pierwsze, wstępne analizy zgranej kasety zaczęły mi dawać pewien obraz sytuacji. Powoli zaczynałem się domyślać, skąd mogła wziąć się naklejka "Klątwa". Wszystko układało się w historię tak nieprawdopodobną, że trudno uwierzyć, aby poprzedni właściciel tej kombinacji sprzętu miał aż takiego pecha przy jej kompletowaniu.

Spróbuję to wyjaśnić dość prostym językiem i w miarę zwięźle, opisując mój tok postępowania.

Zaczęło się od obserwacji przebiegu WAV zgranej kasety. Analizując fragmenty nagrań zauważyłem, że magnetofon, na którym dokonano zapisu programów, miał pewną przypadłość. Po rozpoczęciu zapisu, jeszcze w trakcie tonu synchronizującego, pojawiało się krótkie zniekształcenie sygnału - ostre zbocze słyszalne jako charakterystyczne "pyknięcie".

Samo w sobie nie musiałoby to być dużym problemem, ale tutaj pojawia się istotny szczegół: istniało kilka odmian oprogramowania dla systemu Turbo 2000F. Część z nich różniła się adresami pamięci, w których lokowały się procedury systemu - jedne wersje zajmowały niski obszar pamięci, inne umieszczały większość kodu w RAM pod OS-ROM. Istniały też odmiany z nieco zmodyfikowanymi procedurami odczytu.

Nie wnikając zbyt głęboko w szczegóły techniczne: jedne wersje procedury odczytującej dane tolerowały nagłą przerwę w tonie synchronizującym. W takiej sytuacji restartowały synchronizację i ponownie czekały na odpowiednią długość pilota. Inne wersje, gdy już rozpoznały sygnał pilotujący o odpowiedniej długości, zakładały, że po zakończeniu tonu pilota mogą pojawić się wyłącznie impulsy odpowiadające zerom i jedynkom. Impuls o innej długości powodował błąd nr 140.

Pech chciał, że wersja oprogramowania zawarta na cartridge'u "Klątwa" należy właśnie do tej drugiej grupy. To wersja, która nie toleruje przerwania tonu pilota, jeżeli wcześniej uzna, że odebrała już wystarczającą liczbę impulsów synchronizujących.

Ale to nie jedyny problem w tym wypadku. Przed dalszymi wyjaśnieniami muszę jeszcze dodać, że wersja softu z tego cartridge'a lokuje się na dole pamięci, w obszarze $0700-$199D. To za chwilę okaże się bardzo istotną częścią całej układanki.

Teraz muszę opisać kolejny klocek tej układanki. System Turbo 2000F, gdy powstawał, był w 100% zgodny - przynajmniej jeżeli mówimy o formacie zapisu danych - z "KSO Turbo 2000". KSO Turbo 2000 z kolei odziedziczyło format zapisu danych po systemie Turbo 2T06.

W dużym uproszczeniu: te systemy turbo w swoim natywnym formacie zapisywały dane w blokach po 3072 bajty. Przed każdym z takich bloków występował ton pilotujący, a następnie seria impulsów reprezentujących zera i jedynki danych zapisanych w danym rekordzie.

Z czasem ktoś zauważył, że tony synchronizujące pomiędzy kolejnymi rekordami danych zajmują sporo miejsca na taśmie. Ktoś zatem wpadł na pomysł, aby zmienić format zapisu danych tak, by pozbyć się długich "pilotów" przed każdym rekordem. W ten sposób opracowano tzw. "nowy format" zapisu danych, który miał zredukować liczbę tonów pilotujących, a tym samym jeszcze bardziej przyspieszyć wczytywanie programów.

Ten format rozwiązywał jeszcze jeden problem występujący przy klasycznym formacie zapisu danych. Chodziło o to, że przy klasycznym zapisie w blokach po 3072 bajty oprogramowanie systemu musiało mieć zarezerwowany bufor pamięci o takiej właśnie wielkości. To do niego trafiał odczytany rekord.

Po dodaniu rozmiaru kodu obsługującego cały system turbo okazywało się, że wolna pamięć dla ładowanych programów zaczynała się np. dopiero od wspomnianego wcześniej adresu $199D. Dla większości programów ładowanych z DOS-u nie był to wielki problem, bo MEMLO dla DOS-u często oscylowało na podobnym poziomie, zależnie od używanej wersji DOS-u.

Problem z tak wysokim MEMLO pojawia się natomiast w przypadku gier, które ładują się nisko do pamięci RAM. Jeżeli taka gra zajmuje obszar poniżej $199D, może po prostu zniszczyć bufor danych systemu turbo albo sam kod systemu. Loader plików binarnych nie chroni tych obszarów krytycznych - zakłada, że ładowany program nie nadpisze ani jego samego, ani buforów używanych przez system turbo.

Tutaj "nowy format" pokazuje swoją drugą zaletę. Po pierwsze nie wymaga bufora 3072 bajtów na odczytywany rekord danych, ponieważ ładuje dane bezpośrednio pod adres wskazany w nagłówku. Po drugie loader obsługujący ten format jest o wiele krótszy niż rozbudowany handler systemu Turbo, więc MEMLO dla takiego loadera może być znacznie niższe niż w przypadku używania natywnego formatu.

Pojawia się też trzeci aspekt tej sprawy: programy zapisane w takim formacie były znacznie trudniejsze do skopiowania. Jeżeli użytkownik nie dysponował programem kopiującym dedykowanym temu formatowi, nie mógł swobodnie powielić tak zapisanego programu.

Muszę przyznać, że gdy zetknąłem się z tym formatem w przeszłości, nie posiadałem ani nie znałem żadnego programu kopiującego nagrania w tym formacie. Trafiałem jednak na takie nagrania na tyle rzadko, że nie było to dla mnie dużym problemem. W dodatku pozycje, które spotykałem wtedy w tym formacie, nie były żadnymi unikatami ani nowościami, więc po prostu przechodziłem obok nich obojętnie.

W moim przypadku znacznie częściej natykałem się na programy zapisane w formacie znanym jako "Speedy 2700". Dlatego właśnie w latach 90. powstał "Anty *AJEK Copy", który zyskał drugą młodość jakiś czas temu, gdy w kolekcji uicr0Bee trafiłem na kasetę zapisaną w tym formacie.

W tamtych czasach zakładałem, że dla plików zapisanych w "new format" musi istnieć jakieś narzędzie, którym posługiwali się piraci giełdowi. Musieli przecież jakoś od czasu do czasu zapisywać niektóre programy w tym formacie, szczególnie te długie albo ładujące się na tyle nisko do pamięci RAM, że normalna odmiana systemu Turbo 2000F/2001 nie dawała rady ich załadować.

Siedząc w swojej informacyjnej bańce ograniczonej do warszawskiej giełdy na ul. Grzybowskiej i ul. Saskiej, nie byłem świadomy istnienia jakiegokolwiek programu kopiującego obsługującego "nowy format". Dopiero po latach, gdy tutaj na forum pojawił się cartridge "Turbo 2000 v.3.0" od SONIX", dowiedziałem się, że taki program jednak istniał. Dzięki uprzejmości Dely'ego, który wykonał dump cartridge'a, możemy cieszyć się kolejną ciekawostką historyczną z epoki.

Po uruchomieniu carta i wybraniu opcji "Turbo 2000F+":

https://pigwa.code32.org/atari/Turbo2000_v3_(SONIX)/Turbo2000_v30_(sonix).png

...możemy zobaczyć, że mamy do dyspozycji opcję "NCOPY". Okazuje się, że jest to program kopiujący umożliwiający odczyt i zapis plików w "nowym formacie".

https://pigwa.code32.org/atari/Turbo2000_v3_(SONIX)/turbo_2000F+.png   https://pigwa.code32.org/atari/Turbo2000_v3_(SONIX)/new_format_copy.png

Mając już "na tapecie" wątek Turbo 2000F+, mogę wspomnieć, że przed powstaniem "new format" autorzy rozwiązań związanych z systemem Turbo 2000F wpadli wcześniej na jeszcze jeden pomysł. Chcąc rozwiązać problem gier i programów wymagających wolnej przestrzeni adresowej w niskich lokacjach pamięci, wymyślili sobie, aby umieścić kod programu obsługującego system oraz 3 kB bufor danych pod OS-ROM, czyli w wysokich lokalizacjach pamięci: $C000-$CFFF oraz $D800-$FFFF.

Na dole pamięci umieszczono jedynie niewielki zestaw procedur umożliwiających kodowi znajdującemu się pod OS-ROM korzystanie z odwołań do ROM-u. Korzystanie z procedur w OS-ROM, gdy ten jest wyłączony, bo właśnie włączyliśmy RAM w obszarze ROM-u, jest dość problematyczne. ;P

Dzięki przeniesieniu większości kodu systemu pod OS-ROM uzyskujemy bardzo niskie MEMLO. W przypadku Turbo 2000F+ znajdującego się pod OS-ROM jest to $0800, co pozwala ładować programy zajmujące dość niskie obszary pamięci.

Pojawia się jednak inny problem: programy, które podczas ładowania próbują lokować się pod OS-ROM, mogą zniszczyć system turbo albo zawartość bufora przechowującego aktualnie wczytany rekord danych.

Pierwszy system Turbo 2000F lokujący się pod OS-ROM, z którym się zetknąłem, był rozwiązaniem sygnowanym przez firmę MUEL. Nie było wtedy jednak jeszcze mowy o "new format". Sądzę, że "new format" powstał jako następny krok ewolucji systemu.

Nie mam niestety pojęcia, kto jest autorem koncepcji "nowego formatu". Jak wspominałem wcześniej, podobne podejście do ładowania danych bez podziału na bloki wprowadził *AJEK. Jeszcze wcześniejsze rozwiązania tego typu można było spotkać w czeskich systemach turbo z serii Turbo 2000.

Wasze zdziwienie może zapewne budzić fakt, że napisałem tyle tekstu i wyjaśnień o systemach turbo, ich lokowaniu się w pamięci, formatach danych itd. Miałem przecież pisać o "przeklętej kasecie". Niestety musiałem poruszyć tyle wątków pobocznych przed właściwym wyjaśnieniem problemów z tą kasetą, ponieważ wszystkie te informacje są kluczowe dla zrozumienia problemu człowieka, który próbował cokolwiek wczytać z tej kasety przy użyciu opisanego wyżej kompletu sprzętu.

Podsumujmy zatem najistotniejsze informacje:

  • Istniało kilka wersji oprogramowania obsługującego Turbo 2000F:
        - wersje lokujące się w dolnym obszarze pamięci, z wysokim MEMLO, np. $199D,
        - wersje lokujące się pod OS-ROM, z niskim MEMLO.

  • Istniały dwa formaty zapisu danych:
        - klasyczny format zapisujący dane w blokach po 3 kB,
        - "nowy format", zapisujący każdy segment pliku binarnego jako długi, ciągły blok bez podziału na rekordy danych.

I teraz rzecz dość istotna: "nowy format" wymagał specjalnego loadera umożliwiającego wczytywanie danych w tym formacie. System znajdujący się na cartridge'u nie wspierał "nowego formatu". Obsługiwał jedynie klasyczny sposób zapisu danych, czyli ten z podziałem na bloki po 3 kB.

Aby wczytać program zapisany w "nowym formacie", tuż przed właściwym programem umieszczano więc loader. Po uruchomieniu wczytywał on dalsze dane, obsługując już "nowy format".

Zakładam, że postępowano w ten sposób, aby umożliwić w przyszłości zmiany kodu loadera w razie wykrycia w nim problemów albo gdyby zaszła konieczność zmiany formatu danych. Loader zapisany przed właściwym programem na taśmie dawał pełną swobodę wyboru tego, co znajdzie się potem na taśmie. Tak samo postępowano w przypadku loaderów L1 czy L2 - nagrywano je jedynie przed programami, które tego wymagały. Zakładam, że tutaj autorowi pomysłu przyświecała podobna idea. Program ładujący dane w "nowym formacie" był po prostu zapisany jako jeden blok w standardowym formacie Turbo 2000.

I teraz zbliżamy się do momentu, w którym wszystko stanie się jasne. Tą ogromnie pokręconą drogą doszliśmy właśnie do kwestii tego loadera.

Otóż taki loader powinien być bytem niezależnym i samowystarczalnym. Jednak z jakiegoś nieznanego mi powodu twórcy loadera obsługującego "nowy format" postanowili uzależnić go od istniejącego pod spodem systemu Turbo.

Tutaj pojawiają się dwa problemy:

  • loader ładuje się w obszar $0806-$09EE,

  • w kodzie loadera są bezpośrednie odwołania do procedur konkretnej wersji systemu turbo, umieszczonych w konkretnych miejscach pamięci.

Przypomnę tylko, że system turbo w cartridge'u "Klątwa" to wersja lokująca się nisko w pamięci RAM, w obszarze $0700-$199D. Dodam również, że większość pozycji zapisanych na omawianej kasecie to gry zapisane właśnie w "nowym formacie".

I teraz możemy wreszcie połączyć kropki: jakakolwiek próba załadowania programów z tej kasety przy użyciu "Klątwa Cartridge" nie miała żadnych szans powodzenia.

Jeżeli już udało się ominąć pyknięcie w pilocie pierwszego bloku, to załadowanie bloku zawierającego loader natychmiast niszczyło system turbo znajdujący się w pamięci. Loader pakował się w obszar $0806-$09EE, nadpisując istniejący już tam kod. Nawet gdyby jakimś cudem trafił w mniej istotne fragmenty systemu, to chwilę później i tak wykonywał bezpośrednie skoki do procedur na siódmej stronie pamięci, zakładając, że zostały one dostarczone przez konkretną wersję systemu - na przykład Turbo 2000F+.

Co ciekawe, nie są to żadne rozbudowane procedury. To naprawdę dwa proste kawałki kodu odpowiedzialne za przełączanie ROM/IRQ/NMI. Gdyby zostały wbudowane bezpośrednio w loader, byłby on niezależny od systemu, z którego został załadowany.

Jedyne, co przychodzi mi do głowy, to celowe działanie autora tego loadera. Być może po prostu chciał "przywiązać" to rozwiązanie do wersji systemu, której sam używał. Jeżeli faktycznie takie było założenie, to udało mu się w 100% doprowadzić człowieka, który trafił na tę "pułapkę", do siwych włosów. ;)

Cartridge "Klątwa" nie miał nigdy realnych szans na wczytanie programów z tej kasety. Po pierwsze: pyknięcia w tonie pilota były traktowane przez soft w cartridge'u jako błąd. Po drugie: loader "nowego formatu" zawieszał cały system już w momencie ładowania go do pamięci.

Magnetofon można było zaklinać, egzorcyzmować, wymienić połowę elementów elektronicznych i mechanicznych, a i tak nic by to nie dało.

Potwierdzeniem może być fakt, że po doprowadzeniu magnetofonu do sprawności i tak nie mogłem poprawnie wczytać żadnego programu właśnie ze względu na opisane wcześniej zjawiska. Dopiero używając cartridge'a "Turbo 2000F v.3.0" od SONIX udało mi się wczytać większość programów bez większych problemów, pomijając oczywiście kwestie plików uciętych i nadpisanych na samej kasecie: eksperymenty? Testy? Bezsilność walczącego z systemem? Próby dogrywania innych programów? Tego pewnie już nigdy się nie dowiemy.

Mogę jedynie podejrzewać, że poprzedni właściciel tego kompletu - magnetofonu, cartridge'a i kasety - napotkał tak złośliwe combo, że uznał cały sprzęt za przeklęty.

Oczywiście może być też tak, że nie jest to żaden komplet, tylko przypadkowa zbieranina różnych artefaktów. Być może programów z tej kasety nikt nigdy nie próbował nawet wczytywać. Bo skąd na kasecie programy zapisane w "new format", jeżeli założymy, że użytkownik magnetofonu posiadał jedynie cartridge niewspółpracujący z tym formatem danych?

Równie dobrze każdy z tych przedmiotów może pochodzić z innego miejsca i czasu. Niemniej jednak naklejka "Klątwa" pozwala snuć różne dziwne pomysły... ;-)


Poświęciłem na to wszystko sporo czasu, mimo że tak naprawdę nie jest to już dziś szczególnie praktyczna wiedza i zapewne nikomu się bezpośrednio nie przyda. Zaintrygowało mnie to jednak na tyle, że mimo pełnej świadomości kompletnie nieuzasadnionego nakładu pracy i czasu brnąłem w ten temat jak "zaklęty". :)

Niby wystarczyło tylko zgrać kasetę i udostępnić ją na forum. Zainteresowani sami wiedzieliby, co zrobić z takim materiałem. Jednak moja wewnętrzna ciekawość oraz wspomnienia z przeszłości nie pozwoliły mi przejść obok tego tematu obojętnie.

Musieliście też długo czekać na moją dalszą aktywność w tym wątku. Mimo że to "tylko jedna kaseta", poza samą obróbką materiału, analizą kodu loadera i deasemblacją wiedziałem, że samo napisanie posta wyjaśniającego zajmie mi sporo czasu. Dlatego odkładałem ten temat, ile się dało. W końcu jednak, chcąc zrzucić kolejny temat ze swoich barków, postanowiłem się zawziąć i zacząć pisać.

Zapewne mało kto dobrnie do końca, bo to, co tu wypisuję, dla większości ludzi będzie pewnie niszowymi bredniami człowieka z epoki, w której 8-bitowy mikroprocesor był szczytem techniki. Zatem pora zakończyć już tę część. Myślę, że powstaną jeszcze dwie kolejne. W części drugiej opiszę zawartość kasety: co udało się z niej odzyskać, co było ucięte albo nadpisane i jakie niespodzianki znalazły się na taśmie. Część trzecia będzie już podsumowaniem oraz krótkim opisem tego, jak postanowiłem zdeasemblować loader i stworzyć jego poprawioną wersję - bardziej uniwersalną oraz niezależną od wersji systemu dołączonej na cartridge'u.

na zakończenie jeszcze "bohaterowie odcinka" o których mowa:
https://pigwa.code32.org/aa/uicr0Bee_the_kl%C4%85twa_family.jpg
^^^ zdjęcie auorstwa uicr0Bee ^^^

uicr0Bee napisał/a:

Nie wiem czy znane, więc daję: https://www.atari-800.cz/turbo-2000

Nie znałem. Dzięki! Ale opisy tego czeskiego Turbo2000 zostały udostępnione przez Baktra, linki są na jego stronie, sekcja "Miscellaneous": https://turgen.sourceforge.io/links/

uicr0Bee napisał/a:

Powinno być "2.3" :-)

Poprawione, dzięki!

uicr0Bee napisał/a:

Niestety po wyjęciu niedawno z szafy, okazało się że nie kręci kasetą przy PLAY, nie przewija. Wymieniłem pasek na nowy ale bez zmian.
Nie mam umiejętności ani czasu aby z nim walczyć.

Kurdę! Co za uparty egzemplarz! Nie dość że tyle go reanimowałem to znowu nie działa? :( Ale silnik w ogóle się kręci? czy jest kompleta cisza?

POKE 54018,52

z poziomu BASIC-a i PLAY ... jaki daje efekt? kompletna cisza? (brak odgłosu silnika?).

Jakby co podeślij go jeszcze raz, nie będzie nam taki magnetofon się stawiał ;-)

JLS napisał/a:

Następny update dotyczący adresu wymienionego w instrukcji ul. Wyspiańskiego. Z zawartości książki telefonicznej Gliwic, przełom lat 90-tych i początek 2000 roku, która w postaci elektronicznej przez przypadek mi się ostała, wynika że nie jest to osoba którą wymieniłeś o domniemywanym nazwisku Kania. Mam nawet nr tel. stacjonarnego :)

Dziękuję za sprawdzenie i dalsze zgłębienie tematu! Mamy jakąś jasność co do tego że pod tym adresem pan Grzegorz Kania nie mieszkał, przynajmniej w chwili w której powstawała książka telefoniczna. Na chwilę obecną można chyba uznać że zabrnęliśmy w ślepą uliczkę. No trudno, może przyszłość przyniesie jakieś wyjaśnienia.

uicr0Bee napisał/a:

seban, a czy kojarzysz, czy miałeś te kasety ode mnie? U Ciebie na pigwie nie widzę, a ja mam je w razem z innymi z pigwy w takim białym futerale na 24 kasety, który chyba był u Ciebie, nie? Jak nie miałeś, to czy odłożyć do archiwizacji do przyszłej paczki?

Przyznam że już nie pamiętam czy te konkretne kasety były u mnie, możesz dorzucić do przyszłej paczki, zgram oczywiście. Ale rzucę jeszcze okiem czy czegoś nie pomieszałem i czy czegoś nie opuściłem. Białe pudło jak najbardziej było w moich rękach.

QTZ napisał/a:

AUTOCOPY 3.0 zapisuje inną długość bloku: $0B16, zamiast $0C17

AUTOCOPY 3.1 chodzi o sumę, ale nie wygląda żeby chodziło o XOR-a.
Nie wiem czemu ldx, ale wydaje mi się, że chodzi o inną wartość początkową sumy:


A widzisz nie pamiętałem już że AUTOCOPY 3.0 ma inną długość bloku, sprawdzę.
Jeżeli chodzi o LDX #$A3 - jest dokładnie tak jak piszesz, chodzi o inną początkową wartość sumy kontrolnej.

QTZ napisał/a:

W pliku c3_copy.xsm jest w poniższej linii " ' " zamiast " ; " i w Mads to nie przechodzi.

No tak mój błąd, powinien być oczywiście " ; ", ale w przypadku XASM nie ma to znaczenia (a ja używam do kompilacji projektu XASM), XASM zapewnia wsteczną zgodność z QA, a więc wszystko co będzie po poprawnym mnemoniku będzie ignorowane, dlatego ' (apostrof) przechodzi w XASM a w MADS nie.

QTZ napisał/a:

ert    *>$d000

nie wiem jak w MADS, ale w XASM dyrektywa "ERT" (error if true) generuje błąd kompilacji jeżeli warunek jest prawdą. W tym wypadku to sprawdzenie czy skompilowany kod nie przekroczył adresu $CFFF. Jeżeli skompilowany kod przekroczy ten adres, to XASM po prostu zgłosi błąd. Usunięcie tabulatora zapewne spowodowało że "ERT" zostało potraktowane jako etykieta (nie używam MADS [ za małe  i za proste projekty robię ] - a więc to jedynie moje domysły).

Hej!

JLS napisał/a:

Byłem na wskazanym adresie, rzuciłem okiem, niestety domofon jest na tyle nowoczesny, bo jest bez wskazywania  nazwisk mieszkańców.

Dzięki za sprawdzenie, dalsze drążenie nie ma chyba sensu. Pytanie na miejscu mogłoby być mało komfortowe dla obecnie zamieszkujących pod wskazanym adresem.

@QTZ: Dzięki za szczegółową informację zwrotną! Oczywiście sprawdzę to wszystko. Zgodnie z Twoją sugestią dodam oczywiście wsparcie dla innego liczenia sumy kontrolnej (XOR vs modulo 256) tak aby czytało to pliki zabezpieczone AUTOCOPY 3.x. Przyjrzę się oczywiście szczegółowo też linii którą wskazałeś, wszystko wskazuje na to że popełniłem tam faktycznie błąd, oczywiście poprawię.

Dzięki wielkie że chciało Ci się w tym grzebać i wychwyciłeś nieścisłości! Jeżeli chodzi o BASIC, to coś było na rzeczy ale wydawało mi się że to poprawiłem, może jednak czegoś jeszcze nie dopatrzyłem.

Jeżeli chodzi o KSO 2000 pod Altirra to odczyt działa (sprawdzałem), nie działał chyba tylko zapis, ale zapis działał pod modyfikowaną przez FUJI-ego wersją Atari800.

Na pewno poprawię i dodam co trzeba, tylko proszę o chwilę cierpliwości, muszę dokończyć bieżące tematy leżące na biurku.

Dzięki za skany! :) Każdy taki materiał jest bardzo fajnym i cennym historycznie znaleziskiem!

JLS napisał/a:

Jeśli pod wskazanym adresem znajdują się nazwiska na domofonie, mogę spróbować to sprawdzić. Ten adres  jest w prostej linii około 500 metrów od mojego miejsca zamieszkania.

To jakbyś kiedyś przechodził i miał chęć to rzuć okiem to byłoby fajnie, może faktycznie będzie jakiś ślad, ale to nic na siłę, to nie tak że chodzi mi o "nękanie" ludzi z przeszłości, po prostu ciekawy jestem kontekstu historycznego. Wszystko co związane takimi tematami i sprawami z dawnych czasów bardzo szybko się zaciera, stąd moje czasami dziwne pytania i próby dociekania jak to wszystko mogło wyglądać w tamtym czasie.

@tOri: dzięki za miłe słowa! To naprawdę była fajna przygoda... wyszło tak jakoś samo z siebie ;) Można narzekać na AI/LLM-y ale w tym wypadku to własnie model językowy był motywatorem do działania bo odwalał najnudniejszą robotę, taką za którą nie wziąłbym się sam przed długi czas, ponieważ okno czasowe jakim dysponowałem nie było zbyt duże.

@JLS: a to też jest ciekawa informacja! Nie pamiętasz może czy ten człowiek pod tym adresem nazywał się może Grzegorz Kania? Dopytuję to w niektórych carta do Blizzarda tam gdzie widnieje "KNS Corp.", "KNS" lub "KNS Corporation", widnieje też albo "G. Kania", lub "Grzegorz Kania". Ja to wszystko dopytuję się w celu zrozumienia zależności lub raczej niezależności firmy ATARES i KNS. Można jednak założyć że skoro przeróbkę na Blizzard zrobiłeś w Gliwicach to ten człowiek który tę przeróbkę wykonał (z dużym prawdopodobieństwem był to pan G. Kania / KNS Corp) nie był podmiotem zależnym od ATARES. Zastanawiam się też czy KNS Corp. to był niejako "szyld" pod którym działał pan G. Kania czy też w skład KNS Corp. wchodziło więcej osób. Zastanawiałem się również czy też ów "KNS" nie było skrótem np. od "KaNia Software" ;-) Ale to już czysta spekulacja jest.

Moje dociekania biorą się stąd ze początkowo myślałem że software/hardware jaki powstał dla Blizzarda rodził się ATARES, jednak im więcej kopię i im więcej czasu poświęcam na próbę zrozumienia zależności to wychodzi mi na to że system nie miał jednego autora, tylko to była ciągła ewolucja do której każdy działające wokół tego tematu dokładał swój wkład.

To pewnie jest już nie do ustalenia, ale ciekawi mnie czy ATARES które to potem w swoich cartridge miało software (loadery, KOS, etc.) sygnowane przez KNS w jakiś sposób dogadało się autorem tychże programów czy też było to na zasadzie czystej "partyzantki" i brania z rynku istniejących rozwiązań i pakowania ich do swoich produktów.

O to jest świetna idea! Mirrorów taki wartościowych stron nigdy nie za wiele! Widzę że udało się z Twoją pomocą uzupełnić brakujące pliki! super! Dzięki! No i oczywiście podziękowania również dla Kuby Husaka że chciało mu się to ogarnąć i wrzucić github-IO. Śmiga super szybko! Już sobie dodałem do "zakładek".

ZABEZTUR - rekonstrukcja ROM-u z pomieszanymi liniami adresowymi/danych

Dziś w wątku temat nieco odbiegający od tego, co zwykle tutaj prezentuję - postanowiłem zająć się czymś, co męczyło mnie od dłuższego czasu...

Zacznijmy może od tego że na stronie ś.p. Jerzego Soboli, w dziale schematy, na dole strony znajdują się również dumpy różnych ROM-ów. Jeden z nich opisany jest opisany tak:

zabeztur.zip - ROM kartridża TURBO 2000 zabezpieczający przed kopiowaniem nagrane programy.

Jakiś czas temu mnie to mocno zaintrygowało. Niestety zawartość dumpa wyglądała na kompletną sieczkę - losowy, nieczytelny ciąg bajtów. Przez długi czas odkładałem temat, bo brakowało zarówno czasu, jak i sensownego pomysłu, jak się za to zabrać. Zacząłem się nawet zastanawiać, czy dump nie jest po prostu uszkodzony. Nie chciałem również zawracać głowy Jerowi taką błahostką, odkładając temat na później. Jak się okazało nie zdążyłem zapytać i już nie będę miał takiej możliwości :(

Mimo wszystko temat nie dawał mi spokoju. Wracało co jakiś czas, aż w końcu stwierdziłem, że pora spróbować jeszcze raz - tym razem bardziej metodycznie. Nie chciało mi się jednak zaczynać całkowicie od zera, więc postanowiłem wspomóc się dużym modelem językowym (padło na ChatGPT 5.4). Pomógł mi on przygotować podejście do analizy danych oraz zaproponować metody, których ręczne opracowanie zajęłoby sporo czasu.

Zakładałem, że JER poprawnie odczytał zawartość EPROM-u, ale wszystko wskazywało na to, że:
- albo EPROM był uszkodzony i dump faktycznie jest błędny,
- albo PCB miało celowo pozamieniane ścieżki.

Coraz bardziej prawdopodobne wydawało się to drugie - czyli przemieszane linie adresowe i/lub danych.

Brute force wszystkich możliwości nie wchodził w grę - to daje (8+12)! permutacji, czyli coś około 2432902008176640000 możliwości :P

Zamiast tego zastosowałem podejście etapowe.

1. Dane (D0..D7)

Na początek założyłem, że problem może dotyczyć wyłącznie permutacji bitów danych. 
Przetestowałem wszystkie 8! permutacji, czyli 40320 możliwości, ale zamiast przeszukiwać wszystkie i sprawdzać "czy działa", użyłem heurystyki:

- histogram wartości bajtów
- częstość występowania typowych opcode-ów 6502 (A9, 20, 4C, 60, D0, F0 itd.)

Dobra permutacja szybko się wyróżnia - rozkład bajtów przestaje wyglądać losowo i zaczyna przypominać kod maszynowy.

2. Dolne linie adresowe (A0..A3)

Po poprawieniu danych ROM nadal był niespójny, ale już "prawie wyglądał jak 6502".

Kolejny krok to "brute force" dla A0..A3 (11880 przypadków, bo 12P4 = (12!)/(12-4)! = 12 × 11 × 10 × 9 = 11880) z oceną lokalnej składni:

- dopasowanie sekwencji typu:

A9 xx
20 xx xx
4C xx xx
8D xx xx
D0 xx
60

Na tym etapie pojawił się pierwszy "żywy" kod - nadal rozbity globalnie, ale lokalnie sensowny.

3. Środkowe linie (A4..A7)

Tutaj zaczęły pojawiać się fragmenty tekstów, więc do punktacji dodałem:

- premię za ciągi ASCII
- dopasowanie fragmentów słów (np. "TURBO", "format", "plik")

Obraz ROM-u stawał się coraz bardziej czytelny, choć napisy nadal były porozrywane.

4. Górne linie (A8..A11)

Przełomowy moment nastąpił, gdy zauważyłem, że fragmenty napisów istnieją, ale są rozdzielone między różnymi obszarami pamięci.

Przykład:

"Zly fo"  ...  "rmat pliku"

Czyli dane były poprawne, ale większe bloki (strony) były źle ułożone.

Na tym etapie wystarczyło brute force dla 4! = 24 wariantów i dopasowanie pełnych stringów:

- "Zly format pliku"
- "TURBO COPY"
- "dlugosc"
- itd.

Jeden wariant wyraźnie się wyróżnił - i to był właściwy kierunek.

Wynik

Po odwróceniu wszystkich permutacji:

- ROM jest w pełni poprawny
- system uruchamia się w emulatorze
- teksty i logika programu są spójne

Finalne mapowania

Dane:

CART        -> EPROM 2732
-------------------------
D0          -> D1
D1          -> D0
D2          -> D5
D3          -> D4
D4          -> D7
D5          -> D6
D6          -> D2
D7          -> D3

Adresy:

CART        -> EPROM 2732
-------------------------
A0          -> A2
A1          -> A10
A2          -> A11
A3          -> A9
A4          -> A3
A5          -> A8
A6          -> A7
A7          -> A6
A8          -> A5
A9          -> A4
A10         -> A0
A11         -> A1

Podsumowanie

Plik, który początkowo wyglądał jak losowy szum, koniec końców okazał się poprawnym zrzutem pamięci EPROM. Nie wiem, czy pozamieniane linie adresowe/danych miały być rodzajem zabezpieczenia, czy raczej ułatwieniem prowadzenia ścieżek na płytce drukowanej. Niestety nie widziałem oryginału, z którego JER wykonywał dump, więc mogę się jedynie domyślać.

Całość udało się odtworzyć wyłącznie na podstawie:
- analizy statystycznej danych
- struktury kodu 6502
- oraz fragmentów tekstów obecnych w ROM-ie

Początkowo zakładałem, że nie uda mi się odkryć tajemnicy tego pliku, ale w końcu udało się ją rozwiązać i przestało mnie to "męczyć", teraz mogę stwierdzić że była to fajna zagadka - zdecydowanie warta poświęconego czasu! Naprawdę cieszę się, że cała ta zabawa zakończyła się sukcesem, mimo że odkrycie zawartości wywołało u mnie raczej uśmiech na twarzy, bo po tej całej walce moim oczom ukazał się następujący obraz:

https://pigwa.code32.org/atari/JER_WZab_2T12/scr/WZab_2T12_A.png   https://pigwa.code32.org/atari/JER_WZab_2T12/scr/WZab_2T12_B.png

^^^ zatem z dużym prawdopodobieństwem można przyjąć, że to nie jest: "ROM kartridża TURBO 2000 zabezpieczający przed kopiowaniem nagrane programy", tylko raczej: "ROM kartridża TURBO 2000 zabezpieczony przed kopiowaniem". Zabezpieczeniem był nietypowy układ ścieżek na płytce cartridge ;) Cart z identyczną zawartością był już opisany w tym wątku, a dokładniej w tym poście: Turbo 2000 COPY <--- z tym że ten cart nie miał pozamienianych linii danych/adresowych.

Dla porządku oczywiście wrzucam link do tego, co udało się zdekodować: WZab_2T12_recovered.bin.zip

Skróty plików zgadzają się w 100% z tymi, które są udostępnione w w/w poście:

MD5    : b74515156ce99bbb658ef342a91f051f
SHA256 : 2821fec46fb1caf4ad75f0f2f5905987671df0d5d18c7f9d098d95a23ae7154b

A dla jeszcze większego porządku - aby każdy zainteresowany mógł samodzielnie zdekodować plik ze strony JER-a - dodaję skrypt w Pythonie: descramble_WZab_2T12.py, przykład użycia:

python3 descramble_WZab_2T12.py WZab_2T12_scrambled.bin -o WZab_2T12_recovered.bin 
Gotowe.
Wejscie : WZab_2T12_scrambled.bin
Wyjscie : WZab_2T12_recovered.bin
Dane    : (1, 0, 5, 4, 7, 6, 2, 3)
Adresy  : (2, 10, 11, 9, 3, 8, 7, 6, 5, 4, 0, 1)

Skróty pliku wynikowego:
  MD5    : b74515156ce99bbb658ef342a91f051f
  SHA256 : 2821fec46fb1caf4ad75f0f2f5905987671df0d5d18c7f9d098d95a23ae7154b

I to chyba tyle na dziś - dobranoc wszystkim!

@Pawex Dzięki WILEKIE! Za te zdjęcia! To potwierdza tylko moje przeczucia że KNS Corporation nie było częścią ATARES, początkowo myślałem że KNS Corporation (Grzegorz Kania) jest jakoś związany blisko ale teraz widząc adres Gliwicki mam pewność że Pan Kania nie był z Chorzowa, tak jak firma Atares, co tylko potwierdza moje przypuszczenia że Atares "zaadaptował" rozwiązania opracowane Przez KNS Corp.

Hejka!

No właśnie ową "klątwę" zostawiłem na sam koniec licząc że będzie to ciekawy przypadek... a mówimy o takim nieboraku:

https://pigwa.code32.org/uicr0bee/carts/Turbo2001_v22/photos/t2k1_klatwa_cart.jpg
^^^ otóż ta dodatkowa naklejka z napisem "KLĄTWA", była dość intrygująca.

Prawdę mówiąc liczyłem na jakieś dziwne combo typu cart zawierający grę "KLĄTWA" oraz dodatkowo soft do Turbo 2000F/2001, jednak okazało się to dużą nadinterpretacją z mojej strony... normalnie klątwa mnie dopadła i spotkał swego rodzaju zwód ;-) bo jakże to tak? Nie będzie nowego wyzwania!?! Bleh... Nie wiem kto sobie wymyślił taki numer, ale w pełni mu się to udało... może Turbo 2001 okazało się prawdziwą klątwą dla właściciela tego kartridża ;-P

Z pewną taką nieśmiałością zabrałem się do otwierania tego carta... i moim oczom ukazał się las... (to żart oczywiście :P) ... a tak naprawdę ukazała się następująca płytka drukowana:

Strona elementów:
https://pigwa.code32.org/uicr0bee/carts/Turbo2001_v22/photos/t2k1_klatwa_pcb_bot.jpg

Strona lutowania:
https://pigwa.code32.org/uicr0bee/carts/Turbo2001_v22/photos/t2k1_klatwa_pcb_top.jpg

Jak to zobaczyłem to wydałem z siebie jęk zawodu... otóż jest typowy kartridż oparty o 4kB pamięć EPROM, mieszczący w sobie tylko i wyłącznie oprogramowanie systemu Turbo 2000F/2001 oznaczone w tym wypadku sygnaturą v.2.2, mówię oczywiście o naklejce na obudowie. Po uruchomieniu oczywiście można zobaczyć co następuje:

https://pigwa.code32.org/uicr0bee/carts/Turbo2001_v22/scr/t2k1_v22_klatwa_a.png   https://pigwa.code32.org/uicr0bee/carts/Turbo2001_v22/scr/t2k1_v22_klatwa_b.png

Standardowy cart dla Turbo 2001 zawierał 2KB pamięć EPROM i nie zawierał programu kopiującego, był zmontowany na identycznej PCB, o czym pisałem już w tym poście: Turbo 2001 v.2.1. Również w tym wątku pojawił się dump tożsamego carta udostępniony przez użytkownika "Yezy", dokładnie w tym poście: Turbo 2001 + COPY.

Zawartość pamięci "wyklętego" carta okazała się tożsama z tym co udało się wrzucić na forum Yezemu, ale dla porządku i weryfikacji poprawności zrzutów umieszczam również i ten dump: Turbo 2001 v.2.2. Skróty (MD5/SHA256) plików się zgadzają z tym co udostępnił Yezy:

t2k1_v22_klatwa.bin | 61e5ee7ab9a59c7544c317935acaa8af                                  | MD5
t2k1_v22_klatwa.bin | 1a4ea1b4f5f4e653f6813672a391f9735dd219bf3ac004fc35828c874e293380  | SHA256

Co mi więcej pozostało? Dla porządku narysowałem schemat tego co było na PCB:

https://pigwa.code32.org/uicr0bee/carts/Turbo2001_v22/sch/turbo_2001_4K_cart.png
oczywiście do pobrania wersja wektor: Turbo 2001 4K CART (PDF).

Jak więc widać jest to typowy cart z tamtego okresu który mapuje się w oknie $A000-$BFFF, a ponieważ pamięć ma tylko 4kB a okno wynosi 8kB, to w obszarze $A000-$BFFF widać dwa powtórzenia zawartości pamięci, tzn. obszar $A000-$AFFF zawiera dokładnie to samo co obszar $B000-$BFFF. Cartridge wyłącza się samoistnie po paru sekundach, do tego czasu soft zawarty w carcie kopiuje się do RAM i cierpliwie czeka na odłączenie się kartridża aby przejść dalej.

Program kopiujący "Universal Copy II" dodany do carta był napisany przez Jakuba Kruszonę. Nie mam natomiast żadnej pewności czy autor programu kopiującego pozwolił na to działanie, czy też twórcy carta po prostu umieścili ów program bez wiedzy autora.

No i taki smutny koniec, nieco przeklęty nam się trafił na koniec. To chyba był ostatni cart z obecnej transzy od uicr0Bee, teraz pozostało mi doprowadzić magnetofony które mi pozostały w pudle do porządku, ale to nie będzie ciekawa robota... jeden to magnet w standardzie, drugi (ten do którego był dołączony "Klątwa" kartridż to magnet z Turbo 2000F/2001 pozbawiony kabelka.

Czeka nas w wątku chwilowa przerwa bo muszę obrobić to co pozostało i zająć się na chwilę czym innym, ale obiecuje że niebawem będzie trochę o kasetach w formacie AST, także proszę o cierpliwość i na chwilę obecną odmeldowuje się.


PS) Będę miał do Was, szanowni forumowicze, kilka pytań dotyczących Atares i KNS Corporation. Może ktoś coś jeszcze pamięta - ale to w następnym poście (za jakiś czas), bo muszę najpierw uporządkować to, co udało mi się do tej pory ustalić. Nie chcę pisać chaotycznie, więc wolę zebrać wszystko do kupy i dopiero wtedy zadać konkretne pytania. Być może ktoś z Was będzie w stanie rozwiać moje wątpliwości i rzucić nieco światła na tę historię. Na razie pozwoliłem sobie nieco rozbudować wpis na Atariki o firmie ATARES. Jeśli ktoś ma coś do dodania albo uściślenia - będę wdzięczny za informacje.

Dzień Dobry!

Dziś kolejny mały kroczek wykonany, czyli kolejny cart z kolekcji uicr0Bee został przeanalizowany. Tym razem był to klon cartridge "Phoenix" dla systemu Blizzard. Ten typ carta pojawiał się już kilkukrotnie na tym forum, pozwolę sobie zatem przypomnieć wątki i posty w których się pojawił ów mistyczny Phoenix opracowany przez Hurka:

Tym razem nasz "nieborak" tym razem prezentował się tak:
https://pigwa.code32.org/uicr0bee/carts/Blizzard_16k_Phoenix_clone/photos/blz_phoenix_clone_cart.jpg
^^^ tym razem samotnik bez żadnej naklejki pozwalającej go zidentyfikować "na pierwszy rzut oka".

Nie było to jednak przeszkodą, ponieważ zawsze możemy zajrzeć do środka i obejrzeć sobie płytkę drukowaną (od góry):
https://pigwa.code32.org/uicr0bee/carts/Blizzard_16k_Phoenix_clone/photos/blz_phoenix_clone_pcb_top.jpg
^^^ na naklejce na pamięci EPROM o rozmiarze 16kB widzimy napis "PH 32", płytka drukowana w porównaniu ze starszymi konstrukcjami od ATARES wygląda na całkiem porządnie wykonaną, oraz w miarę estetycznie polutowaną.

dolna strona płytki drukowanej (PCB) prezentuje się następująco:
https://pigwa.code32.org/uicr0bee/carts/Blizzard_16k_Phoenix_clone/photos/blz_phoenix_clone_pcb_bot.jpg

Patrząc na płytkę drukowaną możemy dojść do wniosku że jest to swego rodzaju rozwiązanie "uniwersalne", tzn. możliwe jest wykonanie na tej płytce innej wersji cartridge (mamy miejsce na drugi układ scalony), ścieżki doprowadzone do pamięci EPROM sugerują że możliwe jest również użycie większej pamięci EPROM (np. 27256 czyli 32kB), dołożenie przełączników, etc.

Ta sama płytke drukowana została użyta w cartridge Marka Góreckiego (EGR) o nazwie Turbo Toolbox I, z tym że w przypadku carta Turbo Toolbox I, była użyta pamięć o rozmiarze 8kB. Było tez parę innych cartów w historii tego wątku opartych na podobnej PCB, a więc mogę się domyśleć że to była swego rodzaju "uniwersalna" płytka stosowana przez różnych ludzi do budowania cartów z różną zawartością i w różnej konfiguracji.

Oczywiście ponieważ nie pamiętam już, że wcześniej rysowałem już schemat oparty na tej płytce to uczyniłem to ponownie, zatem nie pozostaje mi nic innego jak ten schemat po prostu wrzucić dla porządku do tego postu:
https://pigwa.code32.org/uicr0bee/carts/Blizzard_16k_Phoenix_clone/sch/blz16k_phoenix_clone.png
^^^ Do pobrania oczywiście również wersja wektorowa: Blizzard 16KB - Phoenix (clone).

Cart po uruchomieniu prezentuje się tak:
https://pigwa.code32.org/uicr0bee/carts/Blizzard_16k_Phoenix_clone/scr/blz_phoenix_1.0.png

Oczywiście zawartość pamięci EPROM do pobrania tutaj: Blizzard Phoenix 1.0 (clone). Dla porządku również skróty pliku:

d17c7ac16b581577a88628da15dd522c                                  blz_phoenix_1.0.bin | MD5
aa49e16095708e153d2350e818a3348d6590bd8c26ec9a2a690e6d4174f8fd5d  blz_phoenix_1.0.bin | SHA256

Są inne niż w przypadku wcześniej prezentowanych dump-ów. Dlaczego? Ponieważ osoba wykonujaca klon postanowiła usunąć informacje o firmie ATARES, zastępując informacje o pochodzeniu softu albo "spacjami", albo innymi napisami o to dlatego nazywam ten cartridge klonem. Szybkie porównanie z dumpem od ATARES:

File A size:      16384 bytes
File B size:      16384 bytes
Compared length:  16384 bytes
Different bytes:  189 (1.1536%)
Equal bytes:      16195
Diff blocks:      3
Compare mode:     full 8-bit
Text mode:        atascii-unicode

Largest diff block: 80 bytes

========================================================================================================
BLOCK 1: diff @ 0x0000270A..0x00002731 (len=40 bytes)
--------------------------------------------------------------------------------------------------------
OFFSET     FILE A HEX               A TXT         FILE B HEX               B TXT
--------------------------------------------------------------------------------------------------------
0000270A  CD C9 C3 D2 CF CC CF C1  |MICROLOA|    A0 CD C9 CB D2 CF CC CF  | MIKROLO|
00002712  C4 C5 D2 A0 B1 AE B0 A0  |DER 1.0 |    C1 C4 C5 D2 A0 B1 AE B0  |ADER 1.0|
0000271A  A0 A0 A0 A0 A0 A0 A0 D0  |       P|    A0 E2 F9 A0 C7 AE CB AE  | by G.K.|
00002722  C8 CF C5 CE C9 D8 A0 C3  |HOENIX C|    A0 E6 F2 EF ED A0 CB CE  | from KN|
0000272A  C1 D2 D4 D2 C9 C4 C7 C5  |ARTRIDGE|    D3 A0 C3 CF D2 D0 AE A0  |S CORP. |

========================================================================================================
BLOCK 2: diff @ 0x00002D29..0x00002D78 (len=80 bytes)
--------------------------------------------------------------------------------------------------------
OFFSET     FILE A HEX               A TXT         FILE B HEX               B TXT
--------------------------------------------------------------------------------------------------------
00002D29  CD C9 C3 D2 CF CC CF C1  |MICROLOA|    A0 CD C9 C3 D2 CF CC CF  | MICROLO|
00002D31  C4 C5 D2 A0 B2 AE B0 A0  |DER 2.0 |    C1 C4 C5 D2 A0 B2 AE B0  |ADER 2.0|
00002D39  A0 A0 A0 A0 A0 A0 A0 D0  |       P|    A0 E2 F9 A0 C7 AE CB AE  | by G.K.|
00002D41  C8 CF C5 CE C9 D8 A0 C3  |HOENIX C|    A0 E6 F2 EF ED A0 CB CE  | from KN|
00002D49  C1 D2 D4 D2 C9 C4 C7 C5  |ARTRIDGE|    D3 A0 C3 CF D2 D0 AE A0  |S CORP. |
00002D51  20 20 20 20 20 20 20 20  |        |    AA AA AA AA AA AA AA AA  |********|
00002D59  20 20 20 20 20 20 20 20  |        |    AA AA AA AA AA AA AA AA  |********|
00002D61  20 20 20 20 20 20 20 20  |        |    AA AA AA AA AA AA AA AA  |********|
00002D69  20 20 20 20 20 20 20 20  |        |    AA AA AA AA AA AA AA AA  |********|
00002D71  20 20 20 20 20 20 20 20  |        |    AA AA AA AA AA AA AA AA  |********|

========================================================================================================
BLOCK 3: diff @ 0x00003291..0x000032E0 (len=80 bytes)
--------------------------------------------------------------------------------------------------------
OFFSET     FILE A HEX               A TXT         FILE B HEX               B TXT
--------------------------------------------------------------------------------------------------------
00003291  CD C9 C3 D2 CF CC CF C1  |MICROLOA|    A0 CD C9 C3 D2 CF CC CF  | MICROLO|
00003299  C4 C5 D2 A0 B2 AE B7 A0  |DER 2.7 |    C1 C4 C5 D2 A0 B2 AE B7  |ADER 2.7|
000032A1  A0 A0 A0 A0 A0 A0 A0 D0  |       P|    A0 A0 E2 F9 A0 A0 C7 AE  |  by  G.|
000032A9  C8 CF C5 CE C9 D8 A0 C3  |HOENIX C|    CB E1 EE E9 E1 A0 A0 A2  |Kania  "|
000032B1  C1 D2 D4 D2 C9 C4 C7 C5  |ARTRIDGE|    C1 D4 C1 D2 C5 D3 A2 A0  |ATARES" |
000032B9  20 20 20 20 20 20 20 20  |        |    C3 E8 EF F2 FA EF F7 A0  |Chorzow |
000032C1  20 20 20 20 20 20 20 20  |        |    C2 E1 F4 EF F2 F9 A0 F5  |Batory u|
000032C9  20 20 20 20 20 20 20 20  |        |    EC AE CA E5 F3 E9 EF EE  |l.Jesion|
000032D1  20 20 20 20 20 20 20 20  |        |    EF F7 E1 A0 B3 A0 F4 E5  |owa 3 te|
000032D9  20 20 20 20 20 20 20 20  |        |    EC AE B4 B6 B5 B7 B1 B9  |l.465719|

I to chyba tyle jeżeli chodzi to co miałem do napisania na temat tego carta. Do usłszenia wkrótce.

Hej!

Po krótkiej przerwie następny cart od uicr0Bee, dziś postaram się krótko i zwięźle, w sumie to miała być formalność, bo to kolejny klon carta z serii "Blizzard HIT", o których pisaliśmy już w tutaj: Blizzard HIT - z kolekcji Dely-ego oraz tutaj, gdzie zaprezentowałem kolejny klon z tej serii: Blizzart HIT - modern clone <--- w tym wypadku wszystko wskazywało na to że była to "nowożytna' replika.

W sumie do tego carta też miałem podejść "po łebkach", bo w sumie to kolejna odmiana Blizzard 32K cart z softem "HIT" w środku. Jednak tym razem autor tego rozwiącania, postanowił nie usuwać do końca śladów po oryginalnym autorze tejże składanki, a jedynie dopisał swoje inicjały do linii z "credits", pozostawiając Artura Miareckiego jako autora oryginalnej "składanki". Sam cart prezentuje się tak:

https://pigwa.code32.org/uicr0bee/carts/Blizzard_32k_Hens/photos/blz_hit_clone_hens_cart.jpg

górna warstwa płytki drukowanej wygląda tak:
https://pigwa.code32.org/uicr0bee/carts/Blizzard_32k_Hens/photos/blz_hit_clone_hens_pcb_top.jpg

a dolna strona prezentuje się następująco:
https://pigwa.code32.org/uicr0bee/carts/Blizzard_32k_Hens/photos/blz_hit_clone_hens_pcb_bot.jpg

Po uruchomieniu widzimy następujący ekran powitalny:
https://pigwa.code32.org/uicr0bee/carts/Blizzard_32k_Hens/scr/blz_hit_clone_hens.png
^^^ Widzimy na nim standardowe menu carta "Blizzard HIT", jednak tak jak wspominałem wyżej pozostała informacja o autorze oraz inicjały "H.M", które prawdopodobnie są inicjałami autora PCB. Dodatkowo na naklejce pamięci EPROM widzimy napisy: "HIT1" oraz wersję oprogramowania "3.93".

Jak wspominałem wyżej, miałem podejść do tego klona "po łebkach", ale w ostatniej chwili tknęło mnie że ta PCB jest nieco inne i schemat nieco się różni od cartów prezentowanych wcześniej, te różnice mnie na tyle zaciekawiły że postanowiłem przerysować schemat na nowo:

https://pigwa.code32.org/uicr0bee/carts/Blizzard_32k_Hens/sch/blz32k_hens_clone.png?
oczywiście do pobrania schemat również w wersji wektorowej: Blizzard 32k - HIT clone "HENS".

Kończąc już ten post pozostaje mi udostępnienie pliku zawierającego zrzut pamięci EPROM: blz_hit_hens.bin.zip.

34ea8c233be22c17e8a02e2eb532dbaf04b89d61a7868d701209aa504572b142  blz_hit_hens.bin | SHA256

hash pliku jest oczywiście inny niż we wcześniej wymienionych klonach, ale to z tego względu że pozmieniano linię zawierającą "credits". Porównując pliki różnice znajdziemy właściewie tylko w tych miejscach gdzie dokonano modyfikacji napisów.

A i jeszcze jedno; Cart to standardowy cart mapujący się w przestrzeni $A000-$BFFF. Cart posiada na pokładzie pamięć 27256, czyli 256kb (kilo-bitów), a więc 32kB. 8kB okno umieszczone w obszarze $A000-$BFFF ma przełączaną zawartość (4 banki po 8 kB). Przełączenie następuje przed odwołanie do obszaru $D500-$D5FF, to powoduje aktywność sygnału ~CCTL, który jest podłączony do wejścia zliczającego licznika 7493. Licznik generuje dwa dodatkowe bity adresu A13,A14. Cart startuje z włączonym BANK #0, kolejne aktywności w obszarze $D5xx powodują przełączanie banków, a w chwili 4 odwołania następuje wyłączenie cartridge. Czyli po starcie mamy BANK #0, potem BANK #1, BANK #2, BANK #3, CARTRIDGE OFF. Kolejne uruchomienie carta wymaga albo cyklu wyłącz/włącz komputera, albo naciśnięcie na carcie przycisku (resetuje przerzutnik RS oraz lincznik 7493 wewnątrz carta) oraz wciśnięci RESET na klawiaturze komputera, wtedy to system operacyjny wykryje pojawienie się cartridge i uruchomi go ponownie. Przypomną tylko jeszcze, że aby uruchomić obraz pod emulatorem wybieramy typ cartridge "Blizzard 32K".

Teraz zaczynam się zastanawiać czy ten "klon" jest faktycznie klonem czy też może to była współpraca Artura Miareckiego i kogoś kto podpisywał się inicjałami "H.M.", a cart był sygnowany jako "HENS". Schemat wygląda na wczesną wersję projektu, klony miały nieco inną konstrukcję (pozbyto się tranzystora, wykorzystano inne części liczników 7490/7493). Ale ja to mogę sobie jedynie dywagować, na te moje dywagacje mógłby pewnie odpowiedzieć jedynie sam autor (Artur Miarecki). Jeżeli ktoś wie kim mógł być H.M. lub HENS proszę o informacje, być może udałoby się wtedy ustalić pochodzenie tego cartridge.

Na dziś tyle! Do usłyszenia niebawem.

49

(16 odpowiedzi, napisanych Różne)

Dzięki Panowie! Fajnie było móc podziałać razem z wami! Sądzę że całkiem zgrabnie nam to wszystko wyszło jak na Atari BASIC!

50

(16 odpowiedzi, napisanych Różne)

#1) dodałem dekoder BASE32 w ML, bo mnie telepało jak widziałem jak to wolno się rysuje! ;-)
#2) wprowadziłem kod BCA
#3) +parę drobnych poprawek

20000 GRAPHICS 0:POKE 752,1
20001 ? "BACK TO THE FUTURE...":SOUND 1,255,10,4:SOUND 2,254,10,3
20002 I=1536: RESTORE 31200
20003 READ V:IF V>=0 THEN POKE I,V:I=I+1:GOTO 20003
20004 FOR I=4 TO 0 STEP -0.1
20005   POKE 710,144+I:POKE 709,I*2
20006 NEXT I
30000 ? CHR$(125):POKE 623,64:FDA=256*PEEK(756)+16*8:? 
30005 FOR N=9 TO 0 STEP -1:Y=8
30010   FOR B=1 TO 6:FDB=PEEK(FDA+N*8+B):X=16:POSITION X,Y
30015     FOR BIT=0 TO 7:? CHR$(32+64*(FDB>=128));:FDB=(FDB-128*(FDB>=128))*2:NEXT BIT
30020     Y=Y+1:NEXT B:GOSUB 32760:NEXT N
30032 REM -- THE WARP --
30033 GRAPHICS 10:POKE 559,0:FOR I=0 TO 7:POKE 705+I,2+I*2:NEXT I
30034 C=0:FOR Q=0 TO 31:SOUND 1,255-Q*2,10,4:SOUND 2,254-Q*2,10,3
30035   COLOR C:C=C+0.5:IF C>7 THEN C=1
30036   PLOT 32-Q,64-Q:DRAWTO 48+Q,64-Q:DRAWTO 48+Q,128+Q:DRAWTO 32-Q,128+Q:DRAWTO 32-Q,64-Q
30037 NEXT Q:C=0:POKE 559,34
30038 Q=PEEK(705):FOR I=0 TO 5:POKE 705+I,PEEK(706+I):SOUND 0,I+Q,8,15:NEXT I
30039 Q=Q+16:IF Q>255 THEN Q=Q-256:C=C+1
30040 POKE 711,Q:IF C<4 THEN 30038
30041 FOR I=0 TO 3:SOUND I,0,0,0:NEXT I:PUT #6,125:GOSUB 32760
30042 REM -- THE LOGO --
30043 RESTORE 31000:GRAPHICS 24:COLOR 1:POKE 765,1:POKE 712,15:POKE 710,15:POKE 709,0
30044 DIM S$(100):TRAP 30075
30045 READ S$:IF LEN(S$)<4 THEN 30060
30049 Q=USR(1536,ADR(S$),LEN(S$))
30050 FOR I=1 TO LEN(S$) STEP 4
30051 C=USR(1536,0):X=USR(1536,1):Y=USR(1536,2)
30054 IF C=0 THEN PLOT X,Y
30055 IF C=1 THEN DRAWTO X,Y
30056 IF C=2 THEN XIO 18,#6,12,0,"S:"
30057 SOUND 0,X,10,4:SOUND 1,Y,12,4
30058 NEXT I:GOTO 30045
30060 SOUND 0,0,0,0:SOUND 1,0,0,0:GOSUB 32760:GOSUB 32760
30075 REM -- BCA FLASHER --- 
30076 FOR II=0 TO 1500:SETCOLOR II/500,II,II:NEXT II
30999 REM -- THE VECTOR DATA (BASE32 ENCODED) --
31000 DATA 04J404LD7ULD7UJ504J504M404N51EN51EN922N922ND2GND2GNH2SNH2SNL34NL34NP3ANP3ANT3INT3IO1
31001 DATA 3OO13OO53SO53SO942O942OD46OD46OH4AOH4AOL4EOL4EOP4IOP4IOT4MOT4MP14OP14OP54SP54SP950P9
31002 DATA 50PD52PD52PH54PH54PL58PL58PP5APP5APT5CPT5CQ15EQ15EQ55GQ55GQ95IQ95IQD5KQD5KQH5MQH5MQL
31003 DATA 5OQL5OQP5QQP5QQT5SQT5SR15UR15UR960R960RD62RD62RH64RH64RP66RP66RT68RT68S56AS56ASD6CSD
31004 DATA 6CSL6ESL6EST6GST6GT56IT56ITH6KTH6KTT6MTT6MU96OU96OUD80UD80U17UU17UTD7STD7SST7QST7QSD
31005 DATA 7OSD7OS57MS57MRP7KRP7KRH7IRH7IR97GR97GR17ER17EQP7CQP7CQH7AQH7AQD78QD78Q576Q576Q174Q1
31006 DATA 74PP72PP72PL70PL70PH6UPH6UPD6SPD6SP96QP96QP16OP16OOT6MOT6MOP6KOP6KOL6GOL6GOH6EOH6EOD
31007 DATA 6COD6CO96AO96AO566O566O164O164NT60NT60NP5UNP5UNL5QNL5QNH5MNH5MND5IND5IN95EN95EN558N5
31008 DATA 58N154N154MT4UMT4UMP4MMP4MML4EML4EMH44MH44MD3OMD3OM934M934M504M504HC04ID1GID1GIH24IH
31009 DATA 24ID3CID3CI93QI93QI546I546I14GI14GHT4OHT4OHP50HP50HL54HL54HH5AHH5AHD5GHD5GH95KH95KH5
31010 DATA 5OH55OH15QH15QGT5UGT5UGP62GP62GL64GL64GH68GH68GD6AGD6AG96CG96CG56GG56GG16IG16IFT6KFT
31011 DATA 6KFP6MFP6MFL6OFL6OFH6QFH6QFD6SFD6SF96UF96UF170F170ET72ET72EP74EP74EH76EH76ED78ED78E9
31012 DATA 7AE97AE17CE17CDP7EDP7EDL7GDL7GDD7IDD7ID57KD57KCP7MCP7MCH7OCH7OC57QC57QBP7SBP7SB97UB9
31013 DATA 7UAH80AH80A96MA96MAL6KAL6KB16IB16IBD6GBD6GBL6EBL6EBT6CBT6CC56AC56ACD68CD68CL66CL66CP
31014 DATA 64CP64D162D162D560D560DD5UDD5UDH5SDH5SDL5QDL5QDP5ODP5ODT5MDT5ME15KE15KE95IE95IED5EED
31015 DATA 5EEH5CEH5CEL5AEL5AEP58EP58ET56ET56F152F152F550F550F94SF94SFD4QFD4QFH4MFH4MFL4IFL4IFP
31016 DATA 4GFP4GFT4CFT4CG146G146G542G542G93UG93UGD3OGD3OGH3IGH3IGL3CGL3CGP36GP36GT2UGT2UH12KH1
31017 DATA 2KH528H528H91IH91IHD04HD8GC08GD58ID58ID98KD98KDD8QDD8QDH90DH90DL96DL96DP9CDP9CDT9IDT
31018 DATA 9IE19OE19OE59UE59UE9A6E9A6EDACEDACEHAIEHAIELAOELAOEPAUEPAUETB4ETB4F1BAF1BAF5BGF5BGF9
31019 DATA BMF9BME5BIE5BIE1BCE1BCDTB4DTB4DPB0DPB0BDB6BDB6B9BCB9BCB5BIB5BIB1BMB1BM9TBI9TBIA1BCA1
31020 DATA BCA5B6A5B6A9B0A9B0ADAQADAQAHAKAHAKALAEALAEAPA6APA6ATA0ATA0B19QB19QB59KB59KB99EB99EBD
31021 DATA 98BD98BH92BH92BL8SBL8SBP8KBP8KBT8IBT8IC18GC18GK08GL18IL18IL58KL58KL98OL98OLD8ULD8ULH
31022 DATA 94LH94LL9ALL9ALP9GLP9GLT9OLT9OM19UM19UM5A4M5A4M9AAM9AAMDAGMDAGMHAMMHAMMLASMLASMPB2MP
31023 DATA B2MTB8MTB8N1BEN1BEN5BMN5BMM1BGM1BGLTBALTBALPB2LPB2LLB0LLB0JDB2JDB2J9B8J9B8J5BEJ5BEJ1
31024 DATA BKJ1BKITBMITBMHPBKHPBKHTBEHTBEI1B8I1B8I5B2I5B2I9ASI9ASIDAMIDAMIHAGIHAGILAAILAAIPA4IP
31025 DATA A4IT9SIT9SJ19MJ19MJ59GJ59GJ99AJ99AJD94JD94JH8UJH8UJL8OJL8OJP8IJP8IK18GK18GOO8GQD8IQD
31026 DATA 8IQP8KQP8KR18MR18MR98OR98ORD8QRD8QRL8URL8URP90RP90RT94RT94S19CS19CS59IS59IS19QS19QRT
31027 DATA 9URT9URPA2RPA2RLA4RLA4RHA6RHA6RDA8RDA8R9AAR9AAR1ACR1ACQPAEQPAEQHAGQHAGQLAIQLAIQPAMQP
31028 DATA AMQTAOQTAOR1AQR1AQR5ASR5ASR9B0R9B0RDB2RDB2RHB4RHB4RLB8RLB8RPBARPBARTBCRTBCS1BES1BES5
31029 DATA BIS5BIS9BKS9BKSDBMSDBMR1BKR1BKQTBIQTBIQPBEQPBEQLBCQLBCQHBAQHBAQDB6QDB6Q9B4Q9B4Q5B2Q5
31030 DATA B2Q1AUQ1AUPTASPTASPPAQPPAQPLAMPLAMPHAKPHAKPDAIPDAIP9A4P9A4PDA2PDA2PTA0PTA0QD9UQD9UQH
31031 DATA 9SQH9SQL9QQL9QQP9OQP9OQT9IQT9IR19CR19CQT98QT98QP96QP96QL94QL94QH92QH92Q590Q590P192P1
31032 DATA 92OTBMOTBMNP8MNP8MNT8KNT8KO98IO98IOP8GOP8GEG8GIH90IH90H5BMH5BMG190G190EH8GEH8GT48GU9
31033 DATA BMU9BMT58GT598CK98CH9CCH9CCD9ICD9IC99OC99OC5A0C5A0C1A6C1A6BTACBTACBPAEBPAEBTAGBTAGDD
31034 DATA AADDAAD9A4D9A4D59UD59UD19OD19OCT9GCT9GCP9ACP9ACL98CL98KG98KD9EKD9EK99KK99KK59QK59QK1
31035 DATA A2K1A2JTA8JTA8JPAGJPAGL9A8L9A8L5A2L5A2L19SL19SKT9MKT9MKP9GKP9GKL9AKL9AKH98KH04HO04HU
31036 DATA 06HO06HU08HO08HU0AHO0AHU0CHO0CHU0EHO0EHU0GHO0GHU0IHO0IHU0KHO0KHU0MHO0MHU0OHO0OHU0QHO
31037 DATA 0QHU0SHO0SHU0UHO0UHU10HO10HU12HO12HU14HO14HU16HO16HU18HO18HU1AHO1AHU1CHO1CHU1EHO1EHU
31038 DATA 1GHO1GHU1IHK1IHQ1KHK1KHQ1MHK1MHQ1OHK1OHQ1QHK1QHQ1SHK1SHQ1UHK1UHQ20HK20HQ22HK22HQ24HK
31039 DATA 24HQ26HK26HQ28HG28HM2AHG2AHM2CHG2CHM2EHG2EHM2GHG2GHM2IHG2IHM2KHC2KHI2MHC2MHI2OHC2OHI
31040 DATA 2QHC2QHI2SHC2SHI2UH82UHE30H830HE32H832HE34H834HE36H436HA38H438HA3AH43AHA3CH03CH63EH0
31041 DATA 3EH63GH03GH63IGS3IH23KGS3KH23MGS3MH23OGO3OGU3QGO3QGU3SGO3SGU3UGK3UGQ40GK40GQ42GG42GM
31042 DATA 44GG44GM46GC46GI48GC48GI4AGC4AGI4CG84CGE4EG84EGE4GG44GGA4IG04IG64KG04KG64MFS4MG24MGS
31043 DATA 4MH24OFS4OG24QFO4QFU4QGO4QGU4SFK4SFQ4SGK4SGQ4UFK4UFQ4UGK4UGQ50FG50FM50GG50GM52FC52FI
31044 DATA 52GG52GM54FC54FI54GC54GI56F856FE56GC56GI58F458FA58G858GE5AF05AF65AG45AGA5CES5CF25CG4
31045 DATA 5CGA5EEO5EEU5EG05EG65GEO5GEU5GG05GG65IEK5IEQ5IFS5IG25KEC5KEI5KFO5KFU5ME85MEE5MFK5MFQ
31046 DATA 5OE45OEA5OFG5OFM5QE05QE65QFC5QFI5SDS5SE25SFC5SFI5UDO5UDU5UF85UFE60DG60DM60F460FA62DC
31047 DATA 62DI62F062F664D464DA64EO64EU66D066D666EO66EU68CO68CU68EG68EM6ACG6ACM6AEC6AEI6CC86CCE
31048 DATA 6CE46CEA6EC06EC66EE06EE66GBO6GBU6GDS6GE26IBC6IBI6IDK6IDQ6KB06KB66KDC6KDI6MAK6MAQ6MD4
31049 DATA 6MDA6OAK6OAQ6OD06OD66QAK6QAQ6QD06QD66SAK6SAQ6SCS6SD26UAK6UAQ6UCO6UCU70AK70AQ70CO70CU
31050 DATA 72AK72AQ72CK72CQ74AK74AQ74CG74CM76AK76AQ76CG76CM78AK78AQ78CC78CI7AAK7AAQ7AC87ACE7CAK
31051 DATA 7CAQ7CC47CCA7EAK7EAQ7EC47ECA7GAK7GAQ7GC07GC67IAK7IAQ7IBS7IC27KAK7KAQ7KBK7KBQ7MAK7MAQ
31052 DATA 7OAK7OAQ7QAK7QAQ7SAK7SAQ04JG04JM06JG06JM08JG08JM0AJG0AJM0CJG0CJM0EJG0EJM0GJG0GJM0IJG
31053 DATA 0IJM0KJG0KJM0MJG0MJM0OJG0OJM0QJG0QJM0SJG0SJM0UJG0UJM10JG10JM12JG12JM14JG14JM16JG16JM
31054 DATA 18JG18JM1AJG1AJM1CJG1CJM1EJG1EJM1GJG1GJM1IJG1IJM1KJG1KJM1MJG1MJM1OJG1OJM1QJG1QJM1SJG
31055 DATA 1SJM1UJG1UJM20JG20JM22JG22JM24JG24JM26JG26JM28JG28JM2AJG2AJM2CJG2CJM2EJG2EJM2GJG2GJM
31056 DATA 2IJG2IJM2KJG2KJM2MJG2MJM2OJG2OJM2QJG2QJM2SJG2SJM2UJG2UJM30JG30JM32JG32JM34JG34JM36JG
31057 DATA 36JM38JG38JM3AJG3AJM3CJG3CJM3EJG3EJM3GJG3GJM3IJG3IJM3KJG3KJM3MJG3MJM3OJG3OJM3QJG3QJM
31058 DATA 3SJG3SJM3UJG3UJM40JG40JM42JG42JM44JG44JM46JG46JM48JG48JM4AJG4AJM4CJG4CJM4EJG4EJM4GJG
31059 DATA 4GJM4IJG4IJM4KJG4KJM4MJG4MJM4OJG4OJM4QJG4QJM4SJG4SJM4UJG4UJM50JG50JM52JG52JM54JG54JM
31060 DATA 56JG56JM58JG58JM5AJG5AJM5CJG5CJM5EJG5EJM5GJG5GJM5IJG5IJM5KJG5KJM5MJG5MJM5OJG5OJM5QJG
31061 DATA 5QJM5SJG5SJM5UJG5UJM60JG60JM62JG62JM64JG64JM66JG66JM68JG68JM6AJG6AJM6CJG6CJM6EJG6EJM
31062 DATA 6GJG6GJM6IJG6IJM6KJG6KJM6MJG6MJM6OJG6OJM6QJG6QJM6SJG6SJM6UJG6UJM70JG70JM72JG72JM74JG
31063 DATA 74JM76JG76JM78JG78JM7AJG7AJM7CJG7CJM7EJG7EJM7GJG7GJM7IJG7IJM7KJG7KJM7MJG7MJM7OJG7OJM
31064 DATA 7QJG7QJM7SJG7SJM04MG04MM06MG06MM08MG08MM0AMG0AMM0CMG0CMM0EMG0EMM0GMG0GMM0IMG0IMM0KMG
31065 DATA 0KMM0MMG0MMM0OMG0OMM0QMG0QMM0SMG0SMM0UMG0UMM10MG10MM12MG12MM14MG14MM16MG16MM18MG18MM
31066 DATA 1AMG1AMM1CMG1CMM1EMG1EMM1GMG1GMM1IMG1IMM1KMG1KMM1MMG1MMM1OMG1OMM1QMG1QMM1SMG1SMM1UMG
31067 DATA 1UMM20MG20MM22MG22MM24MG24MM26MG26MM28MG28MM2AMG2AMM2CMG2CMM2EMG2EMM2GMG2GMM2IMG2IMM
31068 DATA 2KMG2KMM2MMG2MMM2OMG2OMM2QMG2QMM2SMG2SMM2UMG2UMM30MG30MM32MG32MM34MK34MQ36MK36MQ38MK
31069 DATA 38MQ3AMK3AMQ3CMK3CMQ3EMK3EMQ3GMK3GMQ3IMK3IMQ3KMK3KMQ3MMK3MMQ3OMO3OMU3QMO3QMU3SMO3SMU
31070 DATA 3UMO3UMU40MO40MU42MO42MU44MS44N246MS46N248MS48N24AMS4AN24CMS4CN24EN04EN64GN04GN64IN0
31071 DATA 4IN64KN04KN64MN44MNA4ON44ONA4OO44OOA4QN44QNA4QO44QOA4SN44SNA4SO44SOA4UN84UNE4UO84UOE
31072 DATA 50N850NE50O850OE52N852NE52OC52OI54NC54NI54OG54OM56NC56NI56OG56OM58NG58NM58OK58OQ5ANG
31073 DATA 5ANM5AOK5AOQ5CNG5CNM5COO5COU5ENK5ENQ5EOS5EP25GNK5GNQ5GOS5GP25INO5INU5IP05IP65KNO5KNU
31074 DATA 5KP45KPA5MNS5MO25MP85MPE5ONS5OO25OP85OPE5QO05QO65QPC5QPI5SO05SO65SPG5SPM5UO45UOA5UPK
31075 DATA 5UPQ60O860OE60PO60PU62O862OE62PS62Q264OC64OI64Q064Q666OG66OM66Q466QA68OG68OM68Q868QE
31076 DATA 6AOK6AOQ6AQG6AQM6COO6COU6CQK6CQQ6EOS6EP26EQS6ER26GP06GP66GR06GR66IP06IP66IR86IRE6KP4
31077 DATA 6KPA6KRG6KRM6MP86MPE6MRO6MRU6OPC6OPI6ORS6OS26QPK6QPQ6QS06QS66SPO6SPU6SS06SS66UPS6UQ2
31078 DATA 6US46USA70Q070Q670S470SA72Q472QA72S872SE74QC74QI74SC74SI76QG76QM76SC76SI78QO78QU78SG
31079 DATA 78SM7AQS7AR27ASK7ASQ7CR47CRA7CSO7CSU7ERC7ERI7ESS7ET27GRK7GRQ7GT07GT67IRS7IS27IT47ITA
31080 DATA 7KS47KSA7KT87KTE7MSG7MSM7OSO7OSU7QT87QTE7STO7STU8GCC8GCI8IC88ICE8KC48KCA8MC48MCA8OC4
31081 DATA 8OCA8QC48QCA8SC08SC68UC08UC690C090C692BS92C294BS94C296BS96C298BO98BU98D098D69ABO9ABU
31082 DATA 9AD49ADA9CBO9CBU9CD49CDA9EBK9EBQ9ED49EDA9GBK9GBQ9GD89GDE9IBK9IBQ9ID89IDE9KBG9KBM9KD8
31083 DATA 9KDE9MBG9MBM9MD89MDE9OBG9OBM9ODC9ODI9QBC9QBI9QDC9QDI9SBC9SBI9SDC9SDI9UBC9UBI9UDG9UDM
31084 DATA A0B8A0BEA0DGA0DMA2B8A2BEA2DGA2DMA4B8A4BEA4DKA4DQA6B4A6BAA6DKA6DQA8B4A8BAA8DKA8DQAAB4
31085 DATA AABAAADOAADUACB4ACBAACDOACDUAEB0AEB6AEDOAEDUAGB0AGB6AGCOAGCUAIB0AIB6AICOAICUAKASAKB2
31086 DATA AKCOAKCUAMASAMB2AMCOAMCUAOASAOB2AOCOAOCUAQAOAQAUAQCOAQCUASAOASAUASCOASCUAUAOAUAUAUCO
31087 DATA AUCUB0AKB0AQB0E4B0EAB2AKB2AQB2E4B2EAB4AKB4AQB4E8B4EEB6AGB6AMB6E8B6EEB8AGB8AMB8E8B8EE
31088 DATA BAAGBAAMBAE8BAEEBCACBCAIBCECBCEIBEACBEAIBEECBEEIBGACBGAIBGECBGEIBIA8BIAEBIEGBIEMBKA8
31089 DATA BKAEBKEGBKEM8GES8GF28GGK8GGQ8IES8IF28IGK8IGQ8KES8KF28KGK8KGQ8MES8MF28MGK8MGQ8OES8OF2
31090 DATA 8OGK8OGQ8QES8QF28QGK8QGQ8SES8SF28SGK8SGQ8UES8UF28UGK8UGQ90GC90GI92GC92GI94GC94GI96GC
31091 DATA 96GI98GC98GI9AGC9AGI9CGC9CGI9EGC9EGI9GGC9GGI9IGC9IGI9KGC9KGI9MGC9MGI9OGC9OGI9QGC9QGI
31092 DATA 9SGC9SGI9UGC9UGIA0GCA0GIA2GCA2GIA4GCA4GIA6GCA6GIA8GCA8GIAAGCAAGIACGCACGIAEGCAEGIAGGC
31093 DATA AGGIAIGCAIGIAKGCAKGIAMGCAMGIAOGCAOGIAQGCAQGIASGCASGIAUGCAUGIB0GCB0GIB2GCB2GIB4GCB4GI
31094 DATA B6GCB6GIB8GCB8GIBAGCBAGIBCGCBCGIBEGCBEGIBGGCBGGIBIGCBIGIBKGCBKGI8GKC8GKI8IK48IKA8KK4
31095 DATA 8KKA8MK48MKA8OK08OK68QK08QK68SK08SK68UJS8UK290JS90K292JS92K294JO94JU96JO96JU98JO98JU
31096 DATA 98KS98L29AJK9AJQ9AL09AL69CJK9CJQ9CL09CL69EJK9EJQ9EL09EL69GJG9GJM9GL49GLA9IJG9IJM9IL4
31097 DATA 9ILA9KJG9KJM9KL49KLA9MJC9MJI9ML89MLE9OJC9OJI9OL89OLE9QJC9QJI9QL89QLE9SJ89SJE9SLC9SLI
31098 DATA 9UJ89UJE9ULC9ULIA0J8A0JEA0LCA0LIA2J8A2JEA2LGA2LMA4J4A4JAA4LGA4LMA6J4A6JAA6LGA6LMA8J4
31099 DATA A8JAA8LKA8LQAAJ0AAJ6AALKAALQACJ0ACJ6ACLKACLQAEJ0AEJ6AELKAELQAGISAGJ2AGKKAGKQAIISAIJ2
31100 DATA AIKKAIKQAKISAKJ2AKKKAKKQAMIOAMIUAMKKAMKQAOIOAOIUAOKKAOKQAQIOAQIUAQKKAQKQASIKASIQASKK
31101 DATA ASKQAUIKAUIQAUKKAUKQB0IKB0IQB0M0B0M6B2IGB2IMB2M4B2MAB4IGB4IMB4M4B4MAB6IGB6IMB6M4B6MA
31102 DATA B8ICB8IIB8M4B8MABAICBAIIBAM8BAMEBCICBCIIBCM8BCMEBEI8BEIEBEM8BEMEBGI8BGIEBGMCBGMIBII8
31103 DATA BIIEBIMCBIMIBKI4BKIABKMCBKMI8GP48GPA8IOK8IOQ8IPK8IPQ8KO88KOE8KPK8KPQ8MO48MOA8MPK8MPQ
31104 DATA 8OO48OOA8OPO8OPU8QO48QOA8QPS8QQ28SO48SOA8SPS8SQ28UO48UOA8UPS8UQ290O490OA90QG90QM92O4
31105 DATA 92OA92QS92R294O494OA94R094R696O496OA96R496RA98O498OA98R898RE9AO49AOA9AR89ARE9CO49COA
31106 DATA 9CRC9CRI9EO49EOA9ERC9ERI9GO49GOA9GRC9GRI9IO49IOA9IR89IRE9KO49KOA9KR89KRE9MO49MOA9MR8
31107 DATA 9MRE9OO49OOA9OR49ORA9QO49QOA9QR09QR69SO49SOA9SQS9SR29UO49UOA9UQO9UQUA0O4A0OAA0Q8A0QE
31108 DATA A2O4A2OAA2POA2PUA4O4A4OAA4PKA4PQA6O4A6OAA6PKA6PQA8O4A8OAA8PKA8PQAAO4AAOAAAPKAAPQACO4
31109 DATA ACOAACPKACPQAEO4AEOAAEPKAEPQAGO4AGOAAGPKAGPQAIO4AIOAAIPOAIPUAKO4AKOAAKPSAKQ2AMO4AMOA
31110 DATA AMQ0AMQ6AOO4AOOAAOQ0AOQ6AQO4AQOAAQQ4AQQAASO4ASOAASQ8ASQEAUO4AUOAAUQCAUQIB0O4B0OAB0QC
31111 DATA B0QIB2O4B2OAB2QGB2QMB4O4B4OAB4QKB4QQB6O4B6OAB6QOB6QUB8O4B8OAB8QOB8QUBAO4BAOABAQSBAR2
31112 DATA BCO4BCOABCR0BCR6BEO4BEOABER4BERABGO4BGOABGR4BGRABIO4BIOABIR8BIREBKO4BKOABKRCBKRI8GTG
31113 DATA 8GTM8ITG8ITM8KTG8KTM8MTG8MTM8OTG8OTM8QTG8QTM8STG8STM8UTG8UTM90TG90TM92TG92TM94TG94TM
31114 DATA 96TG96TM98TG98TM9ATG9ATM9CTG9CTM9ETG9ETM9GTG9GTM9ITG9ITM9KTG9KTM9MTG9MTM9OTG9OTM9QTG
31115 DATA 9QTM9STG9STM9UTG9UTMA0TGA0TMA2TGA2TMA4TGA4TMA6TGA6TMA8TGA8TMAATGAATMACTGACTMAETGAETM
31116 DATA AGTGAGTMAITGAITMAKTGAKTMAMTGAMTMAOTGAOTMAQTGAQTMASTGASTMAUTGAUTMB0TGB0TMB2TGB2TMB4TG
31117 DATA B4TMB6TGB6TMB8TGB8TMBATGBATMBCTGBCTMBETGBETMBGTGBGTMBITGBITMBKTGBKTM
31118 REM -- END OF VECTOR DATA --
31200 REM -- ML BASE32 DECODER --
31201 DATA 104,201,2,144,87,104,133,204,104,133,203,104,104,141,83,6
31202 DATA 160,0,140,58,6,162,4,138,72,162,5,6,205,38,206,38
31203 DATA 207,202,208,247,104,170,177,203,56,233,48,201,10,144,2,233
31204 DATA 7,5,205,133,205,200,202,208,222,162,51,165,205,157,0,4
31205 DATA 232,165,206,157,0,4,232,165,207,41,7,157,0,4,232,142
31206 DATA 58,6,192,68,144,191,169,0,141,96,6,96,104,104,168,162
31207 DATA 51,192,0,208,12,189,0,4,41,3,133,212,169,0,133,213
31208 DATA 96,192,1,208,15,189,0,4,133,212,189,1,4,41,7,133
31209 DATA 213,76,161,6,192,2,208,33,189,1,4,133,212,189,2,4
31210 DATA 41,7,133,213,24,169,3,109,96,6,141,96,6,70,213,102
31211 DATA 212,70,213,102,212,70,213,102,212,96,-1
32758 POKE 752,0:GRAPHICS 0
32759 END 
32760 POKE 20,0
32761 IF PEEK(20)<64 THEN 32761
32762 RETURN 
32763 REM Prima Aprilis Compo 2026
32764 REM by Lizard, Mono, tbxx, dely, Seban, BCA