Autor Wątek: Issue 2 Keyboard vs. Issue 3 Keyboard  (Przeczytany 6204 razy)

matofesi

  • *****
  • Wiadomości: 2050
  • Miejsce pobytu:
    Toruń/Poland
Odp: Issue 2 Keyboard vs. Issue 3 Keyboard
« Odpowiedź #15 dnia: 2017.01.25, 11:23:31 »
A ja z ciekawości zajrzałem sobie w kod jak wygląda ten nieszczęsny wybór sterowania (bo żeby było zabawnie jak się w emulatorze przełączy klawiaturę w Issue 2, wybierze klawiaturę jako sterowanie odpalając grę a potem wyłączy Issue 2 to gra działa czyli w samej rozgrywce klawiatura wydaje się być czytana poprawnie). Kod wygląda... dziwnie ;)

...

ld hl,$f7fe
push hl
pop bc
in a,(c)
ld l,a
ld h,0
ex de,hl
ld hl,$00fd
xor a
sbc hl,de
jp nz,$c2b8 ; skok jeśli nie jest wciśnięty oczekiwany klawisz
; tu następuje ustawienie zmiennej określającej wciśnięcie konkretnego
; klawisza i wyskok z procedury
...


Ten sam pattern jest powtarzany jeszcze dwa razy zmienia się tylko wartość ładowana do HL przed SBC HL,DE. Wartość ta to w kolejnych przebiegach $FD, $FB i $F7 - binarnie to odpowiednio 11111101, 11111011 i 11110111. Kod czyta więc stan "półrzędu" klawiatury 1-5 a następnie sprawdza czy to, co przeczytał zgadza się z zakładanym patternem - pierwszy to zgaszony bit 01 czyli wciśnięte 4, drugi to bit 02 - wciśnięte 3, trzeci to bit 03 - wciśnięte 2. Tylko zamiast sprawdzać konkretne bity odczytane z portu (i najlepiej robić to jednym odczytem a potem ewentualnie sprawdzić zwolnienie klawisza) czyta trzy razy i porównuje z całym bajtem wliczając w to trzy nadmiarowe bity w tym ten, który w nowszych wersjach jest bardziej podatny na to, co jest wcześniej do portu $FE wysyłane. A w tym wypadku tuż przed odczytem klawiatury wywoływana jest procedura grania beeperem z ROMu w której oczywiście zapisów jest mnóstwo. Efekt jest taki, że w wypadku Issue 3 szósty bit czytany z portu $FE (w tym wypadku $F7FF) zawsze jest wyzerowany i zwracany pattern nigdy nie ma na trzech najwyższych bitach samych jedynek co oczywiście powoduje, że gry nie da się wystartować.

Podobnie przedziwne kombinacje są używane do odczytu klawiatury w samej grze, ale z jakiegoś powodu tam Issue 3 wydaje się nie przeszkadzać w działaniu - być może zapisy do $FE odbywają się w innej kolejności/miejscu i nie wpływają już na stan szóstego bitu. Nie chce mi się tego dalej analizować, bo kod wygląda dość koszmarnie - prawdopodobnie był kompilowany z czegoś wysokopoziomowego.

ikci

  • *****
  • Wiadomości: 1216
  • Miejsce pobytu:
    Kraków
Odp: Issue 2 Keyboard vs. Issue 3 Keyboard
« Odpowiedź #16 dnia: 2017.01.25, 13:28:55 »
Mat, dziękuję !
Lubię Cię za to, że czasami zachce Ci się znaleźć chwilę i zajrzeć do kodu aby później coś całkiem przystępnie wyjaśnić.

To ciekawostka z tym kodem kompilowanym z czegoś wysokopoziomowego. Gra powstała także na Amstrada / Schneidera CPC.
(a może powstała na  CPC wcześniej?)
Może po prostu ktoś próbował żywcem kopiować kod z tamtej maszyny, ale komplikacje wynikające z różnic sprzętowych "omijał"
kombinując i komplikując w ten sposób kod ?
ZX Spectrum 48K, ZX Spectrum +, ZX Spectrum 128K, ZX Spectrum +2, ZX Spectrum +2B, ZX Spectrum +3, TIMEX TC2048, UNIPOLBRIT Komputer 2068, Didaktik Gama 80kB, 
Amstrad/Schneider CPC6128, Schneider CPC464, Commodore C64, Atari 800XL, 65XE 130XE, A500+, A600, A1200, ATARI 1040 STF

matofesi

  • *****
  • Wiadomości: 2050
  • Miejsce pobytu:
    Toruń/Poland
Odp: Issue 2 Keyboard vs. Issue 3 Keyboard
« Odpowiedź #17 dnia: 2017.01.25, 13:53:35 »
Nie wiem jak to było pisane, ale jakby robił to ktoś "kumaty" w assemblerze to raczej nie robiłby takich konstrukcji. Przecież odczyt tych trzech klawiszy to jest coś takiego:
...
ld bc,$f7ff
in a,(c)
bit 1,a
jr z, klawisz_1
bit 2,a
jr z,klawisz_2
bit 3,a
jr z_klawisz_3
...

Zajmuje znacznie mniej miejsca, jest znacznie bardziej czytelne, działa na każdej wersji Spectrum. Można oczywiście zrobić kilka wariacji na ten temat, ale zasadniczo każdy "szanujący się" programista będzie to robił podobnie. Cytowany wyżej kod wygląda tak jakby robił go ktoś, kto zupełnie nie ma pojęcia o assemblerze albo automat... Przypomina kompilację pseudokodu:

let port=$f7fe
let a=in(port)
let klawisz=a
let oczekiwane=$00fd
if klawisz != oczekiwane then goto dalej

...

dalej:
let port=$f7fe
let a=in(port)
let klawisz=a
let oczekiwane=$00fb

...

Efekt jest jaki jest - działa... zwykle ;)

edit: Znalazłem stronę na której jest info, że Abu Simbel wyszło w tym samym roku na MSX i Spectrum... Może kod był pisany dla MSXa a potem dostosowywany do Spectrum... Nie wiem - nie chcę zgadywać :)
« Ostatnia zmiana: 2017.01.25, 13:59:41 wysłana przez matofesi »