home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
AmigActive 13
/
AACD13.ISO
/
AACD
/
Utilities
/
ACDPlay
/
src
/
V1.6
/
asmlib
/
QuickFuncs.s
< prev
next >
Wrap
Text File
|
1997-07-15
|
49KB
|
1,005 lines
*
* QuickFuncs.s V0.22 by mak und MC3 passend zu ACDPlay.c V1.49
*
* Ersetzt einige C-Routinen von ACDPlay durch schnellere und kürzere
* Assemblervarianten. QuickFuncs muß als Object-File in ACDPlay eingebunden
* werden (Make), die Protos (Quickfuncs.h) dürfen natürlich auch nicht fehlen.
* Zum assemblieren muß die CATCOMP_NUMBERS Sektion des aktuellen Katalogs für
* Assembler als Datei "locale.i" vorhanden sein.
*
* ACHTUNG! Alle Funktionen hier (und auch C) gehen davon aus daß alle Register
* erhalten bleiben. Darum müssen alle Register die irgendwie verändert
* werden gesichert werden. Auch d0, wenn kein Wert zurückgegeben wird.
*
* Autor Version Datum Veränderungen
* ------- --------- -------- ------------------------------------------
* mak 0.01 23.10.96 NewShowMsg() und NewGetVec() dazu
* 24.10.96 NewFlushMessages() dazu
* 0.02 26.10.96 Funktionen benutzen jetzt die lokalisierten
* Texte von ACDPlay
* 0.03 31.10.96 NewOpenLibs() erstellt
* 0.04 4.11.96 NewCloseLibs() neu
* 0.05 6.11.96 Funktionsnamen von New.. in ..A geändert
* OpenARexxPortA() erstellt
* QuickFuncs.h erstellt
* 7.11.96 CloseARexxPortA() hinzu
* 12.11.96 StrCmpA() geschrieben
* 0.06 14.11.96 HandleARexxMsgA() endlich fertiggestellt
* 15.11.96 HandleARexxMsgA() optimiert und erweitert
* Play, Stop, Eject, JumpForward und JumpBackward eingeführt
* 0.07 17.11.96 FormatA() umgesetzt
* 18.11.96 alles ausführlich kommentiert
* (falls dich die narrensichere Kommentierung nervt, sag das bitte)
* 0.08 20.11.96 HandleARexxMsgA() gibt jetzt BOOL zurück
* SHOW, HIDE, QUIT hinzugeführt und JUMPFORWARD in NEXTSONG geändert
* 0.09 22.11.96 FindARexxPort() fertiggestellt und OpenARexxPort() gibt
* jetzt nicht mehr PORTALREADYOPEN zurück (jetzt durch FindARexxPort())
* 23.11.96 'ACDP'-Messagetyp eingeführt (private rexxlike Messages)
* 0.10 25.11.96 FakeRequestA() fertiggestellt
* 0.11 04.01.97 Mindestversion des zu öffnenden Katalogs ist CATALOG_VERSION
*
* MC3 0.12 29.01.97 Workbench.library wird geöffnet
*
* mak 0.13 02.02.97 ARexx 'SHOW' schließt jetzt AppIcon
*
* MC3 0.14 14.02.97 ChangeButtonTextA() erstellt
* 16.02.97 asl.library wird geöffnet (wenn vorhanden)
* Library-Locales dazu
*
* mak 0.16 23.02.97 ExecuteARexxA() dazu
* 01.03.97 OPEN, CLOSE und PAUSE hinzu
* CloseARexxPortA() und FlushMsgA() testen auf NULL
* 0.17 08.03.97 OpenLibsA() überprüft ob mathieeedoubbas.library vorhanden ist
* 0.18 14.03.97 Rexx-Kommandos extrahiert
* ExecuteARexxA() öffnet jetzt ggf. ein Window
* 0.19 23.03.97 Fehlermeldung für RexxSysLib-Fehler stimmt jetzt
* 0.20 06.04.97 ChangeButtonTextA auskommentiert
* CON-Fenster von ExecuteArexxA() ist jetzt vom Typ AUTO
* 0.21 27.04.97 HandleARexxMsgA() überarbeitet
* rexxcmds.s überarbeitet und ca. 40 ARexx-Kommandos dazu
* 0.22 11.07.97 FindPort´s() mit Forbid abgesichert
* 15.07.97 MyGT_SetGadgetAttrs() erstellt
include 'exec/ports.i'
include 'dos/dos.i'
include 'dos/dosextens.i'
include 'intuition/intuition.i'
include 'libraries/gadtools.i'
include 'libraries/locale.i'
include 'rexx/rxslib.i'
include 'rexx/storage.i'
include 'lvo/dos.i'
include 'lvo/exec.i'
include 'lvo/gadtools.i'
include 'lvo/graphics.i'
include 'lvo/intuition.i'
include 'lvo/locale.i'
include "locale.i"
xref _GetString
xref __wbflag
xref _CDPlayBase
xref _CxBase
xref _DOSBase
xref _GadToolsBase
xref _GfxBase
xref _WorkbenchBase
xref _IconBase
xref _AslBase
xref _IntuitionBase
xref _LocaleBase
xref _RexxSysBase
xref _ScreenNotifyBase
xref _li ; LocaleInfo Struktur die _GetString übergeben wird
xref _ls ; Array mit Zeigern auf lokalisierte Texte
FALSE equ 0
TRUE equ 1
NULL equ 0
include "CD-ROM.s"
************************* FakeRequestA *****************************
*
* void FakeRequestA(struct Window *win, APTR visualinfo, LONG xoffset, LONG yoffset, LONG height);
*
* Füllt das Fenster 'win' mit einem Muster aus und malt in der Mitte ein
* von einer umgedrehten BevelBox umrahmtes Rechteck mit Farbe 0, so daß es
* wie ein IntuitionRequester aussieht. Die Offsetparameter beziehen sich
* dabei auf den inneren Rand des Fensters.
*
CNOP 0,2
xdef _FakeRequestA
_FakeRequestA: movem.l d0-d5/a0-a6,-(sp)
movem.l 52+4(a7),a3-a4 ; a3=win a4=visualinfo
lea wd_RPort(a3),a2
movea.l (a2)+,a5 ; a5=RastPort
.PrepareRPort lea Pattern(pc),a0 ; Daten für Ditherpattern in
move.l a0,rp_AreaPtrn(a5) ; RastPort eintragen
move.b #1,rp_AreaPtSz(a5)
movea.l _GfxBase,a6 ; GfxBase laden
movea.l a5,a1
moveq #2,d0 ; Vordergrundfarbe auf weiß
jsr _LVOSetAPen(a6) ; setzen
.DitherWindow moveq #0,d0 ; d0 und d1 müssen vom Typ
moveq #0,d1 ; LONG sein
move.b (a2)+,d0 ; =wd_BorderLeft
move.b (a2)+,d1 ; =wd_BorderTop
move.b (a2)+,d4 ; =wd_BorderRight
move.b (a2),d5 ; =wd_BorderBottom
ext.w d4 ; d4 und d5 auf WORD
ext.w d5 ; erweitern
movem.w wd_Width(a3),d2-d3 ; Windowbreite und Höhe laden
sub.w d4,d2 ; x2 = Width-BorderRight-1
sub.w d5,d3 ; y2 = Height-BorderBottom-1
subq.w #1,d2
subq.w #1,d3
ext.l d2 ; RectFill erwartet Parameter
ext.l d3 ; vom Typ LONG, darum erweitern
movem.l d0-d1,-(a7) ; wird noch gebraucht
movea.l a5,a1 ; RastPort ist Parameter
jsr _LVORectFill(a6) ; Window Füllen
clr.l rp_AreaPtrn(a5) ; Dithermuster wieder löschen
clr.b rp_AreaPtSz(a5)
movea.l a5,a1 ; RastPort ist Parameter
moveq #0,d0 ; sollte aus DrawInfo gelesen werden...
jsr _LVOSetAPen(a6) ; Vordergrundfarbe auf 0 setzen
.ClearArea movem.l (a7)+,d0-d1 ; gesichertes left, top laden
lea 52+12(a7),a0 ; Adresse der Parameter ab 'xoffset' laden
add.l (a0),d0 ; left=left+xoffset
sub.l (a0)+,d2 ; right=right-xoffset
add.l (a0)+,d1 ; top=top+yoffset
move.l d1,d3
add.l (a0),d3 ; bottom=top+height-1
movem.l d0-d1/d3,-(a7) ; wird nochmal gebraucht
subq.l #1,d3
movea.l a5,a1 ; RastPort
jsr _LVORectFill(a6) ; Fläche löschen
.DrawBevelBox movea.l _GadToolsBase,a6 ; für DrawBevelBoxA
movea.l a5,a0 ; RastPort ist Parameter
movem.l (a7)+,d0-d1/d3
sub.l d0,d2 ; Absolute Koordinaten in
addq.l #1,d2 ; Breite / Höhe wandeln
sub.l d1,d3
lea BevelBoxTags(pc),a1 ; Taglist laden
move.l a4,4(a1) ; VisualInfo in TagList eintragen
jsr _LVODrawBevelBoxA(a6) ; inverse BevelBox zeichnen
.EXIT movem.l (sp)+,d0-d5/a0-a6
rts
Pattern: dc.w %1010101010101010
dc.w %0101010101010101
BevelBoxTags: dc.l GT_VisualInfo, NULL
dc.l GTBB_Recessed, TRUE
dc.l TAG_END
************************** ListLengthA *****************************
*
* ULONG ListLengthA(register __a0 struct List *list);
*
CNOP 0,2
xdef _ListLengthA
_ListLengthA: movem.l d1/a0,-(sp) ; Register sichern
moveq #-2,d0 ; Zähler auf -2 setzen
.Loop addq.l #1,d0 ; Nodezähler erhöhen
move.l (a0),a0 ; lh_Head/ln_Succ in a0
move.l a0,d1 ; für Condition-Flags
bne.s .Loop ; bis Liste zu Ende ist
.EXIT movem.l (sp)+,d1/a0 ; Register restaurieren
rts
************************** ChangeButtonTextA ***********************
*
* struct Gadget *ChangeButtonTextA(register __a0 struct Application *app, register __a1 struct Window *win, register __a2 struct Gadget *prevgad, register __a3 char *newtext);
*
* Vorsicht: Es wird auf die Application-Struktur zugegriffen!
* Diese darf sich vor app->font nicht mehr ändern!
*
; CNOP 0,2
; xdef _ChangeButtonTextA
;_ChangeButtonTextA:
; movem.l d1/a0-a6,-(sp) ; Register sichern
; moveq #0,d0 ; für die Rückgabe
;
; move.l (a2),a4 ; gad = prevgad->NextGadget
; move.l (a4),a5 ; nextgad = gad->NextGadget
;
; move.l a2,d1 ; prüft prevgad
; beq.s .EXIT
; move.l a4,d1 ; prüft gad
; beq.s .EXIT
;
; lea NewGadStruct(pc),a6 ; newgad laden
;
; move.l 4(a4),(a6) ; LeftEdge, TopEdge kopieren
; move.l 8(a4),4(a6) ; Width, Height kopieren
; move.l a3,8(a6) ; GadgetText kopieren
; move.l 16(a0),12(a6) ; app->font nach TextAttr ***
; move.w 38(a4),16(a6) ; GadgetID kopieren
; move.l 12(a0),22(a6) ; app->visualinfo kopieren ***
;
; move.l d0,(a4) ; NextGadget auf NULL
; move.l a4,a0 ; gad ist Parameter
; move.l a1,a3 ; win verlagern, damit
; move.l a6,a1 ; newgad nach a1 kann
; movea.l _GadToolsBase,a6 ; für Funktionsaufruf
;
; movem.l a0-a6,-(sp) ; alles retten
; jsr _LVOFreeGadgets(a6) ; FreeGadgets()
; movem.l (sp)+,a0-a6 ; alles restaurieren
;
; moveq #BUTTON_KIND,d0 ; Argument 1
; move.l a2,a0 ; Argument 2
; ; Argument 3 ist bereits in a1
; suba.l a2,a2 ; auf NULL setzen (Argument 4)
;
; movem.l a0-a5,-(sp) ; alles retten
; jsr _LVOCreateGadgetA(a6) ; CreateGadgetsA()
; movem.l (sp)+,a0-a5 ; alles restaurieren
;
; tst.l d0 ; Rückgabewert testen
; beq.s .EXIT ; ggf. weg
;
; move.l d0,a0 ; gad sichern & Argument 1
; move.l a5,(a0) ; gad->NextGadget = nextgad
; move.l a3,a1 ; win ist Argument 2
; ; a2 ist noch NULL (Argument 3)
; moveq #1,d0 ; Argument 4
; movea.l _IntuitionBase,a6 ; für Funktionsaufruf
;
; movem.l a1,-(sp)
; jsr _LVORefreshGList(a6) ; RefreshGList()
; movem.l (sp)+,a1
;
; move.l a1,d0 ; Rückgabewert (gad)
;
;.EXIT movem.l (sp)+,d1/a0-a6 ; Register restaurieren
; rts
;
; CNOP 0,2
;NewGadStruct: dc.w 0 ; ng_LeftEdge
; dc.w 0 ; ng_TopEdge
; dc.w 0 ; ng_Width
; dc.w 0 ; ng_Height
; dc.l 0 ; ng_GadgetText
; dc.l 0 ; ng_TextAttr
; dc.w 0 ; ng_GadgetID
; dc.l 0 ; ng_Flags
; dc.l 0 ; ng_VisualInfo
; dc.l 0 ; ng_UserData
************************** FormatA ********************************
*
* void FormatA(register __a0 char *buffer, register __a1 char *formatstr, ...);
*
* Kopiert den formatierten Text formatstr nach buffer und benutzt dabei
* die Werte bzw. Adressen der Argumente vom Stack.
*
CNOP 0,2
xdef _FormatA
_FormatA: movem.l d0-d1/a0-a3/a6,-(sp) ; Register sichern
movea.l 4.w,a6 ; SysBase laden
; Argumente für RawDoFmt()
movea.l a0,a3 ; PutChData -> a3
movea.l a1,a0 ; FormatString -> a0
movea.l a7,a1 ; DataStream -> a1
lea 32(a1),a1 ; Offset da Register auf dem Stack sind
lea PutChProc(pc),a2 ; Copy-Routine
jsr _LVORawDoFmt(a6)
.EXIT movem.l (sp)+,d0-d1/a0-a3/a6 ; Register restaurieren
rts
PutChProc: move.b d0,(a3)+ ; wird von RawDoFMt aufgerufen
rts ; soll ich einen Overflowtest einbauen?
************************* ShowMsgA ********************************
*
* void ShowMsgA(char *ReqTitle, char *ReqBody, ...);
*
* Zeigt eine Nachricht Abhängig von __wbflag auf der Workbench als Requester
* oder im CLI an.
*
CNOP 0,2
xdef _ShowMsgA
_ShowMsgA: movem.l d0-d2/a0-a3/a6,-(sp)
tst.w __wbflag ; von WB gestartet?
beq .CLIMsg ; nein: in CLI schreiben
.WBMsg lea MsgEasyStruct(pc),a1 ; a1=*EasyStruct
move.l 36(a7), es_Title(a1) ; Titel eintragen
move.l 40(a7), es_TextFormat(a1) ; Text eintragen
lea _ls,a0
move.l 4*MSG_OK_REQ(a0), es_GadgetFormat(a1) ; Gadget eintragen
suba.l a0,a0 ; *Window=NULL
suba.l a2,a2 ; a2=NULL (IDCMP)
movea.l a7,a3 ; * auf restliche
adda.l #44,a3 ; Argumente nach a3
move.l _IntuitionBase, a6 ; IBase laden
jsr _LVOEasyRequestArgs(a6) ; Requester darstellen
bra .EXIT ; das wars
.CLIMsg suba.l #88,a7 ; 88 bytes auf´m Stack
move.l a7,d1 ; freimachen damit 87
moveq #87,d2 ; Zeichen da reinpassen
move.l _DOSBase, a6 ; DOSBase laden
jsr _LVOGetProgramName(a6) ; ProgNamen in Puffer schreiben
tst.w d0 ; geklappt ?
beq .WriteMsg ; nö: Msg ausgeben
move.l a7,d1
jsr _LVOPutStr(a6) ; Prognamen ausgeben
lea Colon(pc),a1
move.l a1,d1
jsr _LVOPutStr(a6) ; ": " ausgeben
.WriteMsg adda.l #88,a7 ; Stack zurücksetzen
move.l 40(a7),d1 ; ReqBody als Arg für VPrintf
move.l a7,d2
addi.b #44,d2 ; Rest als Argument
jsr _LVOVPrintf(a6) ; Msg ausgeben
lea LineFeed(pc),a1 ; erst mit dem LF
move.l a1,d1 ; erscheint alles im
jsr _LVOPutStr(a6) ; CON-CLI-Window
.EXIT movem.l (sp)+, d0-d2/a0-a3/a6 ; Register wiederherstellen
rts
MsgEasyStruct: dc.l 20 ; es_StructSize
dc.l 0 ; es_Flags
dc.l 0 ; es_Title
dc.l 0 ; es_TextFormat
dc.l 0 ; es_GadgetFormat
Colon: dc.b ": ",0
LineFeed: dc.b 10,0
************************* GetVecA *********************************
*
* APTR GetVecA(register __d0 ULONG bytesize, register __d1 ULONG requirements);
*
* Versucht 'bytesize' Bytes RAM zu erhalten und Zeigt im Fehlerfall eine
* Fehlermeldung an.
*
CNOP 0,2
xdef _GetVecA
_GetVecA: movem.l d1-d2/a0-a1/a6,-(sp) ; alte Register speichern
move.l d0,d2 ; bytesize für Fehlerfall sichern
move.l 4.w,a6 ; SysBase laden
jsr _LVOAllocVec(a6) ; AllocVec bytesize requiements
tst.l d0 ; erfolgreich?
bne .EXIT ; mem <> 0 -->.EXIT
move.l d2,-(a7) ; Argumente für NewShowMsg
lea _ls,a0 ; auf den Stack schieben
move.l 4*MSG_NO_MEMORY(a0),-(a7)
move.l 4*MSG_ERROR_TITLE(a0),-(a7)
bsr _ShowMsgA ; Error anzeigen
lea 12(a7),a7 ; Stack wieder runtersetzen
.EXIT movem.l (sp)+,d1-d2/a0-a1/a6 ; alte Register restaurieren
rts
************************* OpenLibsA ********************************
*
* BOOL OpenLibsA(void);
*
* Versucht alle benötigten (siehe Tabelle) Libraries zu öffnen und zeigt
* im Fehlerfall, falls die Library unbedingt benötigt wird, einen Requester an.
* Außerdem wird die LocaleInfo-Struktur initialisiert und die Pointer auf
* die lokalisierten Texte werden in das ls-Array kopiert.
*
CNOP 0,2
xdef _OpenLibsA
_OpenLibsA: movem.l d1-d2/d7/a0-a3/a6,-(sp)
moveq #FALSE,d7 ; success = FALSE
move.l 4.w,a6 ; SysBase laden
.OpenIntuition lea IntuitionLibName(pc),a1
moveq #37,d0
jsr _LVOOpenLibrary(a6) ; IntuitionLib V37 öffnen
move.l d0,_IntuitionBase
beq .EXIT ; if (!IntuitionBase) return success;
.OpenLocale lea LocaleLibName(pc),a1
moveq #38,d0
jsr _LVOOpenLibrary(a6) ; LocaleLib V38 öffnen
lea _li,a3 ; a3 = LocaleInfo
move.l d0,_LocaleBase
beq .CopyStrings ; if (LocaleBase)
; {
.OpenCatalog move.l d0,(a3) ; li.li_LocaleBase = LocaleBase
suba.l a0,a0
lea CatName(pc),a1
lea CatalogVerTags(pc),a2
move.l d0,a6 ; LocaleBase laden
jsr _LVOOpenCatalogA(a6) ; li.li_Catalog=OpenCatalog()
move.l d0,4(a3) ; }
.CopyStrings lea _ls,a2 ; a2 = ls[]
lea _GetString,a6 ; ein bißchen Speed...
moveq #0,d2
; for (i = 0;i < ANZ_MSG;)
.Next move.l a3,a0 ; {
move.l d2,d0
jsr (a6) ; GetString(li, id)
move.l d0,(a2)+ ; ls[i]=GetString(li, i)
addq.w #1,d2 ; i++
cmp.w #ANZ_MSG,d2 ; }
blt .Next ;
.TstMathDoub move.l 4.w,a6 ; SysBase wieder laden
lea MathDoubBasName(pc),a1
moveq #34,d0
jsr _LVOOpenLibrary(a6) ; mathieeedoubbas.library öffnen
tst.l d0 ; geklappt?
bne .CloseMathDoub ; ja: wieder schließen...
lea _ls,a0
move.l 4*MSG_NO_MATHIEEEDOUBBASLIB(a0),-(a7)
move.l 4*MSG_ERROR_TITLE(a0),-(a7); ErrorTitle auf den Stack
bsr _ShowMsgA ; Fehlertext anzeigen
addq.l #8,a7 ; Stack aufräumen
bra .EXIT
.CloseMathDoub move.l d0,a1
jsr _LVOCloseLibrary(a6)
.OpenRestLibs lea Libs(pc),a2 ; Librarytabelle laden
.Loop tst.l (a2) ; while (Libs.LibName)
beq .AllOpened ; {
move.l (a2)+,a1 ; Libs.LibName
move.l (a2)+,d0 ; Libs.Version
jsr _LVOOpenLibrary(a6) ; OpenLibrary()
move.l (a2)+,a0
move.l (a2)+,d1 ; ...[Libs++]...
move.l d0,(a0) ;
bne .Loop ; if (!(Libs.Base = OpenLibrary())
; {
.Error tst.l d1 ; ErrorText vorgesehen?
beq .Loop ; nein -> kein Fehler, weitermachen
movea.l d1,a0 ; Adresse des Errortextes auf den Stack
move.l (a0),-(a7)
move.l MSG_ERROR_TITLE*4+_ls,-(a7); ErrorTitle auf den Stack
bsr _ShowMsgA ; Fehlertext anzeigen
addq.l #8,a7 ; Stack aufräumen
bra .EXIT ; return success
; } }
.AllOpened moveq #TRUE,d7 ; success = TRUE
.EXIT move.l d7,d0
movem.l (sp)+,d1-d2/d7/a0-a3/a6
rts
CatalogVerTags: dc.l OC_Version, CATALOG_VERSION
dc.l TAG_END
************************* CloseLibsA *******************************
*
* void CloseLibsA(void);
*
* Schließt, ausgehend von der Libstabellealle, alle geöffneten Libraries
* und den geöffnetet Katalog.
*
CNOP 0,2
xdef _CloseLibsA
_CloseLibsA: movem.l d0-d7/a0-a6,-(sp)
move.l 4.w,a6 ; SysBase laden
lea Libs(pc),a2 ; Librarytabelle laden
.Loop tst.l (a2) ; while (Libs.LibName)
beq .CloseLocale ; {
move.l 8(a2),a1 ; Libs.LibName
tst.l (a1) ; Library geöffnet?
beq .IsClosed
move.l (a1),a1
jsr _LVOCloseLibrary(a6) ; Library schließen
.IsClosed add.l #16,a2
bra .Loop ; }
.CloseLocale lea _LocaleBase,a0
tst.l (a0) ; LocaleLib geöffnet ?
beq .CloseIntui
movea.l (a0),a6 ; LocaleBase laden
move.l _li+4,a0 ; a0 = li.li_Catalog
jsr _LVOCloseCatalog(a6)
move.l a6,a1 ; LocaleBase wird geschlossen
move.l 4.w,a6 ; SysBase laden
jsr _LVOCloseLibrary(a6)
.CloseIntui lea _IntuitionBase,a0 ; Prüfen mit (An)
tst.l (a0) ; ist schneller und
beq .EXIT ; kürzer als 2 mal die
move.l (a0),a1 ; absolute Adresse zu benutzen
jsr _LVOCloseLibrary(a6)
.EXIT movem.l (sp)+,d0-d7/a0-a6 ; Register & Stack wiederherstellen
rts
Libs: *LibName, Version, *LibBase, **ErrorText im Fehlerfall
dc.l CxLibName, 37, _CxBase, MSG_NO_CXLIB*4+_ls
dc.l GadToolsLibName, 37, _GadToolsBase, MSG_NO_GADTOOLSLIB*4+_ls
dc.l GfxLibName, 37, _GfxBase, MSG_NO_GFXLIB*4+_ls
dc.l WorkbenchLibName, 37, _WorkbenchBase, MSG_NO_WORKBENCHLIB*4+_ls
dc.l IconLibName, 37, _IconBase, MSG_NO_ICONLIB*4+_ls
dc.l AslLibName, 0, _AslBase, 0
dc.l RexxSysName, 36, _RexxSysBase, MSG_NO_REXXSYSLIB*4+_ls
dc.l SNLibName, 0, _ScreenNotifyBase, 0 ; ( 0 bedeutet daß Library nicht unbedingt geöffnet werden muß)
dc.l 0
CatName: dc.b "ACDPlay.catalog",0
IntuitionLibName: dc.b 'intuition.library',0
MathDoubBasName: dc.b 'mathieeedoubbas.library',0
LocaleLibName: dc.b 'locale.library',0
CxLibName: dc.b 'commodities.library',0
GadToolsLibName: dc.b 'gadtools.library',0
GfxLibName: dc.b 'graphics.library',0
WorkbenchLibName: dc.b 'workbench.library',0
IconLibName: dc.b 'icon.library',0
AslLibName: dc.b 'asl.library',0
RexxSysName: dc.b 'rexxsyslib.library',0
SNLibName: dc.b 'screennotify.library',0
************************* FindARexxPortA ***************************
*
* BOOL FindARexxPortA(void);
*
* Prüft ob schon ein öffentlicher Port 'ACDPLAY' vorhanden ist, sendet
* gegebenenfalls das ARexxkommando 'SHOW' zu diesem Port und gibt TRUE
* zurück, falls der Port nicht ausfindig gemacht werden konnte FALSE.
*
CNOP 0,2
xdef _FindARexxPortA
_FindARexxPortA: movem.l d1-d3/d6-d7/a0-a2/a6,-(sp)
moveq #FALSE,d7 ; Vorgabe: kein Port gefunden
move.l 4.w,a6 ; SysBase laden
lea _ARexxPortName(pc),a2 ; a2=ACDPlayPortName
jsr _LVOForbid(a6) ; damit PatchWork nicht meckert
movea.l a2,a1
jsr _LVOFindPort(a6) ; Port 'ACDPLAY' suchen
move.l d0,d2
jsr _LVOPermit(a6)
tst.l d2 ; gefunden?
beq .EXIT ; nein: Ende
moveq #TRUE,d7 ; Port gefunden
.OpenRexxLib lea RexxSysName(pc),a1 ; rexxsyslib.library
moveq #36,d0 ; Version 36
jsr _LVOOpenLibrary(a6) ; wird für RexxMsg benötigt
move.l d0,d6 ; RexxSysBase->d6
beq .EXIT
.MakeReplyPort jsr _LVOCreateMsgPort(a6) ; ReplyPort erstellen
move.l d0,d3 ; d3=ReplyMsgPort
beq .CloseRexxLib ; nicht genug Speicher...
.PrepareRexxMsg movea.l d6,a6 ; RexxSysBase laden
movea.l d0,a0 ; Replymsgport
suba.l a1,a1 ; Standartextension 'REXX'
move.l a2,d0 ; Portname
jsr _LVOCreateRexxMsg(a6)
move.l d0,d2 ; d2 = a0 = RexxMsg
beq .DeleteMsgPort ; nicht geklappt: Ende
lea name_SHOW(pc),a1
move.l a1,ARG0(a0) ; SHOW-Befehl senden
lea PrivateMsg(pc),a1 ; damit ACDPlay die Msg
move.l a1,LN_NAME(a0) ; identifizieren kann
move.l #RXCOMM|RXFB_NOIO,rm_Action(a0) ; RexxMsg ist ein RX_Kommando/keine IO-Umleitung
moveq #1,d0 ; nur ein Argument
moveq #0,d1 ; alle Argumente sind STRPTRs
jsr _LVOFillRexxMsg(a6) ; Argumente in ArgStrs konvertieren
tst.b d0 ; erfolgreich?
beq .DeleteRexxMsg ; nein: Ende
.SendMsg movea.l 4.w,a6 ; SysBase laden
jsr _LVOForbid(a6) ; Taskswitching abschalten
movea.l a2,a1 ; damit der Port nicht
jsr _LVOFindPort(a6) ; plötzlich verschwindet
tst.l d0
bne .SendIt ; Port überhaupt noch da?
jsr _LVOPermit(a6) ; Multitasking wieder an
bra .ClearRexxMsg ; und Ende
.SendIt movea.l d0,a0 ; gefundener Port
movea.l d2,a1 ; RexxMsg
jsr _LVOPutMsg(a6) ; ab geht die Post :-)
jsr _LVOPermit(a6) ; Kermit?
movea.l d3,a0 ; eigener ReplyPort
jsr _LVOWaitPort(a6) ; auf Reply warten
movea.l d3,a0 ; ReplyPort
jsr _LVOGetMsg(a6) ; es kommt mit Sicherheit nur
; eine Msg an, darum reicht GetMsg
.ClearRexxMsg movea.l d6,a6 ; RexxSysBase wieder laden
movea.l d2,a0 ; RexxMsg
moveq #1,d0 ; einen ArgString freigeben
jsr _LVOClearRexxMsg(a6)
.DeleteRexxMsg movea.l d2,a0 ; RexxMsg
jsr _LVODeleteRexxMsg(a6) ; freigeben
.DeleteMsgPort movea.l 4.w,a6 ; und SysBase wieder laden
movea.l d3,a0 ; eigener ReplyPort
jsr _LVODeleteMsgPort(a6) ; entfernen
.CloseRexxLib movea.l d6,a1 ; RexxSysBase
jsr _LVOCloseLibrary(a6) ; schließen
.EXIT move.l d7,d0 ; Returnwert setzen
movem.l (sp)+,d1-d3/d6-d7/a0-a2/a6
rts
************************* OpenARexxPortA ***************************
*
* struct MsgPort *OpenARexxPortA(void);
*
CNOP 0,2
xdef _OpenARexxPortA
_OpenARexxPortA: movem.l d1/d7/a0-a2/a6,-(sp)
moveq #FALSE,d7 ; Returnwert = FALSE
move.l 4.w,a6 ; SysBase laden
lea _ARexxPortName(pc),a2
jsr _LVOForbid(a6) ; sicherheitshalber...
movea.l a2,a1
jsr _LVOFindPort(a6) ; Port 'ACDPlay' suchen
tst.l d0 ; ACDPlay schon gestartet?
bne .EXIT ; ja: Ende
jsr _LVOCreateMsgPort(a6) ; Port erstellen
move.l d0,d7 ; Returnwert = MsgPort *
beq .EXIT ; oder NULL
movea.l d0,a1
move.l a2,LN_NAME(a1) ; Namen und Priorität (die AddPort sowieso ändert)
move.b #0,LN_PRI(a1) ; des MessagePorts setzen
jsr _LVOAddPort(a6) ; und öffentlich machen
.EXIT jsr _LVOPermit(a6) ; Und die Welt darf sich wieder drehen :-)
move.l d7,d0
movem.l (sp)+,d1/d7/a0-a2/a6
rts
xdef _ARexxPortName
_ARexxPortName: dc.b "ACDPLAY",0
************************* CloseARexxPortA **************************
*
* void CloseARexxPortA(register __a1 struct MsgPort *arexxport);
*
* 'arexxport' : öffentlicher Port oder NULL
*
CNOP 0,2
xdef _CloseARexxPortA
_CloseARexxPortA: movem.l d0-d2/a0-a1/a6,-(sp)
move.l a1,d2 ; arexxport sichern und testen
beq .EXIT
movea.l 4.w,a6 ; SysBase
jsr _LVORemPort(a6) ; Port aus der Public-Liste entfernen
jsr _LVOForbid(a6) ; Taskswitching abschalten
movea.l d2,a0 ; damit uns nach FlushMessages
bsr _FlushMessagesA ; niemand mehr Nachrichten in
movea.l d2,a0 ; den Port legt
jsr _LVODeleteMsgPort(a6) ; MsgPort entfernen
jsr _LVOPermit(a6) ; Multitasking wieder erlauben
.EXIT movem.l (sp)+,d0-d2/a0-a1/a6
rts
************************* ExecuteARexxA ***************************
*
* BOOL ExecuteARexxA(register __a0 char *rexxscript, register __a1 struct MsgPort *rexxport, register __a2 struct Application *app);
*
* Führt das übergebene ARexxmacro "rexxscript" aus. Wurde QUIT empfangen,
* wird QUIT zurückgegeben.
*
CNOP 0,2
xdef _ExecuteARexxA
_ExecuteARexxA: movem.l d1-d7/a0-a6,-(sp)
moveq #FALSE,d7
moveq #0,d5
move.l 4.w,a6 ; SysBase laden
move.l a0,a3 ; a3=Filename
move.l a1,a4 ; a4=eigener ARexxPort
.MakeReplyPort jsr _LVOCreateMsgPort(a6) ; ReplyPort erstellen
move.l d0,d3 ; d3=ReplyMsgPort für
beq .EXIT ; Antwort von REXX
.PrepareRexxMsg movea.l _RexxSysBase,a6 ; RexxSysBase laden
movea.l d0,a0 ; ReplyPort
suba.l a1,a1 ; Standartextension "REXX"
moveq #0,d0 ; Standardport "REXX"
jsr _LVOCreateRexxMsg(a6)
move.l d0,d2 ; d2 = a0 = RexxMsg
beq .KillReplyPort ; nicht geklappt: Ende
move.l a3,ARG0(a0) ; Filename ist 1. Argument
move.l #RXFUNC,rm_Action(a0) ; RexxMsg ist eine RX_Function
moveq #1,d0 ; nur ein Argument
moveq #0,d1 ; alle Argumente sind STRPTRs
jsr _LVOFillRexxMsg(a6) ; Argumente in ArgStrs konvertieren
tst.l d0 ; erfolgreich?
beq .DeleteRexxMsg ; nein: Ende
move.l 4.w,a6 ; SysBase greifen
suba.l a1,a1
jsr _LVOFindTask(a6) ; eigenen Task finden
move.l d0,a0 ; Task wird immer gefunden
tst.l pr_CIS(a0) ; ACDPlay ist ein Process
beq .OpenCON ; Kein Eingabestrom...
tst.l pr_COS(a0)
bne .SendMsg ; Ein- und Ausgabestrom da
.OpenCON move.l _DOSBase,a6 ; DOSBase laden
lea CONName(pc),a0
move.l a0,d1 ; Filename "CON:..."
move.l d2,d4 ; RexxMsg sichern
move.l #MODE_OLDFILE,d2 ; Zugriffsmodus
jsr _LVOOpen(a6)
move.l d0,d5 ; d5=filehandle
beq .doserror ; Fehler...
move.l d4,d2 ; RexxMsg zurück
move.l d4,a0
move.l d0,rm_Stdin(a0) ; Ein- und Ausgabe in
move.l d0,rm_Stdout(a0) ; RexxMsg eintragen
.doserror movea.l 4.w,a6 ; SysBase laden
.SendMsg jsr _LVOForbid(a6) ; Multitasking aus
lea RexxName(pc),a1
jsr _LVOFindPort(a6) ; Port von RexxMast holen
tst.l d0
bne .SendIt ; Port überhaupt noch da?
jsr _LVOPermit(a6) ; Multitasking wieder an
bra .ClearRexxMsg ; und Ende
.SendIt movea.l d0,a0 ; gefundener Port
movea.l d2,a1 ; RexxMsg
jsr _LVOPutMsg(a6) ; ab geht die Post :-)
jsr _LVOPermit(a6) ; Tasks laufen wieder und
; das Macro startet jetzt
.Loop movea.l d3,a0
moveq #0,d1
moveq #1,d0
move.b MP_SIGBIT(a0),d1 ; Signalbit vom ReplyPort
lsl.l d1,d0 ; in Bitmaske wandeln
moveq #1,d4
move.b MP_SIGBIT(a4),d1 ; Signalbit vom ARexxPort
lsl.l d1,d4 ; in Bitmaske wandeln
or.l d4,d0 ; und zusammenodern :-)
jsr _LVOWait(a6) ; auf Message warten
cmp.l d0,d4 ; Message vom Macro (ARexxkommando)?
bne .IsEnd ; nein: warscheinlich vom ReplyPort (Macro zuende)
move.l a4,a0
move.l a2,a1
bsr _HandleARexxMsgA ; ARexxkommando bearbeiten
or.l d0,d7 ; QUIT empfangen?
bra .Loop ; auf ein neues...
.IsEnd movea.l d3,a0 ; ReplyPort
jsr _LVOGetMsg(a6) ; Message holen
tst.l d0 ; wirklich Reply von Rexx?
beq .Loop
.ClearRexxMsg movea.l _RexxSysBase,a6 ; RexxSysBase wieder laden
movea.l d2,a0 ; RexxMsg
moveq #1,d0 ; einen ArgString freigeben
jsr _LVOClearRexxMsg(a6)
move.l d5,d1 ; CON-Filehandle
beq .DeleteRexxMsg ; falls vorhanden...
move.l _DOSBase,a6
jsr _LVOClose(a6) ; ...schließen
move.l _RexxSysBase,a6
.DeleteRexxMsg movea.l d2,a0 ; RexxMsg
jsr _LVODeleteRexxMsg(a6) ; freigeben
.KillReplyPort movea.l 4.w,a6 ; und SysBase wieder laden
movea.l d3,a0 ; eigenen ReplyPort
jsr _LVODeleteMsgPort(a6) ; entfernen
.EXIT move.l d7,d0 ; returnwert setzen
movem.l (sp)+,d1-d7/a0-a6
rts
RexxName: dc.b "REXX",0
CONName: dc.b "CON:0/100/640/140/ACDPlay Output/AUTO/WAIT",0
*********************** HandleARexxMsgA ****************************
*
* BOOL HandleARexxMsgA(register __a0 struct MsgPort *arexxport, register __a1 struct Application *app);
*
* Gibt TRUE zurück wenn QUIT empfangen wurde
*
CNOP 0,2
xdef _HandleARexxMsgA
_HandleARexxMsgA: movem.l d1-d3/d7/a0-a6,-(sp)
moveq #FALSE,d7 ; success=FALSE
move.l 4.w,d3 ; SysBase speichern um
movea.l d3,a6 ; CHIPRam-Zugriffe zu vermeiden
move.l a0,d2 ; MsgPort sichern
movea.l a1,a5 ; Appzeiger sichern
.GetNextMsg movea.l d2,a0
jsr _LVOGetMsg(a6) ; GetMsg(arexxport)
tst.l d0 ; Msg da?
beq .EXIT ; nein: raus hier
movea.l d0,a4 ; a4=Message
.TstMsg movea.l _RexxSysBase,a6 ; RexxSysBase laden
movea.l d0,a0
jsr _LVOIsRexxMsg(a6) ; kommt Msg von ARexx?
tst.b d0
bne .GetFirstToken ; ja: weitermachen
move.l LN_NAME(a4),a0
lea PrivateMsg(pc),a1 ; 4 Bytes reichen für 'ACDP'
cmp.l (a0)+,(a1)+ ; kommt Msg von ACDPlay?
bne .ReplyMsg ; nein: zurückschicken
.GetFirstToken movea.l ARG0(a4),a0 ; ARexxCmd -> a0
jsr _LVOStcToken(a6) ; a1=FirstToken
tst.w d1 ; d1=TokenLenght
beq .ReplyMsg ; leeres Kommando ''
move.l a0,a2 ; a2=Scan (Rest)
lea Commands(pc),a0 ; a0=Schlüsselwörter
lea JmpTable(pc),a3 ; a3=Sprungtabelle
move.l #10,rm_Result1(a4) ; sicherheitshalber RETURN_ERROR :-)
tst.b d0 ; Anführungszeichen vorhanden?
beq .CmpNextCmd ; nein: weiter
subq.w #1,d1 ; TokenLength-1
addq.l #1,a1 ; ' bzw. " übergehen
.CmpNextCmd tst.b (a0) ; weiteres Kommando bekannt?
beq .ReplyMsg ; nein: zurückschicken
move.l d1,d0 ; d1 Zeichen vergleichen
bsr _StrCmpA
tst.b d0 ; Kommando bekannt?
bne .FoundCmd ; ja: Funktion anspringen
.SkipRest tst.b (a0)+ ; nächstes Kommando
bne .SkipRest ; suchen
addq.w #4,a3 ; JmpTableoffset erhöhen
bra .CmpNextCmd ; nächstes vergleichen
.FoundCmd movem.l d1-d6/a0-a4,-(a7) ; Register sichern, damit das Kommando keinen Unsinn macht ;-)
move.l (a3),a3 ; Adresse des Kommandos laden um ...Buttonaufrufe vorzubereiten
move.l a5,-(a7) ; AppStruct auf Stack sichern
move.l 40(a5),a0
move.l 8(a0),a0 ; app->cdstr->cdx nach a0
moveq #0,d0 ; Errorcode vordefinieren
jsr (a3) ; Kommando anspringen
move.l (a7)+,a5
movem.l (a7)+,d1-d6/a0-a4 ; Register zurück
move.l d0,rm_Result1(a4) ; Errorcode in RexxMsg setzen
.ReplyMsg movea.l d3,a6 ; SysBase wieder laden
movea.l a4,a1
jsr _LVOReplyMsg(a6) ; Message zurück
tst.b d7 ; QUIT empfangen?
bne .EXIT ; ja: gleich beenden
bra .GetNextMsg ; und nächste holen
.EXIT move.l d7,d0 ; "done" zurückgeben
movem.l (sp)+,d1-d3/d7/a0-a6
rts
PrivateMsg: dc.b 'ACDP',0
***************************** StrCmpA ******************************
*
* BOOL StrCmpA(register __a0 char *str1, register __a1 char *str2, register __d0 UWORD length);
*
* Vergleicht die Strings str1 und str2 Zeichen für Zeichen bis length oder
* das Ende von str1 erreicht ist oder eine Abweichung erkannt wird. Dabei wird
* nicht zwischen Groß- und Kleinschreibung unterschieden. Die Funktion gibt
* nur dann TRUE zurück, wenn str1 vollständig in str2 enthalten ist.
*
CNOP 0,2
xdef _StrCmpA
_StrCmpA: movem.l d1-d2/d7/a0-a1,-(sp)
moveq #FALSE,d7 ; success=FALSE
subq.w #1,d0 ; dbra geht bis -1, darum jetzt d0--
.GetChar1 move.b (a0)+,d1 ; Byte aus String1 einlesen
cmpi.b #'a',d1 ; und gegebenenfalls
bcs .GetChar2 ; Kleinbuchstaben in Großbuchstaben
cmpi.b #'z',d1 ; wandeln
bhi .GetChar2
bclr #5,d1 ; 'a' <= d1 <= 'z'
.GetChar2 move.b (a1)+,d2 ; s.o.
cmpi.b #'a',d2
bcs .CmpChars
cmpi.b #'z',d2
bhi .CmpChars
bclr #5,d2 ; 'a' <= d2 <= 'z'
.CmpChars cmp.b d1,d2 ; Bytes identisch?
bne .EXIT
dbra d0,.GetChar1 ; wenn ja: weiter bis d0=-1
tst.b (a0) ; Ende von str1 erreicht?
bne .EXIT ; nein: str1 ist nicht in str2
moveq #TRUE,d7 ; sonst: success=TRUE
.EXIT move.l d7,d0 ; return success
movem.l (sp)+,d1-d2/d7/a0-a1
rts
*********************** FlushMessagesA *****************************
*
* void FlushMessagesA(register __a0 struct MsgPort *port);
*
* Leert den MsgPort 'port', der auch NULL sein kann.
*
CNOP 0,2
xdef _FlushMessagesA
_FlushMessagesA: movem.l d0-d2/a0-a1/a6,-(sp)
move.l a0,d2 ; MsgPort sichern und testen
beq .EXIT
move.l 4.w,a6 ; SysBase laden
.loop jsr _LVOGetMsg(a6) ; Msg holen
tst.l d0 ; vorhanden?
beq .EXIT ; nein: Ende
move.l d0,a1
jsr _LVOReplyMsg(a6) ; ja: antworten
movea.l d2,a0 ; MsgPort zurückholen
bra .loop ; nächste Msg holen
.EXIT movem.l (sp)+,d0-d2/a0-a1/a6
rts
*********************** MyGT_SetGadgetAttrs *****************************
*
* void MyGT_SetGadgetAttrs(struct Gadget *gadget, struct Window *window, struct Requester *req, ...);
*
* Prüft 'gadget' und 'window' auf NULL und ruft ggf. GT_SetGadgetAttrsA()
* aus der gadtools.library auf. Diese Funktion basiert auf GT_SetGadgetAttrs()
* aus der amiga.lib.
*
CNOP 0,2
xdef _MyGT_SetGadgetAttrs
_MyGT_SetGadgetAttrs: link a5,#0
movem.l a2-a3/a6,-(sp)
movea.l $0c(a5),d0
beq .EXIT
move.l d0,a1
movea.l $08(a5),d0
beq .EXIT
move.l d0,a0
lea $14(a5),a3
movea.l $10(a5),a2
movea.l _GadToolsBase,a6
jsr _LVOGT_SetGadgetAttrsA(a6)
.EXIT movem.l (sp)+,a2-a3/a6
unlk a5
rts
include "rexxcmds.s"