Autor Wątek: Przerwania - ZX Spectrum 48  (Przeczytany 14723 razy)

dr.df0

  • *
  • Wiadomości: 15
  • Miejsce pobytu:
    Poland
Przerwania - ZX Spectrum 48
« dnia: 2021.10.14, 19:43:20 »
Witajcie,

Przeglądając kod mojego starego demka (z przełomu 1990/1991) znalazłem ciekawą (niestety bardzo słabo przenośną na klony, inne modele i rozszerzone gumiaczki) metodę uruchamiania kodu na przerwaniach.

Metoda polega na wykorzystaniu trybu przerwań IM 2 procesora Z80 (tryb ma chyba nazwę vectored interrupt), a polega na tym, że do rejestru I wstawia się starszy bajt adresu tablicy zawierającej adresy procedur obsługujących przerwania, której adres w teorii (chyba również w praktyce, choć podobno Z80 nie obsługuje poprawnie nieparzystych indeksów, czyli potrafi procedurę z spod nieparzystego indeksu również wywołać) powinna być w momencie wygenerowania przerwania wczytana z szyny danych z urządzenia zewnętrznego.

Trik, który stosowaliśmy polegał na dwóch założeniach:

  • W niezmodyfikowanym ROM-ie ZX Spectrum 48k od adresu $3900 znajduje się ciągły blok ponad 257 bajtów wypełnionych wartościami $FF, więc ustawienie rejestru I na wartość $39 (przy trybie przerwań IM 2) powodowało przy każdym przerwaniu VBLANK skok do adresu $FFFF, bo niezależnie jaka wartość była aktualnie na szynie danych ($00 - $FF), to w bloku pamięci ROM wskazanym jako tablica wektorów przerwań ($3900 - $3A00, bo I = $39) zawsze otrzymywaliśmy adres procedury obsługi przerwania = $FFFF.

    Uwaga: tablica wektorów przerwań musi mieć rozmiar 257 bajtów, a nie 256, bo potencjalnie na szynie danych może pojawić się wartość $FF i wtedy adres procedury obsługi przerwania jest pobierany z lokalizacji $39FF i $3A00 (257 bajt, licząc od $3900).

  • W pamięci ROM pod adresem $0000 mieści się wartość $F3, więc jeśli do komórki pamięci $FFFF wpiszemy opcode dla rozkazu JR ($18), to rozkaz ten przy wykonaniu w trakcie obsługi przerwania pobierze swój operand z kolejnego adresu, czyli $0000, co w efekcie spowoduje skok pod adres $FFF4, gdzie umieszczaliśmy rozkaz JP irq_routine

Przykładowy kod, który korzysta z ten sztuczki i działa chyba tylko na oryginalnym ZX Spectrum 48k (w formacie pasmo) może wyglądać tak:

    org $8000

start:
   call irq_init

; basically do nothing, as the main job of changing backgroud colors
; is done in the irq routine
loop:
    halt

    jr  loop
   
irq:
    di
   
    push af
    push hl
   
    ld  hl, color
    ld  a, (hl)
    and 7
    out (254), a
    inc (hl)

    pop  hl
    pop  af

    ei
    ret

; VARIABLES
color: db 0

;; ========================================================
;;   IRQ Init Routine
;; ========================================================
irq_init:
    halt
    di

    ld  hl, $FFFF
    ld  (hl), $18 ; JR opcode

    ; set the IM2 mode to use jump table at $3900 (block of $FF in ROM)
    ld  a, $39
    ld  i, a
    im  2

    ; insert JP irq at address $FEFE
    ld  hl, $FFF4
    ld  (hl), $C3 ; JP opcode
    inc hl
    ld  (hl), LOW irq
    inc hl
    ld  (hl), HIGH irq

    ei
    retn

    end $8000

Tak to robiliśmy wtedy ... oczywiście ten kod można trochę poprawić (pracuje wtedy np. na 128k), używając spreparowanej tablicy wektorów w pamięci RAM, co realizuje poniższa procedura irq_init, którą można podmienić we wcześniejszym kodzie.

;; ========================================================
;;   IRQ Init Routine - more generic
;; ========================================================
irq_init:
    halt
    di

    ; fill 257 bytes starting from $FD00 with $FE,
    ; so IRQ in IM 2 mode will always jump to $FEFE
    ld  hl, $FD00
    ld  de, $FD01
    ld  bc, 257
    ld  (hl), $FE
    ldir

    ; set the IM2 mode to use jump table at $FD00
    ld  a, $FD
    ld  i, a
    im  2

    ; insert JP irq at address $FEFE
    ld  hl, $FEFE
    ld  (hl), $C3 ; JP opcode
    inc hl
    ld  (hl), LOW irq
    inc hl
    ld  (hl), HIGH irq

    ei
    ret

Pozdrawiam i ciekaw jestem waszych uwag!

Phonex

  • *****
  • Wiadomości: 1260
  • Miejsce pobytu:
    Warszawa
Odp: Przerwania - ZX Spectrum 48
« Odpowiedź #1 dnia: 2021.10.14, 21:48:19 »
Tak się wtedy robiło. Tą sztuczkę na forum opisywał rafamiga parę lat temu.
Kto ją spopularyzował w "środowisku"? Nie pamiętam, ale oczywiście też stosowałem.
Ten napisał rafamiga https://www.speccy.pl/forum/index.php?topic=4489.msg72050#msg72050
Ten napisałem ja https://www.speccy.pl/forum/index.php?topic=4489.msg72225#msg72225
Zajrzałem na szybko i jedyna różnica, to z przekory (tak! przypomniałem sobie - chciałem się odróżniać 8) ) użyłem tablicę pod $3B00, a nie $3900 ;)

I to działa na ZX128! Bez żadnego dołączonego interfejsu na szynie jest $FF, więc adres bierze spod $39FF (lub $3BFF lub też $3AFF). W tych trzech strategicznych miejscach projektanci ZX128 specjalnie zostawili dwa $FF! Widać, że specjalnie bo w jednej z tych lokalizacji przed nimi jest skok omijający o dwa bajty :D
W czasie dyskusji na ten temat ktoś (chyba trojacek) napisał, że w zasadzie nawet z dołączonymi interfejsami w momencie odczytu wektora nie ma szans, żeby na szynie było cokolwiek innego niż $FF.
Na Pentagonie też działa. Ta jego część jest zgodna ze 128.

Także nie wiem do końca, czemu ten sposób jest odradzany? Może na innyh klonach nie działa...
Albo może chodzi o niezgodność z dodatkowymi ROMami ZX128? Że np. w edytorze Basica nie działało by? A w +3 w czasie operacji dyskowych?

KWF

  • *****
  • Wiadomości: 6823
  • Miejsce pobytu:
    trzecia planeta od Słońca
  • "I co ja robię tu, u-u, co Ty tutaj robisz ..."
    • Insta do lasownia
Odp: Przerwania - ZX Spectrum 48
« Odpowiedź #2 dnia: 2021.10.14, 21:57:31 »
Dzięki za podzielenie się i wyjaśnienia. Swoją drogą, kilka tygodni temu z matem pisałem o lokalizacji wektora przerwań na Discorcie. W zasadzie kiedy wywoływane jest przerwanie wszystkie urządzenia powinny być odłączone od szyny danych, w 99% przypadków (w zasadzie zawsze, o ile nie mamy jakiegoś interfejsu siejącego po szynie danych) procesor odczyta $FF. W „wolnym” bloku ROM są możliwe trzy alokacje wektora przerwań ($3900, $3A00 i $3B00) i z tego co pisał mat, to wystarczy 6 bajtów (3 lokacje po 2 bajty), aby obsłużyć przerwania. Ma to znaczenie, w przypadku modyfikowanych ROMow, wiec warto byłoby zostawiać te 6 bajtów z wartością $FF, a resztę wykorzystać zgodnie z własnym uznaniem.
KWF
-----
R Tape loading error 0:1
Moje zabawki: https://github.com/McKlaud76

matofesi

  • *****
  • Wiadomości: 2048
  • Miejsce pobytu:
    Toruń/Poland
Odp: Przerwania - ZX Spectrum 48
« Odpowiedź #3 dnia: 2021.10.15, 09:33:56 »
Także nie wiem do końca, czemu ten sposób jest odradzany? Może na innyh klonach nie działa...
Albo może chodzi o niezgodność z dodatkowymi ROMami ZX128? Że np. w edytorze Basica nie działało by? A w +3 w czasie operacji dyskowych?

Tak - chodzi głównie o inne maszyny - jakieś nietypowe klony w których ludzie dokładają kod w "wolnym" miejscu nie zwracając uwagi na FFy czy też urządzenia podmieniające ROM, które również nie zwracają uwagi na to, żeby zachować te 6 bajtów.

Nie pamiętam o co dokładnie chodziło (ponad 30 lat minęło ;)), ale na 100% były jakieś sytuacje/maszyny na których taka obsługa przerwań nie działała.

trojacek

  • *****
  • Wiadomości: 6831
  • Miejsce pobytu:
    Warszawa
Odp: Przerwania - ZX Spectrum 48
« Odpowiedź #4 dnia: 2021.10.15, 09:46:41 »
ale na 100% były jakieś sytuacje/maszyny na których taka obsługa przerwań nie działała.

All-RAM?

matofesi

  • *****
  • Wiadomości: 2048
  • Miejsce pobytu:
    Toruń/Poland
Odp: Przerwania - ZX Spectrum 48
« Odpowiedź #5 dnia: 2021.10.15, 10:23:24 »
To też, ale chodzi mi po głowie jakaś wersja Unipolbrita czy coś takiego...

Sprawdziłem - ROM do TC2068, który przychodzi w pakiecie z Fuse ma kod w całym obszarze FFów - wolne miejsce jest od $3CDC do $3D00 gdzie zaczyna się generator znaków, czyli nie ma dwóch FFów w odpowiednim miejscu na żadnej z trzech stron.

KWF

  • *****
  • Wiadomości: 6823
  • Miejsce pobytu:
    trzecia planeta od Słońca
  • "I co ja robię tu, u-u, co Ty tutaj robisz ..."
    • Insta do lasownia
Odp: Przerwania - ZX Spectrum 48
« Odpowiedź #6 dnia: 2021.10.15, 11:05:13 »
TS2068/TC2068/UK2086 mają 24KB ROM (16K + 8K). Timexowe MMU tym rządzi i przełącza pomiędzy tymi ROMami. Część BASICa jest w dodatkowych 8K. Musiałbym zaglądnąć do instrukcji serwisowej TS2068, aby dokładnie sprawdzić mechanizm przełączania przy starcie systemu, bo jest to tam dobrze opisane.
KWF
-----
R Tape loading error 0:1
Moje zabawki: https://github.com/McKlaud76

matofesi

  • *****
  • Wiadomości: 2048
  • Miejsce pobytu:
    Toruń/Poland
Odp: Przerwania - ZX Spectrum 48
« Odpowiedź #7 dnia: 2021.10.15, 11:20:46 »
Wiem, że tam jest 24 kilo, ale w tych podstawowych 16 w miejscu, gdzie są FFy jest dodatkowy kod - nie patrzyłem czego dokładnie dotyczy, po kawałkach tekstu, które widzę ("Start tape, then press any key", "Program:","Number array:","Character array:","Bytes:") z jakiegoś powodu jest tam przeniesiona część obsługi taśmy.

KWF

  • *****
  • Wiadomości: 6823
  • Miejsce pobytu:
    trzecia planeta od Słońca
  • "I co ja robię tu, u-u, co Ty tutaj robisz ..."
    • Insta do lasownia
Odp: Przerwania - ZX Spectrum 48
« Odpowiedź #8 dnia: 2021.10.15, 11:35:50 »
ROM TS/TC2068 był przepisany od nowa, posiada dodatkowe słowa BASICa, mechanizmy obsługi stronicowania pamięci, obsługę AYka i jeszcze kilka innych rzeczy. Stad jego rozdmuchanie do 24K i inny układ niż oryginalny. Zajrzyj do manuskryptu, tam są także odnośniki do oryginalnego ROMu Sinclaira.

https://www.speccy.pl/forum/index.php?topic=5346.msg82029#msg82029
KWF
-----
R Tape loading error 0:1
Moje zabawki: https://github.com/McKlaud76

matofesi

  • *****
  • Wiadomości: 2048
  • Miejsce pobytu:
    Toruń/Poland
Odp: Przerwania - ZX Spectrum 48
« Odpowiedź #9 dnia: 2021.10.15, 11:45:14 »
Ta... Zrobiłem diff'a na rozkompilowanych ROMach - 800kilo i ponad 4000 linii różnicy ;)

Istotne w kontekście tego wątku jest to, że przy przepisywaniu nie pomyślano o zachowaniu naszych sześciu bajtów i co za tym idzie przerwania nie będą działały.

tooloud

  • *****
  • Wiadomości: 3185
  • Miejsce pobytu:
    Warszawa
  • mydłem go!
Odp: Przerwania - ZX Spectrum 48
« Odpowiedź #10 dnia: 2021.10.15, 12:02:43 »
Dzięki za kolejny fajny wątek!
dużo sprzętu mało czasu.

dr.df0

  • *
  • Wiadomości: 15
  • Miejsce pobytu:
    Poland
Odp: Przerwania - ZX Spectrum 48
« Odpowiedź #11 dnia: 2021.10.15, 13:08:36 »
też dzięki za wszystkie rzeczowe komentarze - okazuje się, że po 30-tu latach, też można się jeszcze czegoś ciekawego nauczyć :)

Gryzor

  • *****
  • Wiadomości: 2009
  • Miejsce pobytu:
    Warszawa
Odp: Przerwania - ZX Spectrum 48
« Odpowiedź #12 dnia: 2021.10.15, 13:19:38 »
No coz, do odkrycia jeszcze troche zostalo, np. jak "zrobic" floating bus na Timexie :-)
Oczywiscie bez zmian sprzetowych.

trojacek

  • *****
  • Wiadomości: 6831
  • Miejsce pobytu:
    Warszawa
Odp: Przerwania - ZX Spectrum 48
« Odpowiedź #13 dnia: 2021.10.16, 10:25:54 »
Przyznam, że nie bardzo rozumiem. Jak można w sprzęcie "zrobić" zmianę sprzętową bez zmian sprzętowych?

KWF

  • *****
  • Wiadomości: 6823
  • Miejsce pobytu:
    trzecia planeta od Słońca
  • "I co ja robię tu, u-u, co Ty tutaj robisz ..."
    • Insta do lasownia
Odp: Przerwania - ZX Spectrum 48
« Odpowiedź #14 dnia: 2021.10.16, 17:00:49 »
Czary Panie, czary!
KWF
-----
R Tape loading error 0:1
Moje zabawki: https://github.com/McKlaud76