
                         ****************************
                         *   ROMWack Patcher v2.0   *
                         *  Napisaî Grzegorz Królik *
                         ****************************

     incdir  "devpac_asm_3.02ß:include/"
     include "exec/exec_lib.i"
     include "libraries/dos_lib.i"
     include "libraries/dosextens.i"
     include "intuition/intuition_lib.i"
     include "intuition/intuition.i"
     include "workbench/icon_lib.i"
     include "workbench/startup.i"
     include "workbench/workbench.i"

call macro
     jsr     _LVO\1(a6)
     endm


     section main_program,code

start:
     movem.l d0-d3/a0-a2/a6,-(sp) ;Zrzucamy kolejne rejestry na stos
     move.l  a0,cli_args          ;Argumenty pobrane z CLI zapisujemy
                                  ;w cli_args
     bsr.w   find_task            ;Odnajdujemy nasz task i sprawdzamy
     tst.l   message              ;czy jesteômy na workbenchu czy CLI?
     beq.s   from_cli             ;Brak komunikatu z MsgPortu oznacza
                                  ;ûe jesteômy na CLI
     bsr.w   open_libraries       ;Czas otworzyê niezbëdne biblioteki
     beq.s   exit                 ;Wyjôcie jeôli któraô z nich nie moûe
                                  ;byê otwarta
     bsr.w   find_tool_type       ;Jesteômy na workbenchu, wiëc moûe
                                  ;by tak sprawdziê czy nie ma dla nas
                                  ;jakiô ToolTypes'ów
     beq.s   exit                 ;Jak to uruchomiony z workbencha i brak
                                  ;ikony?
from_cli:
     tst.l   int_base             ;Czy biblioteki Intuition i Dos byîy
                                  ;otwierane?
     bne.s   go_on                ;Fajnie, idúmy dalej
     bsr.w   open_libraries       ;Nie?, to trzeba je otworzyê
     beq.s   exit                 ;O kurcze!!!, znów bîâd w ROM'ie, brak
                                  ;którejô z bibliotek
go_on:
     bsr.w   open_window          ;A moûe by tak jakieô okienko otworzyê,
                                  ;ûeby czasem jakiô cymbaî nie pomyôlaî,
                                  ;ûe program nie zostaî uruchomiony
     beq.s   exit                 ;No i masz!!!, chyba brak pamiëci?
     tst.l   message              ;Czy argumenty sâ pobrane z Ikony czy CLI?
     bne.s   set_language         ;Z ikony
     bsr.w   read_args            ;Z CLI

set_language:
     bsr.w   set_right_language   ;Ustawiamy wybrany przez uûytkownika
                                  ;jëzyk, gdy language_flag=1 to jest to
                                  ;jëzyk polski, a gdy zero to angielski
     bsr.w   install_patch        ;instalujemy nowâ funkcjë Debug()
     beq.s   exit                 ;Ach tak!!!, program juû uruchomiony!
     bsr.w   print_message        ;W CLI wypisujemy krótkâ wiadomoôê o
                                  ;mnie (autorze programu), oraz programie
wait_yet:
     bsr.w   wait_for_close       ;Czekamy aû nasz kochany uûytkownik
                                  ;zamknie okienko, to znaczy zmusi
                                  ;program do 'wyjôcia z siebie'
     tst.b   req_active           ;Nie moûna pozwoliê na to by uûytkownik
                                  ;zamknâî okienko podczas gdy aktywny jest
                                  ;requester, a wiec req_active=1 - requester
                                  ;jest aktywny, gdy req_active=0 - jest
                                  ;zamkniëty

     ;Gdy uûytkownik opuôci program wtedy wszystko powróci do poprzedniego
     ;stanu, to znaczy, ûe nasza funkcja zostanie usuniëta i pamiëc przez
     ;niâ zajmowana zostanie zwolniona. Wiec co by sië staîo gdyby w czasie
     ;gdy requester jest aktywny uûytkownik wyszedî z programu?
     ;Odpowiedú jest prosta: WIELKIE GURU !!!

     bne.s   wait_yet             ;A wiëc czekamy na zamkniëcie requestera
                                  ;przez uûytkownika
     bsr.w   remove_patch         ;i usuwamy naszâ funkcjë podstawiajâc
                                  ;poprzedniâ
exit:
     tst.l   window_base          ;Czy okno programu otwarte?
     beq.s   check_dos_base       ;Nie
     move.l  window_base,a0       ;Tak, zamykamy nasze okno
     move.l  int_base,a6
     call    CloseWindow
check_dos_base:
     move.l  4.w,a6
     tst.l   dos_base             ;Czy biblioteka Dos otwarta?
     beq.s   check_int_base       ;Nie
     move.l  dos_base,a1          ;Tak, to jâ zamykamy
     call    CloseLibrary
check_int_base:
     tst.l   int_base             ;Czy biblioteka Intuition otwarta?
     beq.s   check_icon_base      ;Nie
     move.l  int_base,a1          ;Tak, zamykamy bibliotekë Intuition
     call    CloseLibrary
check_icon_base:
     tst.l   icon_base            ;Czy biblioteka Icon otwarta?
     beq.s   check_msg            ;Nie
     move.l  icon_base,a1         ;Zamykamy jâ
     call    CloseLibrary
check_msg:
     tst.l   message              ;Czy istnieje komunikat odebrany z pr_MsgPort?
     beq.s   leave_program        ;Nie
     call    Forbid               ;Dla bezpieczeïstwa, wywoîujemy Forbid()
     move.l  message,a1           ;Informujemy MsgPort, ûe komunikat zostaî
     call    ReplyMsg             ;odebrany i moûna go usunâê
leave_program:                    ;Wyjôcie z programu
     movem.l (sp)+,d0-d3/a0-a2/a6 ;Rejestry ze stosu
     moveq   #0,d0                ;ERROR=0
     rts

find_task:                        ;Ta procedura odnajduje nasz task
     sub.l   a1,a1
     move.l  4.w,a6
     call    FindTask
     move.l  d0,a0
     tst.l   pr_CLI(a0)           ;Gdy uruchomiony z CLI to pr_CLI>0
     bne.s   cli_task             ;Skok gdy uruchomiony z CLI
     lea     pr_MsgPort(a0),a0    ;Czekamy na komunikat z MsgPortu i
     call    WaitPort             ;odbieramy go
     call    GetMsg
     move.l  d0,message           ;Wskaúnik na komunikat w message
cli_task:
     rts

open_libraries:                   ;Otwieranie potrzebnych bibliotek
     lea     dos_name,a1
     moveq   #0,d0
     move.l  4.w,a6
     call    OpenLibrary
     beq.s   open_error
     move.l  d0,dos_base
     lea     int_name,a1
     moveq   #0,d0
     call    OpenLibrary
     beq.s   open_error
     move.l  d0,int_base
     tst.l   message              ;Czy uruchomiony z workbencha?
     beq.w   positive_flag        ;Nie, biblioteka Icon nie potrzebna
     lea     icon_name,a1
     moveq   #0,d0
     call    OpenLibrary
     move.l  d0,icon_base
open_error:
     rts

find_tool_type:                   ;Czytamy nasze ToolTypes'y
     move.l  message,a2
     move.l  sm_ArgList(a2),a2    ;Lista argumentów z komunikatu
     move.l  wa_Lock(a2),d1       ;Lock - katalog z którego nasz program
     move.l  dos_base,a6          ;zostaî wczytany
     call    CurrentDir
     move.l  wa_Name(a2),a0       ;Nazwa ikony naszego programu
     move.l  icon_base,a6
     call    GetDiskObject        ;Otwieramy ikonë
     beq.w   no_icon              ;Co brak?, to jakiô bîâd. Natychmiast
                                  ;trzeba 'wyjôê z siebie'
     move.l  d0,disk_Obj          ;disk_Obj=wskaúnik na naszâ ikonë
     lea     eng_tool_type,a1     ;ToolType w j. angielskim
     bsr.s   find_it              ;Odnajdujemy ToolType
     beq.s   find_other           ;Nie znaleziony, moûe po polsku?
     bsr.s   read_language        ;Sprawdzamy jaki jezyk jest ustawiony w
                                  ;ToolTypes i ustawiamy flagë language_flag
     bra.w   no_icon              ;i wyjôcie z tej procedury, ERROR=0
find_it:
     move.l  disk_Obj,a2          ;Procedurka czytajâca ToolTypes
     move.l  do_ToolTypes(a2),a0  ;Wskaúnik na ciâg znaków zawarty w ToolTypes
     call    FindToolType         ;ikony
     move.l  d0,a0                ;Do A0 wysyîamy tekst znajdujâcy sië w
     rts                          ;ToolTypes ikony
find_other:
     lea     pol_tool_type,a1     ;ToolType w j. polskim
     bsr.s   find_it              ;Tak jak poprzednio
     beq.w   positive_flag        ;ToolType nie odnaleziony, jezyk ustawiony
                                  ;na angielski
     bsr.s   read_language        ;Tak jak wyûej
     bra.w   no_icon              ;wyjôcie z tej procedury ERROR=0

read_language:
     lea     eng_arg,a1           ;Procedurka obsîugujâca teskst znajdujâcy
     addq.w  #2,a1                ;sië w ToolTypes naszej ikony
     move.w  #5,d0                ;Dîugoôê tekstu
     move.l  a0,-(sp)
     bsr.s   read_in_english      ;Skok do procedury, która kolejno czyta
                                  ;nasz tekst w j. angielskim, a jeûeli go
                                  ;nie znajdzie to w polskim
     move.l  (sp)+,a0
     lea     pol_arg,a1           ;Argument jaki powinien byê pobrany
                                  ;z CLI jest inny niû ten pobrany z
                                  ;ikony
                                  ;Trzeba go zmieniê
                                  ;W A1 znajduje sië "POPOLSKU",
     addq.w  #2,a1                ;a po wykonaniu tego w A1 znajduje sië
                                  ;"POLSKU"
     move.b  #"I",5(a1)           ;A teraz to i mamy "POLSKI"
     move.w  #5,d0                ;Tak jak wyûej
     bsr.s   read_in_english
close_icon:
     move.l  disk_Obj,a0          ;Zamykamy naszâ ikonë i wychodzimy z
     call    FreeDiskObject       ;ERROR=0
     bra.w   positive_flag

read_args:
     move.l  cli_args,a0          ;Procedurka czytajâca (po angielsku i po
     lea     eng_arg,a1           ;polsku) argumenty pobrane z CLI
     move.w  #8-1,d0              ;W wyrazie "INPOLISH" jest 8 liter
read_in_english:
     move.b  (a0)+,d1             ;Do D1 przesyîamy pierwszâ literë z argumentu,
                                  ;który zostaî pobrany z CLI lub ToolTypes
     cmp.b   #"Z",d1              ;Czy w D1 znajduje sië duûa czy maîa litera?
     ble.s   capital_letter0      ;Duûa
     subi.b  #"z"-"Z",d1          ;Maîa, a wiec trzeba zrobiê z niej duûâ
                                  ;poniewaû taki jest 'defaultowy' argument
capital_letter0:
     move.b  (a1)+,d2             ;Nasza literka (po wszystkich torturach)
                                  ;idzie do D2
     cmp.b   d1,d2                ;Czy pierwsza litera argumentu=pierwszej
                                  ;literze 'defaultowego' argumentu?
     bne.s   read_in_polish       ;Nie
     dbf     d0,read_in_english   ;Tak, czytamy literë kolejnâ
     bra.s   polish               ;language_flag=1 to znaczy j. polski
read_in_polish:
     move.l  cli_args,a0
     lea     pol_arg,a1
     move.w  #8-1,d0              ;W wyrazie "POPOLSKU" jest równieû 8 liter
read_nxt_letter:
     move.b  (a0)+,d1             ;Dalej jest tak jak wyûej
     cmp.b   #"Z",d1
     ble.s   capital_letter1
     subi.b  #"z"-"Z",d1
capital_letter1:
     move.b  (a1)+,d2
     cmp.b  d1,d2
     bne.s   english
     dbf     d0,read_nxt_letter
polish:
     move.b  #1,language_flag
english:
     rts

open_window:                      ;Procedurka otwierajâca nasze okno
     lea     window_struct,a0
     move.l  int_base,a6
     call    OpenWindow
     move.l  d0,window_base
     rts

set_right_language:               ;Ta procedurka sprawdza jaki jezyk zostaî
                                  ;wybrany przez uûytkownika, a nastëpnie
                                  ;jeûeli jest to jezyk polski podmienia
     tst.b   language_flag        ;bodytext, positivetext i negativetext
     beq.s   language_ok          ;na odpowiedniki po polsku
     lea     body_text_0,a0
     move.l  #pol_info_text_0,12(a0);Podmienia adresy bodytext'u
     lea     body_text_1,a0
     move.l  #pol_info_text_1,12(a0)
     lea     positive_text,a0
     move.l  #pol_pos_text,12(a0) ;Podmienia adresy positivetext'u i
     lea     negative_text,a0     ;negativetext'u
     move.l  #pol_neg_text,12(a0)
language_ok:
     rts

install_patch                     ;Procedurka instalujâca nowâ funkcjë
     move.l  4.w,a6               ;Baza biblioteki Exec
     move.l  _LVODebug+2(a6),a2   ;Adres funkcji Debug() z ROM'u
     move.l  new_function,a0      ;Adres nowej funkcji
     cmp.l   (a2),a0              ;Jeûeli sâ równe to znaczy, ûe funkcja
                                  ;jest juû zainstalowana
     beq.s   already_installed    ;Skok aby poinformowaê o tym uûytkownika
     move.l  _LVODebug+2(a6),old_function+2;Zapamiëtujemy adres funkcji z ROM'u
     move.l  #new_function,d0     ;W D0 zapamiëtujemy adres nowej funkcji
     bsr.s   patch                ;i instalujemy jâ
     bra.w   positive_flag        ;No i wychodzimy z ERROR=0

already_installed:                ;Ta procedurka jest wywoîywana gdy
                                  ;uûytkownik uruchomi program wtedy kiedy
                                  ;jest on juû uruchomiony
     tst.b   language_flag        ;Jeûeli language_flag>0 (j. polski)
     bne.s   print_in_polish      ;to informacja zostanie wydrukowana po
                                  ;polsku
     lea     eng_ai_text,a0
     bsr.s   print
     moveq   #0,d0
     rts

print_in_polish:                  ;Podmieniamy tekst po angielsku
     lea     eng_ai_text,a0       ;na tekst po polsku
     lea     16(a0),a1
     lea     pol_ai_text,a2
copy_txt:
     move.b  (a2)+,(a1)+
     bne.s   copy_txt
     bsr.s   print
     moveq   #0,d0
     rts

print_message:                    ;Ta procedurka jest wywoîywana przy
     lea     my_info_text,a0      ;kaûdym uruchomieniu programu z CLI
     bsr.s   print
     rts

wait_for_close:                   ;Ta procedurka czeka na zamkniëcie okna przez
     move.l  window_base,a0       ;uûytkownika
     move.l  wd_UserPort(a0),a0
     move.b  MP_SIGBIT(a0),d1     ;Bity sygnaîowe okna
     moveq   #1,d0                ;Ukryty numer bitu i umieszczenie
     lsl.l   d1,d0                ;rezultatu w D0
     move.l  4.w,a6
     call    Wait
     rts

remove_patch:                     ;Procedurka zwracajâca do ROM'u poprzedniâ
     move.l  old_function+2,d0    ;funkcjë
     bsr.s   patch
     rts

patch:                            ;Procedurka instalujâca starâ/nowâ funkcjë
     call    Forbid               ;w ROM'ie
     move.w  #_LVODebug,a0
     move.l  a6,a1
     call    SetFunction
     call    Permit
     rts

print:                            ;Procedurka drukujâca tekst
     tst.l   message
     bne.s   positive_flag
     move.l  a0,d2
     move.l  dos_base,a6
     call    Output               ;Odnajdujemy bazë okna CLI
     move.l  d0,d1
     move.l  d2,a0
     moveq   #-1,d3
size_loop:                        ;Ta petelka oblicza iloôê znaków w tekôcie
     addq.l  #1,d3
     tst.b   (a0)+
     bne.s   size_loop
     call    Write
no_print:
     rts

positive_flag:                    ;Wskaúnik na ERROR=0
     moveq   #1,d0
no_icon:
     rts

new_function:                     ;Nowa funkcja
     movem.l d0-d3/a0-a3/a6,-(sp)
     move.b  #1,req_active        ;Ustawiamy aby uûytkownik nie mogî zamknâê
                                  ;okna podczas gdy requester jest aktywny
     move.l  int_base,a6
     move.l  ib_ActiveWindow(a6),a0;Baza aktywnego okna do A0
     lea     body_text_0,a1       ;Struktura bodytext,
     lea     positive_text,a2     ;positivetext
     lea     negative_text,a3     ;i negativetext
     moveq   #0,d0
     moveq   #0,d1
     move.l  #322,d2              ;Szerokoôê requestera
     moveq   #62,d3               ;Wysokoôê requestera
     call    AutoRequest
     beq.s   no_debug
     clr.b   req_active
     movem.l (sp)+,d0-d3/a0-a3/a6
old_function:
     jmp      0.l                 ;Skok do poprzedniej funkcji, kiedy
                                  ;uûytkownik wcisnâî "Yes/Tak"
no_debug:
     clr.b   req_active
     movem.l (sp)+,d0-d3/a0-a3/a6
     rts
function_end:

     section data,data

dos_name:  DOSNAME

icon_name: ICONNAME

int_name:  INTNAME

eng_tool_type:  dc.b "LANGUAGE",0
pol_tool_type:  dc.b "JËZYK",0

eng_arg:        dc.b "INPOLISH",0
pol_arg:        dc.b "POPOLSKU",0

my_info_text:   dc.b 10,155,"1;33mROMWack Patcher v2.0",155,"1;31m  FREEWARE"
                dc.b    " © 1995, Grzegorz Królik",155,"0m",10,0

eng_ai_text:    dc.b "ROMWack Patcher already installed",10,0
pol_ai_text:    dc.b "jest juû zainstalowany",10,0
                even
cli_args:       dc.l 0
message:        dc.l 0
window_base:    dc.l 0
dos_base:       dc.l 0
icon_base:      dc.l 0
int_base:       dc.l 0
disk_Obj:       dc.l 0
req_active:     dc.b 0
language_flag:  dc.b 0
                even

window_struct:  dc.w    102,0
                dc.w    436,10
                dc.b    0,1
                dc.l    CLOSEWINDOW
                dc.l    SMART_REFRESH+WINDOWDRAG+WINDOWDEPTH+WINDOWCLOSE+NOCAREREFRESH
                dc.l    0
                dc.l    0
                dc.l    window_name
                dc.l    0,0
                dc.w    0,0
                dc.w    0,0
                dc.w    WBENCHSCREEN

body_text_0:    dc.b    1,0
                dc.b    RP_JAM1+RP_COMPLEMENT,0
                dc.w    15,5
                dc.l    0
                dc.l    eng_info_text_0
                dc.l    body_text_1

body_text_1:    dc.b    1,0
                dc.b    RP_JAM1+RP_COMPLEMENT,0
                dc.w    14,15
                dc.l    0
                dc.l    eng_info_text_1
                dc.l    0

positive_text:  dc.b    1,0
                dc.b    RP_JAM1+RP_COMPLEMENT,0
                dc.w    6,3
                dc.l    0
                dc.l    eng_pos_text
                dc.l    0

negative_text:  dc.b    1,0
                dc.b    RP_JAM1+RP_COMPLEMENT,0
                dc.w    6,3
                dc.l    0
                dc.l    eng_neg_text
                dc.l    0

window_name:    dc.b    "ROMWack Patcher v2.0 © 1995, Grzegorz Królik",0

eng_info_text_0:dc.b    "Do you really want to run ROMWack,",0
eng_info_text_1:dc.b    "the Amiga's ROM-resident debugger?",0

pol_info_text_0:dc.b    "Czy naprawdë chcesz uruchomiê",0
pol_info_text_1:dc.b    "rezydentny debugger ROMWack?",0

eng_pos_text:   dc.b    "Yes",0
eng_neg_text:   dc.b    "No",0

pol_pos_text:   dc.b    "Tak",0
pol_neg_text:   dc.b    "Nie",0
                end
