*** FME.asm - FastMemEmulator V1.0 - © 30.09.1989 by Holger Lubitz *** *** Patcht die AllocMem()-Routine so, daß keine explizite Anforderung von *** FastMem mehr möglich ist, wenn nicht gleichzeitig das MEMF_LARGEST-Bit *** gesetzt ist. Bei bereits installiertem Patch wird dieser entfernt. *** *** Sinn der Sache ist, an sich interessante Programme wie Evolution (Fish *** 239) oder Crud, Demon und Life (alle Fish 249), die sich aber aus *** unerfindlichen Gründen nicht ohne FastMem zufriedengeben, auch auf *** Amigas ohne FastMem (512k oder 1MB mit Fatter Agnus) zum Laufen zu *** bringen, ohne in den Programmen selbst herumpatchen zu müssen. *** *** Von der Benutzung dieses Programms auf Amigas MIT FastMemory wird *** vorsorglich abgeraten ! (Auch wenn es normalerweise nichts schaden *** dürfte, aber sicher ist sicher) *** *** Quellen: A68k von Fish 186, BLink von Fish 110, small.lib von Fish 92 *** *** 1> A68k FME.asm *** 1> BLink FME.o small.lib to FME *** *** FME ist zuerst im AmigaJUICE 17 (November 1989) erschienen. *** Die jeweils neueste AmigaJUICE-Ausgabe gibts gegen Einsendung einer *** Leerdiskette mit frankiertem Rückumschlag (1,70 DM Porto) bei: *** AmigaJUICE, c/o Holger Lubitz, Postfach 1431, 3070 Nienburg/Weser *** *** FME darf frei kopiert werden, wenn das Programm zusammen mit dem Source *** und unverändert weiterkopiert wird. (diese Vermerke müssen drinbleiben !) *** *** P.S.: 380 Bytes für dieses Programm sind ziemlich kurz, oder ? *** An alle: Lernt Assembler, wenn ihr den Amiga WIRKLICH effizient *** programmieren wollt !! XREF _LVOAllocMem XREF _LVOClose XREF _LVOCloseLibrary XREF _LVODelay XREF _LVOForbid XREF _LVOFindTask XREF _LVOFreeMem XREF _LVOGetMsg XREF _LVOOldOpenLibrary XREF _LVOOpen XREF _LVOOutput XREF _LVOPermit XREF _LVOReplyMsg XREF _LVOSetFunction XREF _LVOWaitPort XREF _LVOWrite _AbsExecBase = 4 ThisTask = 276 pr_CLI = $ac pr_MsgPort = $5c MODE_OLDFILE = 1005 SECTION "",CODE *** Registerbelegung: A6 reserviert für Exec-Base *** A5 reserviert für Adresse der Taskstruktur *** A4 reserviert für DOS-Base *** A3 reserviert für Adresse des Speicherblocks *** D7 reserviert für Länge des Speicherblocks *** D6 reserviert für Fenster-Handle *** Eigenen Task finden move.l _AbsExecBase,a6 ; Exec-Basisadresse move.l ThisTask(a6),a5 ; FindTask(0) - Thanxx Fridtjof *** DOS-Library öffnen lea dosname(pc),a1 ; Zeiger auf 'dos.library' jsr _LVOOldOpenLibrary(a6) ; Version ist egal move.l d0,a4 ; Basisadresse in A4 ; Kein Test ! ; Ohne dos.library sind wir eh schon kurz ; vorm Absturz :-) ; Übrigens: DOS ist die EINZIGE Library, ; die ihre Basisadresse beim Aufruf NICHT ; in A6 braucht (BCPL's einziger Vorteil) *** Test auf Workbench oder CLI tst.l pr_CLI(a5) ; Sind wir vom CLI aus gestartet worden ? beq.s WB ; Wenn nicht dann zum WB-Startup *** CLI-Startup CLI jsr _LVOOutput(a4) ; Handle des CLI-Fensters move.l d0,d6 ; in D6 bra.s main ; und zum Start des Patches *** WB-Startup WB lea.l pr_MsgPort(a5),a0 ; Sonst auf die Message warten jsr _LVOWaitPort(a6) ; die die Workbench sendet jsr _LVOGetMsg(a6) ; Sie ist da, wie schön ! move.l d0,-(a7) ; Zeiger auf Message sichern lea fenster(pc),a0 ; Zeiger auf Fenstertitel move.l a0,d1 ; in D1 move.l #MODE_OLDFILE,d2 ; CON: sollte es schon geben jsr _LVOOpen(a4) ; öffnen tst.l d0 ; hats geklappt ? beq.s wbexit ; sonst hats keinen Zweck move.l d0,d6 ; Fenster-Handle in D6 sichern main *** Länge des Patches ermitteln und in D7 speichern moveq #endpatch-startpatch,d7 ; Länge unseres Patches *** Testen, ob wir schon installiert sind move.l _LVOAllocMem+2(a6),a3 ; Anfangsadresse AllocMem() move.l startpatch(pc),a0 ; Start unseres Patches cmp.l (a3),a0 ; sind wir schon da ? beq.s remove ; dann entfernen *** Speicher für den Patch reservieren move.l d7,d0 ; Länge in D0 moveq #0,d1 ; keine besonderen Anforderungen jsr _LVOAllocMem(a6) ; Speicher belegen *** Speicher bekommen ? tst.l d0 ; Enthält D0 eine Startadresse ? beq.s fehler ; bei 0 haben wir keinen Speicher bekommen ; TEST! Speicheranforderungen müssen ; immer getestet werden, auch wenn das ; System lumpige 16 Bytes eigentlich ; finden sollte. *** Startadresse in A3 zwischenspeichern move.l d0,a3 ; Adressen immer in Adressregister ! ; außerdem brauchen wirs noch als Basis ; (schau mal ein paar Zeilen tiefer) *** Den Patch kopieren lea startpatch(pc),a0 ; Startadresse des Patches in A0 move.l a3,a1 ; Start reservierter Speicher in A1 subq #1,d7 ; weil DBRA-Loop copyloop ; Kopierschleife move.b (a0)+,(a1)+ ; byteweise kopieren dbra d7,copyloop ; weil in D7 die Länge in Bytes steht *** Korrekten ROM-Einsprung für AllocMem in Patch nachtragen move.l _LVOAllocMem+2(a6),allocmem-startpatch+2(a3) *** AllocMem() umpatchen move.l a3,d0 ; Startadresse des Patches bsr.s patch *** Installed-Text ausgeben lea text1(pc),a0 ; Text-Adresse nach A0 moveq #text1e-text1,d3 ; Länge in D3 bsr.s schreibe *** und aufräumen bra.s cleanup *** Hier wird der Patch wieder entfernt remove move.l allocmem-startpatch+2(a3),d0 ; originalen AllocMem-Einsprung holen bsr.s patch *** und der Speicher wieder freigegeben move.l d7,d0 ; Länge in D0 move.l a3,a1 ; Startadresse in A1 jsr _LVOFreeMem(a6) ; D0 Bytes ab A1 freigeben *** Removed-Text ausgeben lea text2(pc),a0 moveq #text2e-text2,d3 bsr.s schreibe bra.s cleanup *** Fehler-Text ausgeben fehler lea text3(pc),a0 moveq #text3e-text3,d3 bsr.s schreibe *** Falls vom CLI gestartet, sind wir fast fertig cleanup tst.l pr_CLI(a5) ; war es das CLI ? bne.s closelib ; dann dos.library schließen *** Sonst haben wir noch ein bißchen zu tun (WB-Cleanup) *** Fenster schließen move.l #150,d1 ; 150/50 (also 3) Sekunden jsr _LVODelay(a4) ; warten (damit mans auch lesen kann) move.l d6,d1 ; Fenster jsr _LVOClose(a4) ; schließen wbexit bsr.s closelib ; dos-lib schließen *** Msg beantworten jsr _LVOForbid(a6) ; Wir wollen nicht zu früh von der WB ; rausgeschmissen werden move.l (a7)+,a1 ; Die gesicherte msg nach A1 jmp _LVOReplyMsg(a6) ; und endlich antworten *** DOS-Lib schließen (erwartet DOSBase in A4 und Exec-Base in A6) closelib move.l a4,a1 ; Dos-Base nach A1 jmp _LVOCloseLibrary(a6) ; schließen *** Die Routine zum Patchen von AllocMem() in der Exec-Sprungleiste *** wird zweifach aufgerufen, steht darum hier. patch jsr _LVOForbid(a6) ; Multitasking aus (sicher ist sicher) move.l #_LVOAllocMem,a0 ; Offset von AllocMem move.l a6,a1 ; gepatcht wird in Exec jsr _LVOSetFunction(a6) ; und ändern. jmp _LVOPermit(a6) ; Multitasking wieder erlauben *** Text ausgeben (a0 und d3 müssen Adresse und Länge enthalten) schreibe move.l d6,d1 move.l a0,d2 jmp _LVOWrite(a4) *** Hier beginnt der eigentliche Patch startpatch ; Label für Patch-Startadresse btst #17,d1 ; MEMF_LARGEST-Bit testen bne.s allocmem ; Bei soviel Hunger MEMF_FAST lieber nicht löschen ; (für Kompatibilität mit etlichen NOFASTMEM-Programmen) bclr #2,d1 ; sonst MEMF_FAST-Bit löschen allocmem jmp $12345678 ; diese Adresse wird erst in der Patch-Kopie angepaßt ; (sonst wäre FME nicht resident-fähig) endpatch ; dient zur Längenermittlung des Patches *** Dies ist die Text-Sektion dosname dc.b "dos.library",0 fenster dc.b "CON:10/10/320/80/HAL's FastMemEmulator",0 text1 dc.b "Patch installiert",10 text1e text2 dc.b "Patch entfernt",10 text2e text3 dc.b "Kein Speicher",10 text3e END