kategoria: Asembler
[#1] Zmiana napisu na belce WB
Czy zna ktoś sposób, jak w asemblerze zmienić napis na belce tytułowej Workbencha? Chodzi o to, aby dowolny napis był ciągle widoczny na belce tak, jak robi to MCP. W dokumentacji MCP jest napisane: "MCP tries to identify the old WBTitleBar by searching for 'Amiga' at the beginning of the ScreenTitle. If this fails the function has no effect." Wynika z tego, że program szuka w pamięci starego napisu tytułowego i zmienia go. Pytanie, gdzie jest w pamięci struktura ekranu WB?
[#2] Re: Zmiana napisu na belce WB

@RomanWorkshop, post #1

W systemie jest funkcja GetDefaultPubScreen ;)

tygrysekHD
[#3] Re: Zmiana napisu na belce WB

@RomanWorkshop, post #1

Nie mam gotowego przykładu w asm, mogę jedynie wpuścić trochę światła w tym temacie, moja wiedza w tym temacie nie jest pełna.

Nie wiem jak to dokładnie robi MCP, ale widziałem źródła do WBTitle14. I tam to jest robione w ten sposób że jest podmieniana funkcja SetWindowTitles (intuition -276). Funkcję podmieniamy za pomocą SetFunction (exec -420). Która to zmienia wektor w tabeli skoków biblioteki i od teraz każdy, kto użyje SetWindowTitles to będzię korzystał z naszej nowej funkcji. I dopiero wtedy w tej funkcji sprawdzamy czy string jest typu "amiga" + "graphics mem" i jeśli się zgadza to możemy zmienić napis na własny, a jeśli się nie zgadza to wołamy starą wartość wektora dla SetWindowTitles (to musimy wcześniej zapamiętać) . W tymże programiku jest więcej technicznych rzeczy do zrozumienia. W przypadku gdy mamy inny język w wb to należy porównywać inne napisy i w WBTitle14 robione jest to za pomocą tooltipów, nie zagłębiałem się w ten temat jednakże.

Druga "twardsza" metoda to hakowanie kicka (o ile przeniesiemy go do ramu). Trzeba by odnaleźć napis "Amiga" i gdzieś niedaleko "graphics mem" i znaleźć referencję do napisu i tam zrobić podmiankę, na pewno wcześniej będą wołania execowskich funkcji AvailMem. Nie jest to łatwe ale możliwe. Z tego co ja wiem to co 5 sekund odpalany jest timer request i jest robiona aktualizacja napisu na belce WB. Czyli co 5 sekund system sprawdza dostępną pamięć i wyświetlą informację za pomocą SetWindowTitles.

Oczywiście na początku myślałem, że wystarczy zrobić locka na wb (LockPubScreen(0)) i zmienić sobie napis na belce zmieniając referencje do sc_Title (offset 22 względem struktury Screen, do której otrzymujesz wskaźnik po założeniu kłódki na wb i o dziwo przez chwilę nawet widziałem efekt, ale zaraz się pojawił znajomy stary napis :). Zatem jednorazowa zmiana referencji do sc_Title nie działa, więc system musi inaczej to robić i tak też się dzieje, bo przecież trzeba sprawdzać od czasu do czasu, czy pamięci ubyło czy przybyło.

Jeśli coś jeszcze nie zrozumiałe, to proszę o info.
[#4] Re: Zmiana napisu na belce WB

@asman, post #3

Dzięki za informacje, będę próbował coś zdziałać w tym temacie. Chce napisać programik, który będzie wyświetlał informacje o Amidze podobnie, jak robi to MCP tyle że za pomocą moich procedur sprawdzających sprzęt.
[#5] Re: Zmiana napisu na belce WB

@asman, post #3

No i udało mi się napisać programik, który zmienia nazwę na belce (prawie) każdego, aktywnego ekranu na dowolny tekst. Nie zmieniają się tylko nazwy na belkach ekranowych programów, które nie korzystają z systemowej funkcji SetWindowTitles z biblioteki Intuition (np. FileMaster, DeluxePaint 3, czy SuperEdC).

move.l 4.w,A6 ;adres bazowy biblioteki Exec

moveq #0,D0

lea INT(pc),A1 ;nazwa biblioteki Intuition

jsr -552(A6) ;otwiera bibliotekę Intuition (funkcja Exec:OpenLibrary)

move.l D0,A1 ;adres bazowy biblioteki Intuition

jsr -414(A6) ;zamyka bibliotekę Intuition (funkcja Exec:CloseLibrary)

lea OKI(pc),A0

move.l A0,BUT

move.l #-276,A0 ;numer funkcji do zamiany (Intuition:SetWindowTitles)

lea PRO(pc),A2

move.l A2,D0 ;adres nowej funkcji

move.l A2,BUF

jsr -420(A6) ;zamienia starą funkcję na nową (funkcja Exec:SetFunction)

move.l D0,BUF ;adres starej funkcji
LOP: bra.s LOP
PRO:

move.l BUT,A2 ;adres tekstu do wyświetlenia na belce aktywnego ekranu

dc.w $4EF9 ;skok pod adres starej funkcji (Intuition:SetWindowTitles)

BUF:

dc.l 0
INT:

dc.b "intuition.library",0

OKI:

dc.b "New name of every active screen",0

BUT:

dc.l 0

Wystarczy dodać sprawdzanie obecności w nowej nazwie belki wyrazów "graphics mem" i "other mem", żeby zmieniać nazwę tylko na belce Workbencha. Poza tym taki program jest wykonywany bez końca (pętla). Myślę nad zarezerwowaniem pamięci CHIP i umieszczeniu w niej mojej, podmienionej funkcji zmiany nazwy. Wtedy mógłbym zamknąć program, a podmieniona funkcja dalej by działała, aż do wyłączenia Amigi. Nie wiem, czy dobrze kombinuję?
[#6] Re: Zmiana napisu na belce WB

@RomanWorkshop, post #5

Zauważyłem kilka potencjalnych problemów w Twoim programie:
- Używasz "busy loop". Należy użyć systemowej funkcji Wait() z biblioteki exec i przykładowo czekać na kombinację CTRL-C!

- Adres zwrócony przez SetFunction() jest aktualny tylko przy wywołaniu funkcji! Nie można w ten sposób się do niego odwołać.

- Biblioteka intuition powinna być stale otwarta.

- Funkcja CloseLibrary() może zaśmiecić A1, nie ma gwarancji.

Ogólnie z SetFunction() trzeba ostrożnie.

Ostatnia aktualizacja: 18.02.2015 19:31:37 przez Hexmage960
[#7] Re: Zmiana napisu na belce WB

@Hexmage960, post #6

- Program musi ciągle działać. Co mi da użycie funkcji Wait() i sprawdzanie sygnałów?

- Jak się mam do niego odwoływać? Adres funkcji Intuition:SetWindowTitles jest stały po uruchomieniu WB, chyba że inny program go zmienia.

- Nie ma potrzeby, aby biblioteka Intuition pozostawała otwarta. Zamykam ją po uzyskaniu jej adresu bazowego, który również jest stały. Bibliotekę zamykam, bo w zamyśle program będzie się wyłączał, pozostawiając jedynie w pamięci podmienioną funkcję SetWindowTitles.

- Tak wiem o tym, przetestuje to na różnych Kickstartach. Dokumentacja nic o tym nie mówi więc, jeśli rejestr A1 raz pozostaje niezmieniony, to zakładam że będzie tak zawsze na danym Kickstarcie.
[#8] Re: Zmiana napisu na belce WB

@RomanWorkshop, post #7

- Program musi ciągle działać. Co mi da użycie funkcji Wait() i sprawdzanie sygnałów?

Pętla typu "busy loop" jest błędem, bo Twój task zajmuje zbytecznie czas procesora!


- Jak się mam do niego odwoływać? Adres funkcji Intuition:SetWindowTitles jest stały po uruchomieniu WB, chyba że inny program go zmienia.

- Nie ma potrzeby, aby biblioteka Intuition pozostawała otwarta. Zamykam ją po uzyskaniu jej adresu bazowego, który również jest stały. Bibliotekę zamykam, bo w zamyśle program będzie się wyłączał, pozostawiając jedynie w pamięci podmienioną funkcję SetWindowTitles.

Przepraszam, pomyliłem się co do kwestii wywoływania oryginalnej funkcji SetWindowTitles() w Twoim kodzie.

Jeśli jednak chodzi o pozostawienie biblioteki w pamięci - wydaje mi się, że tak będzie bardziej elegancko. Jeśli biblioteka jest zamykana może zniknąć przecież z pamięci (jeśli jest zamykana po raz ostatni)!

- Tak wiem o tym, przetestuje to na różnych Kickstartach. Dokumentacja nic o tym nie mówi więc, jeśli rejestr A1 raz pozostaje niezmieniony, to zakładam że będzie tak zawsze na danym Kickstarcie.

Dokumentacja mówi w tej sprawie: rejestry D0/D1/A0/A1 mogą być zaśmiecone.
[#9] Re: Zmiana napisu na belce WB

@Hexmage960, post #8

Czyli mam wyzerować rejestr D0, wywołać funkcję Exec:Wait i wtedy program będzie zajmował mniej czasu procesora?

Bibliotekę Intuition faktycznie należy zostawić otwartą, aż do wyłączenia programu.

Którą dokumentację masz na myśli?
[#10] Re: Zmiana napisu na belce WB

@RomanWorkshop, post #9

Czyli mam wyzerować rejestr D0, wywołać funkcję Exec:Wait i wtedy program będzie zajmował mniej czasu procesora?

Nie zero, ale ustawiony bit 12 (CTRL-C). Dzięki temu po wysłaniu do Twojego procesu kombinacji CTRL-C program zostanie wyłączony. Myślę, że program będzie też bardziej przyjazny dla użytkownika.

Konstrukcji pętli, której użyłeś nie można używać w programie w środowisku wielozadaniowym. Wait() lub WaitTOF() lub Delay() musi się znaleźć w takiej pętli czekającej.

Którą dokumentację masz na myśli?

Dokumentację ROM Kernel Reference Manual.

Ostatnia aktualizacja: 18.02.2015 21:34:36 przez Hexmage960
[#11] Re: Zmiana napisu na belce WB

@RomanWorkshop, post #9

I jeszcze jedna kwestia: ja bym nie tworzył samo-modyfikującego się kodu, ale zrobił warunek w funkcji podmieniającej. Tak będzie o wiele bezpieczniej.
[#12] Re: Zmiana napisu na belce WB

@Hexmage960, post #10

Ale, jeśli program ma działać w nieskończoność, czyli żadne sygnały nie mogą go przerywać, to czy użycie funkcji Wait(0) spowoduje zmniejszenie obciążenia procesora tym programem?

No tak, w RKRM z 1987 roku mam to napisane.

Nie bardzo rozumiem, jaki warunek i gdzie?

Ostatnia aktualizacja: 18.02.2015 21:51:33 przez RomanWorkshop
[#13] Re: Zmiana napisu na belce WB

@RomanWorkshop, post #12

Ale, jeśli program ma działać w nieskończoność, czyli żadne sygnały nie mogą go przerywać, to czy użycie funkcji Wait(0) spowoduje zmniejszenie obciążenia procesora tym programem?

Szczerze mówiąc to program powinien być przyjazny dla użytkownika i dać się zatrzymać. Takie jest moje zdanie.

Nie bardzo rozumiem, jaki warunek i gdzie?

Wewnątrz kodu funkcji, która podmienia działanie SetWindowTitles(). Adres zwrócony przez SetFunction() zapisz gdzieś w bloku danych swojego programu (a nie bezpośrednio jako parametr JMP). Zaś do kodu funkcji dopisz sprawdzanie, czy adres ów został zapisany (np. czy jest różny od zero).

; Program główny:
...
jsr _LVOSetFunction(a6)
move.l d0, funkcja
...

; Zamiennik funkcji:
nowa_funkcja:
move.l funkcja,d0
beq .zero
movea.l d0,a0
jmp (a0)
.zero:
rts

funkcja: dc.l 0


Oczywiście zakładamy, że w D0 i A0 nie ma parametrów funkcji. Jednak jeśli są należy użyć innych rejestrów oraz zapamiętywania na stosie.

Ostatnia aktualizacja: 18.02.2015 22:09:03 przez Hexmage960
[#14] Re: Zmiana napisu na belce WB

@Hexmage960, post #13

Tak, to jest tylko przykład. Finalny program zmieniający napis na belce WB, będzie działał na zasadzie zainstalowania w pamięci łatki na funkcję Intuition:SetWindowTitles. Sam program wyłączy się i nie będzie zajmował czasu procesora.

Można i tak, ale jeśli jakiś program wywoła moją funkcję z takim warunkiem w czasie, gdy bufor z adresem będzie pusty, to w efekcie zmiana nazwy na belce nigdy nie nastąpi (RTS). W moim rozwiązaniu nastąpi tuż po zapisaniu adresu w buforze (do tego czasu będą wykonywane skoki na początek mojej funkcji). Jednak są to skrajne przypadki.

Jeszcze interesuje mnie, jak sprawdzić że mój program został już uruchomiony i przykładowo, zainstalował odpowiednie procedury w pamięci? Chodzi o to, żeby nie zajmować niepotrzebnie pamięci przy kolejnym uruchomieniu programu.


Ostatnia aktualizacja: 18.02.2015 22:22:57 przez RomanWorkshop
[#15] Re: Zmiana napisu na belce WB

@RomanWorkshop, post #14

Można i tak, ale jeśli jakiś program wywoła moją funkcję z takim warunkiem w czasie, gdy bufor z adresem będzie pusty, to w efekcie zmiana nazwy na belce nigdy nie nastąpi (RTS). W moim rozwiązaniu nastąpi tuż po zapisaniu adresu w buforze (do tego czasu będą wykonywane skoki na początek mojej funkcji). Jednak są to skrajne przypadki.

Rozumiem, ale moje rozwiązanie jest bezpieczniejsze - cache procesora i te rzeczy.

Jeszcze interesuje mnie, jak sprawdzić że mój program został już uruchomiony i przykładowo, zainstalował odpowiednie procedury w pamięci? Chodzi o to, żeby nie zajmować niepotrzebnie pamięci.

FindTask() chyba załatwi sprawę.
[#16] Re: Zmiana napisu na belce WB

@Hexmage960, post #15

W sumie przed podmianą funkcji można wyłączyć multitasking funkcją Forbid(), a zaraz po podmianie i zapisaniu adresu starej funkcji do bufora można go włączyć funkcją Permit(). Wtedy będzie pewność, że żaden program nie wywoła mojej funkcji w momencie, gdy bufor jest pusty lub ma nieprawidłowy adres. Wtedy też cache procesora nie spowoduje wykonania skoku pod niewłaściwy adres, mimo użycia samo modyfikującego się kodu.

Funkcja FindTask() znajduje tylko aktualnie działający program, o określonej nazwie. A co jeśli zmieni się nazwę pliku tego programu? Poza tym mój program po zainstalowaniu nowej funkcji w pamięci, wyłączy się. Będę więc sprawdzał wartości początkowych bajtów w funkcji SetWindowTitles, do której adres skoku znajduje się w odpowiednim wektorze systemowym, czyli -276(Intuition_base). Będę znał wartości tych bajtów dla mojej funkcji więc łatwo rozpoznam, czy mój program ją zainstalował, czy też jest to oryginalna funkcja systemowa (lub innego programu).
[#17] Re: Zmiana napisu na belce WB

@RomanWorkshop, post #16

Dodałem do tego czyszczenie pamięci cache procesora tak, jak to robi program WBTitle i wyszedł taki prosty kodzik:

move.l 4.w,A6 ;adres bazowy biblioteki Exec
moveq #0,D0
lea INT(pc),A1 ;nazwa biblioteki Intuition
jsr -552(A6) ;otwiera bibliotekę Intuition (funkcja Exec:OpenLibrary)
move.l D0,D7
move.l D0,A1 ;adres bazowy biblioteki Intuition
lea OKI(pc),A0
move.l A0,BUT
move.l #-276,A0 ;numer funkcji do zamiany (Intuition:SetWindowTitles)
lea PRO(pc),A2
move.l A2,D0 ;adres nowej funkcji
jsr -132(A6) ;wyłącza multitasking (funkcja Exec:Forbid)
jsr -420(A6) ;zamienia starą funkcję na nową (funkcja Exec:SetFunction)
move.l D0,BUF ;adres starej funkcji
jsr -636(A6) ;czyści pamięć cache procesora (funkcja Exec:CacheClearU)
jsr -138(A6) ;włącza multitasking (funkcja Exec:Permit)
move.l D7,A1
jsr -414(A6) ;zamyka bibliotekę Intuition (funkcja Exec:CloseLibrary)

LOP: bra.s LOP

PRO:
move.l BUT,A2 ;adres tekstu do wyświetlenia na belce aktywnego ekranu
dc.w $4EF9
BUF: dc.l 0 ;skok pod adres starej funkcji (Intuition:SetWindowTitles)

INT: dc.b "intuition.library",0
OKI: dc.b "New name of every active screen",0
BUT: dc.l 0


Ostatnia aktualizacja: 19.02.2015 17:45:49 przez RomanWorkshop
[#18] Re: Zmiana napisu na belce WB

@RomanWorkshop, post #17

Jest mały problem. Po uruchomieniu tego programu na belce WB wyświetla się mój napis, ale po otwarciu okna dowolnego napędu lub katalogu, na chwilę pojawia się stary napis "Amiga Workbench _ graphics mem _ other mem" (w MCP tak się nie dzieje). Jak to zmienić?
Na stronie www.PPA.pl, podobnie jak na wielu innych stronach internetowych, wykorzystywane są tzw. cookies (ciasteczka). Służą ona m.in. do tego, aby zalogować się na swoje konto, czy brać udział w ankietach. Ze względu na nowe regulacje prawne jesteśmy zobowiązani do poinformowania Cię o tym w wyraźniejszy niż dotychczas sposób. Dalsze korzystanie z naszej strony bez zmiany ustawień przeglądarki internetowej będzie oznaczać, że zgadzasz się na ich wykorzystywanie.
OK, rozumiem