Asembler procesora 68000 Działa w systemie Workbench     BasicDiag 1.07           Kompilacja


Program sprawdza i wyświetla podstawowe informacje o konfiguracji sprzętowej Amigi, podczas
jej uruchamiania z dyskietki (lub obrazu ADF w emulatorze stacji dyskietek). Został napisany
w asemblerze i skompilowany za pomocą "ASM-One 1.44".

Do prawidłowego działania wymaga Kickstartu 1.1 (31.34) lub nowszego, ponieważ używa bitu
nr 0 (AFB_68010) z flag AttnFlags biblioteki Exec do ustalenia, czy zainstalowany procesor to
68000 lub 68010+. Na starszych Kickstartach 0.7/1.0 program zadziała tylko, gdy rejestr VBR=0
dla procesorów 68010+, ale każdy procesor zostanie wykryty jako "68000", a FPU w procesorze
68060 nie zostanie wykryty (napis "NONE"), jeśli jest programowo wyłączony (bit DFP=1 w reje-
strze PCR). Wynika to z tego, że te Kickstarty nie rozpoznają procesorów innych niż 68000
(bit AFB_68010 ma zawsze wartość 0).

Używa podstawowych funkcji systemowych z bibliotek Exec/DOS/Intuition oraz opracowanych
przeze mnie nisko-poziomowych procedur. Wykrywają one poszczególne komponenty przez:
programową obsługę wyjątków procesora (CPU/FPU), odczyt wartości identyfikacyjnej z rejestru
VPOSR (GFX), odczyt wersji/rewizji z pamięci Kickstart (ROM) oraz odczyt wartości zwracanych
przez funkcję systemową (CHIP/FAST). Wyświetlane o Amidze informacje obejmują:

CPU - model procesora z rodziny 680x0: "68000", "68010", "68020" (68EC020), "68030" (68EC030), "68040"
(68EC040/68LC040), "68060" (68EC060/68LC060). W przypadku procesora 68060 zostanie też podana jego
wersja: "68060" - pełna (zawiera FPU i MMU) lub "XX060" - EC (bez FPU i MMU)/LC (bez FPU) oraz rewizja
"(rev X)". Dodatkowe informacje o procesorze 68060 pochodzą z jego rejestru PCR.

FPU - model koprocesora matematycznego z rodziny 6888x: zewnętrzny "68881"/"68882" lub wewnętrzny,
wbudowany w procesor 68040 - "IN040"/68060 - "IN060". FPU w procesorze 68060 zostanie wykryty, nawet
jeśli jest programowo wyłączony (bit DFP=1 w rejestrze PCR). W przypadku braku koprocesora matematy-
cznego zostanie wyświetlony napis "NONE".

GFX - model układu graficznego: "OCS"/"ECS"/"AGA" oraz standard jego pracy: "(PAL)"/"(NTSC)".
Informacje o układzie graficznym Denise/Lisa pochodzą z rejestru VPOSR układu Agnus/Alice.

ROM - wersja Kickstartu od "1.2 (33.166)" do "3.1 (40.72)", ustalana na podstawie zapisanej w nim wersji
($Fx000C, 16-bit version) i rewizji ($Fx000E, 16-bit revision). Najstarsze Kickstarty 0.7/1.0/1.1 zostaną
rozpoznane jako "1.x ()", natomiast nowsze (43+) jako "3.x (vv.rr)" z wersją i rewizją podaną w nawiasie.
Kickstart 1.2.1 (34.4) zostanie rozpoznany jako "1.3 (34.4)", a Kickstart 3.5 (40.71) jako "3.1 (40.71)".
Wyświetlona wersja Kickstartu może nie być tą, która jest aktualnie używana przez system Amigi.
Zwłaszcza, jeśli Kickstart został załadowany (relokowany/remapowany) do pamięci RAM przez program
(np. ReKick, SKick), funkcję maprom/fastrom karty turbo lub jednostkę zarządzania pamięcią (MMU).

CHIP / FAST - ilość dostępnej wolnej pamięci RAM wyrażona w "kB" (maksymalnie 4194303 kB),
podana oddzielnie dla pamięci CHIP współdzielonej z chipsetem (m.in. układ graficzny) oraz dla
pamięci FAST (lub SLOW), do której procesor ma bezpośredni i dzięki temu szybszy dostęp.


Program uruchamia się z bootbloku dyskietki (pierwsze 1024-bajty) i powinien działać na każdej
Amidze. Kompilację najlepiej przeprowadzić przy użyciu kompilatora "ASM-One 1.44", który od razu
umożliwi zapisanie programu w bootbloku dyskietki, wraz z prawidłową sumą kontrolną (checksum).
W tym celu uruchamiamy "ASM-One" i wpisujemy "c"+enter, aby wybrać pamięć typu CHIP, w której
zostanie zarezerwowany bufor roboczy dla kompilatora. Następnie podajemy rozmiar tego bufora
w [kB], wpisując np. "100"+enter. Wpisujemy "r"+enter i w oknie wyboru, wskazujemy plik z kodem
źródłowym programu "BasicDiag.s". Po załadowaniu kodu źródłowego wpisujemy "a"+enter, aby
rozpocząć kompilację, która powinna zakończyć się bez żadnych błędów (komunikat "No Errors").
Teraz wkładamy dyskietkę, na której chcemy zapisać program i wpisujemy kolejno: "ws"+enter,
"Boot"+enter, "0"+enter, "2"+enter. Na koniec wpisujemy "cc"+enter, co spowoduje obliczenie
i zapisanie na dyskietce sumy kontrolnej jej bootbloku.

Po uruchomieniu programu z dyskietki pojawi się czarny ekran otoczony migającą ramką, wewnątrz
krórej zostaną wyświetlone informacje diagnostyczne. W zależności od wersji Kickstartu kolor tekstu
i ramki może być czerwony, pomarańczowy lub zielony. Aby zamknąć ekran programu i kontynuować
bootowanie z dyskietki (uruchomienie CLI startowego), należy nacisnąć lewy przycisk myszki. Naci-
śnięcie prawego przycisku myszki, spowoduje zresetowanie Amigi.

Program testowałem na mojej Amidze 500/600 oraz pod emulatorem "WinUAE" na Amigach,
o różnych konfiguracjach sprzętowych z prawie każdym obsługiwanym Kickstartem. Nie zauwa-
żyłem żadnych błędów/problemów w działaniu programu, ale w razie ich wystąpienia można
pisać na mój e-mail. Poniżej znajduje się kod źródłowy programu.

Boot:
 dc.l     $444F5300,0,880 ;napis "DOS" + bajt flag, suma kontrolna bootbloku, numer głównego bloku
                          ;dyskietki. Bajt flag zawiera parametry dyskietki (bity 76543210):
                          ; 0 - File System: 0=OFS (Old), 1=FFS (Fast)
                          ; 1 - International Mode: 0=OFF, 1=ON
                          ; 2 - Directory Cache & International Mode: 0=OFF, 1=ON
                          ;Pozostałe bity (3-7) mają wartość 0.

 movem.l  A2-A6/D2-D7,-(A7)
 jsr      -132(A6)     ;blokuje multitasking (funkcja Exec:Forbid)
 lea      Diag(pc),A5  ;adres procedury, która zostanie wykonana w trybie nadzorcy
 jsr      -30(A6)      ;włącza tryb nadzorcy i wykonuje procedurę (funkcja Exec:Supervisor)
 jsr      -138(A6)     ;odblokowuje multitasking (funkcja Exec:Permit)
 lea      INTn(pc),A1  ;nazwa biblioteki Intuition
 jsr      -408(A6)     ;otwiera bibliotekę Intuition (funkcja Exec:OldOpenLibrary)
 tst.l    D0
 beq.s    Error        ;nie otwarto biblioteki Intuition
 move.l   D0,A6        ;adres bazowy biblioteki Intuition
 lea      Text(pc),A0  ;adres tekstu do wyświetlenia
 moveq    #0,D0        ;kod błędu
 move.l   #201,D1      ;wysokość ramki komunikatu "Recoverable Alert"
 jsr      -90(A6)      ;wyświetlenie komunikatu (funkcja Intuition:DisplayAlert)
 move.l   A6,A1        ;adres bazowy biblioteki Intuition
 move.l   4.w,A6       ;adres bazowy biblioteki Exec
;Sprawdzanie, który przycisk myszki został naciśnięty
 tst.l    D0
 bne.s    Boot0
;Naciśnięto prawy przycisk myszki (reset)
 lea      Reset(pc),A5 ;adres procedury, która zostanie wykonana w trybie nadzorcy
 jsr      -30(A6)      ;włącza tryb nadzorcy i wykonuje procedurę (funkcja Exec:Supervisor)
Reset:
 move.l   #$1000000,A0 ;adres za obszarem Kickstartu
 sub.l    -20(A0),A0   ;adres początku Kickstartu 256/512kB ($FC0000/$F80000)
 move.l   4(A0),A0     ;początkowa wartość rejestru PC odczytana z Kickstartu
 subq.l   #2,A0        ;adres instrukcji RESET i reszty kodu startowego w Kickstarcie
 reset                 ;wykonanie pierwszej instrukcji RESET
 jmp      (A0)         ;skok do drugiej instrukcji RESET i reszty kodu startowego w Kickstarcie
;Naciśnięto lewy przycisk myszki (boot)
Boot0:
 jsr      -414(A6)     ;zamyka bibliotekę Intuition (funkcja Exec:CloseLibrary)
 lea      DOSn(pc),A1  ;nazwa biblioteki DOS
 jsr      -96(A6)      ;szuka modułu rezydentnego biblioteki DOS (funkcja Exec:FindResident)
 tst.l    D0
 beq.s    Error        ;nie znaleziono modułu rezydentnego biblioteki DOS
 move.l   D0,A0
 move.l   $16(A0),A0   ;adres kodu inicjalizującego bibliotekę DOS
 moveq    #0,D0        ;powrót z bootbloku i wykonanie kodu o adresie w rejestrze A0
Exit:
 movem.l  (A7)+,A2-A6/D2-D7
 rts
Error:
 moveq    #$FF,D0      ;powrót z bootbloku i wyświetlenie komunikatu "Recoverable Alert"
 bra.s    Exit

INTn:   dc.b     "intuition.library",0
DOSn:   dc.b     "dos.library",0


;##### Sprawdzanie modelu procesora (CPU)
Diag:                ;procedura wykonywana przez funkcję Exec:Supervisor
 move.l   A7,A3      ;zapamiętanie wskaźnika stosu (A7=SSP)
 moveq    #0,D5      ;znacznik obecności FPU w procesorze 68060 (brak)
 lea      Text0(pc),A4
 moveq    #$30,D1    ;procesor 68000
 moveq    #$2C,D3
 move.l   D3,A2
 btst     #0,297(A6) ;wartość bitu określa procesor: 0=68000, 1=68010 lub nowszy (bit ten wchodzi
                     ;w skład flag AttnFlags, wypełnianych przez bibliotekę Exec podczas startu Amigi).
 beq.s    Diag04     ;procesor 68000
;W tym miejscu procesor to 68010 lub nowszy
 dc.l     $4E7A3801  ;MOVEC VBR,D3 - instrukcja przenosi wartość rejestru VBR do rejestru D3.
                     ;Jest obsługiwana przez procesory 68010/20/30/40/60.
 moveq    #$10,D2
 move.l   D2,A1
 add.l    D3,A1
 move.l   (A1),D2    ;wektor wyjątku nr 4 (Illegal Instruction), który wystąpi
                     ;gdy procesor natrafi na kod nieobsługiwanej instrukcji.
 lea      Diag03(pc),A0
 move.l   A0,(A1)    ;zmiana wektora wyjątku nr 4
 add.l    D3,A2
 move.l   (A2),D3    ;wektor wyjątku nr 11 (Line 1111 Emulator), który wystąpi gdy procesor
                     ;natrafi na kod nieobsługiwanej instrukcji, rozpoczynający się słowem $Fnnn.
 lea      Diag02(pc),A0
 move.l   A0,(A2)    ;zmiana wektora wyjątku nr 11
 moveq    #$31,D1    ;procesor 68010
 dc.l     $4E7A1002  ;MOVEC CACR,D1 - instrukcja obsługiwana przez 68020/30/40/60
 moveq    #$32,D1    ;procesor 68020/68030
 dc.l     $4E7A1004  ;MOVEC ITT0,D1 - instrukcja obsługiwana przez 68040/60.
                     ;Przenosi wartość rejestru ITT0 (68040, 68LC040, 68060,
                     ;68EC060, 68LC060)/IACR0 (68EC040) do rejestru D1.
 moveq    #$34,D1    ;procesor 68040
 dc.l     $4E7A1808  ;MOVEC PCR,D1 - instrukcja obsługiwana przez 68060
 lea      Text7(pc),A0
 addq.l   #3,A4
 bsr.s    Write
 subq.l   #2,A4
 move.w   D1,D4
 ror.w    #8,D4
 add.b    #$30,D4
 move.b   D4,(A4)    ;numer rewizji procesora
 subq.l   #8,A4
 btst     #16,D1     ;wartość bitu określa wersję procesora: 0=68060, 1=68EC060/68LC060
 beq.s    Diag00     ;procesor 68060 w pełnej wersji
 subq.l   #3,A4      ;procesor 68060 w wersji LC (bez FPU)/EC (bez FPU i MMU)
 move.w   #"XX",(A4)+ ;68060 może zapisywać słowo pod nieparzysty adres
 addq.l   #1,A4
 bra.s    Diag01
Diag00:
 moveq    #$FF,D5    ;znacznik obecności FPU w procesorze 68060 (jest)
Diag01:
 moveq    #$36,D1    ;procesor 68060
Diag02:              ;kod obsługi wyjątku nr 11 (tylko dla 68020)
 move.l   D2,(A1)    ;przywrócenie wektora wyjątku nr 4
 move.l   A3,A7      ;przywrócenie wskaźnika stosu (A7=SSP)
 bra.s    Diag05


Diag03:              ;kod obsługi wyjątku nr 4
 cmp.b    #$32,D1
 bne.s    Diag02
;Rozpoznawanie procesora 68020/68030
 dc.w     $F02F,$6200,$FFFE ;PMOVE.W PSR,-2(A7) - instrukcja odkłada na stos (A7=SSP)
                            ;wartość rejestru MMUSR (68030)/ACUSR (68EC030).
                            ;Na procesorze 68020 powoduje wystąpienie wyjątku nr 11.
 moveq    #$33,D1    ;procesor 68030
 bra.s    Diag02


;##### Sprawdzanie modelu koprocesora matematycznego (FPU)
Diag04:
 move.l   (A2),D3    ;wektor wyjątku nr 11 (Line 1111 Emulator), który wystąpi gdy procesor
                     ;natrafi na kod nieobsługiwanej instrukcji, rozpoczynający się słowem $Fnnn
                     ;(prawidłowy tylko dla 68000).
Diag05:
 move.b   D1,(A4)    ;wartość określa model procesora: $30-$36=68000-68060
 lea      Diag07(pc),A0
 move.l   A0,(A2)    ;zmiana wektora wyjątku nr 11
;Sprawdzenie obecności FPU w procesorze 68060
 tst.l    D5         ;znacznik obecności FPU w procesorze 68060
 bne.s    Diag06     ;FPU jest w procesorze 68060 (może być wyłączony)
 moveq    #0,D1      ;brak koprocesora
 dc.l     $F201583A  ;FTST.B D1 - instrukcja testuje najmłodszy bajt w rejestrze D1 procesora
                     ;(zapobiega wygenerowaniu ramki NULL przez instrukcję FSAVE).
                     ;Jeśli nie ma zainstalowanego FPU, powoduje wystąpienie wyjątku nr 11.
 dc.w     $F327      ;FSAVE -(A7) - instrukcja odkłada na stos (A7=SSP) ramkę ze stanem FPU
 move.l   A3,D2
 sub.l    A7,D2      ;rozmiar ramki odłożonej przez instrukcję FSAVE
 moveq    #5,D1      ;koprocesor 68881
 cmp.b    #$1C,D2    ;ramka IDLE
 beq.s    Diag07
 moveq    #11,D1     ;koprocesor 68882
 cmp.b    #$3C,D2    ;ramka IDLE
 beq.s    Diag07
 moveq    #17,D1     ;koprocesor wbudowany w 68040
 cmp.b    #4,D2      ;ramka IDLE
 beq.s    Diag07
 bra.s    Diag06


Write:  move.b   (A0)+,(A4)+
        tst.b    (A0)
        bne.s    Write
        rts


Diag06:
 moveq    #23,D1     ;koprocesor wbudowany w 68060
Diag07:              ;kod obsługi wyjątku nr 11 (tylko jeśli nie ma FPU)
 move.l   D3,(A2)    ;przywrócenie wektora wyjątku nr 11
 move.l   A3,A7      ;przywrócenie wskaźnika stosu (A7=SSP)
 lea      Text8(pc),A0
 lea      Text1(pc),A4
 add.l    D1,A0      ;wartość określa model FPU: 0=brak, 5=68881, 11=68882, 17=68040, 23=68060
 bsr.s    Write


;##### Sprawdzanie modelu układu graficznego (GFX)
 moveq    #0,D1
 move.w   $DFF004,D1 ;odczyt rejestru VPOSR z układu Agnus/Alice
 lsr.w	  #8,D1
 bclr     #7,D1      ;wyodrębnienie wartości identyfikacyjnej
 lea      TextA(pc),A0
 lea      Text3(pc),A4
 btst     #4,D1      ;wartość bitu określa standard układu: 0=PAL, 1=NTSC
 beq.s    Diag08     ;standard PAL
 addq.l   #5,A0
 sub.b    #$10,D1
Diag08:
 bsr.s    Write
 lea      Text9(pc),A0
 lea      Text2(pc),A4
 tst.b    D1
 beq.s    Diag09     ;układ OCS
 sub.b    #$20,D1
 lsr.b    #1,D1
 rol.b    #2,D1
 add.l    D1,A0      ;wartość określa model układu: 0=ECS, 4=AGA
 addq.l   #4,A0
Diag09:
 bsr.s    Write


;##### Sprawdzanie wersji Kickstartu (ROM)
 move.l   #$1000000,A0 ;adres za obszarem Kickstartu
 sub.l    -20(A0),A0 ;adres początku Kickstartu 256/512kB ($FC0000/$F80000)
 move.w   12(A0),D2  ;wersja Kickstartu
 move.w   14(A0),D3  ;rewizja Kickstartu
 cmp.w    #$FFFF,D2
 beq.s    Diag13     ;Kickstart 1.x (0.7/1.0/1.1)
 lea      Text4(pc),A4
 moveq    #$21,D1
 cmp.w    D1,D2
 beq.s    Diag11     ;Kickstart 1.2
 moveq    #$31,D1
 cmp.w    #$22,D2
 beq.s    Diag11     ;Kickstart 1.3 (1.2.1)
 moveq    #$02,D1
 cmp.w    #$24,D2
 bne.s    Diag10
 cmp.w    #$10,D3
 bhi.s    Diag11     ;Kickstart 2.0
 moveq    #$41,D1
 bra.s    Diag11     ;Kickstart 1.4
Diag10:
 cmp.w    #$25,D2
 beq.s    Diag11     ;Kickstart 2.0
 moveq    #$03,D1
 cmp.w    #$27,D2
 beq.s    Diag11     ;Kickstart 3.0
 moveq    #$13,D1
 cmp.w    #$28,D2
 beq.s    Diag11     ;Kickstart 3.1 (3.5)
 addq.b   #2,(A4)
 addq.l   #5,A4
 bra.s    Diag12     ;Kickstart 3.x
Diag11:
 lsl.w    #4,D1
 ror.b    #4,D1
 add.w    #$3030,D1
 move.b   D1,(A4)
 ror.w    #8,D1
 addq.l   #2,A4
 move.b   D1,(A4)
 addq.l   #3,A4
Diag12:
 bsr.s    ConWD
 move.b   #".",(A4)+
 move.w   D3,D2
 bsr.s    ConWD
 move.b   #")",(A4)
Diag13:


;##### Sprawdzanie dostępnej wolnej pamięci RAM (CHIP, FAST)
 moveq    #2,D1      ;pamięć CHIP
 jsr      -216(A6)   ;ustala liczbę bajtów wolnej pamięci (funkcja Exec:AvailMem)
 lea      Text5(pc),A4
 bsr.s    Con24D
 moveq    #4,D1      ;pamięć FAST
 jsr      -216(A6)   ;ustala liczbę bajtów wolnej pamięci (funkcja Exec:AvailMem)
 lea      Text6(pc),A4
 bsr.s    Con24D
 rte                 ;powrót z funkcji Exec:Supervisor


;Konwersja 2-bajtów z rejestru D2 do systemu DEC-ASCII (nieznaczące zera są pomijane)
ConWD:  moveq    #$30,D1
        move.l   #$2710,D4
ConWD0: move.b   #$2F,(A4)
ConWD1: addq.b   #1,(A4)
        sub.w    D4,D2
        bcc.s    ConWD1
        add.w    D4,D2
        cmp.b    (A4),D1
        beq.s    ConWD2
        moveq    #0,D1
        addq.l   #1,A4
ConWD2: divu     #$0A,D4
        bne.s    ConWD0
        cmp.b    #$20,(A4)
        beq.s    ConWD3
        addq.l   #1,A4
ConWD3: rts


;Konwersja 24-bitów (maks. $98967F) z rejestru D0 do systemu DEC-ASCII (nieznaczące zera są pomijane)
Con24D:  lsr.l    #8,D0
         lsr.l    #2,D0   ;dzielenie liczby bajtów pamięci przez 1024 (wynik w kB)
         moveq    #$30,D1
         move.l   #$0F4240,D2
         move.l   #$0927C0,D3
Con24D0: move.b   #$2F,(A4)
Con24D1: addq.b   #1,(A4)
         sub.l    D2,D0
         bcc.s    Con24D1
         add.l    D2,D0
         cmp.b    (A4),D1
         beq.s    Con24D2
         moveq    #0,D1
         addq.l   #1,A4
Con24D2: sub.l    D3,D2
         divu     #$0A,D3
         lsr.l    #2,D2
         tst.b    D2
         bne.s    Con24D0
;Generowanie napisu "kB"
         cmp.b    #$20,(A4)+
         beq.s    Con24D3
         addq.l   #1,A4
Con24D3: move.b   #"k",(A4)+
         move.b   #"B",(A4)
         rts


Text:  dc.b   0,20,20,"BasicDiag 1.07 (14.06.2025) by RomanWorkshop",0,1,0,20,30,0,1,0,20,40,"CPU: 680"
Text0: dc.b   "x0        ",0,1,0,20,50,"FPU: "
Text1: dc.b   "xxxx ",0,1,0,20,60,"GFX: "
Text2: dc.b   "xxx ("
Text3: dc.b   "xxxx ",0,1,0,20,70,"ROM: "
Text4: dc.b   "1.x ()           ",0,1,0,20,90,"CHIP: "
Text5: dc.b   "x         ",0,1,0,20,100,"FAST: "
Text6: dc.b   "x         ",0,1,0,20,150,"LMB - boot, RMB - reset",0,0
Text7: dc.b   "(rev x)",0
Text8: dc.b   "NONE",0,"68881",0,"68882",0,"IN040",0,"IN060",0
Text9: dc.b   "OCS",0,"ECS",0,"AGA",0
TextA: dc.b   "PAL)",0,"NTSC)",0

 END

;Konwersja 4-bajtów z rejestru D0 do systemu DEC-ASCII (nieznaczące zera są pomijane)
ConLD:  lsr.l    #8,D0
        lsr.l    #2,D0   ;dzielenie liczby bajtów pamięci przez 1024 (wynik w kB)
        moveq    #$30,D1
        lea      ConLD4(pc),A1
ConLD0: move.b   #$2F,(A4)
ConLD1: addq.b   #1,(A4)
        sub.l    (A1),D0
        bcc.s    ConLD1
        add.l    (A1)+,D0
        cmp.b    (A4),D1
        beq.s    ConLD2
        moveq    #0,D1
        addq.l   #1,A4
ConLD2: tst.b    (A1)
        bpl.s    ConLD0
;Generowanie napisu "kB"
        cmp.b    #$20,(A4)+
        beq.s    ConLD3
        addq.l   #1,A4
ConLD3: move.b   #"k",(A4)+
        move.b   #"B",(A4)
        rts
ConLD4: dc.l     1000000000,100000000,10000000,1000000,100000,10000,1000,100,10,1
        dc.b     $80

;Rozmiar: 964 B, linii kodu: 251