***************************************************************************** ** ** ** Startup20 - Startup-Code für Workbench und CLI ab Kickstart 2.0 ** ** ** ** by Christian A. Weber, Zürich/Switzwerland ** ** ** ***************************************************************************** ** ** ** Universeller Startup-Code für CLI und WorkBench. ** ** library (DOSBase), schreibt Adresse unseres Tasks nach 'Process- ** ** Falls wir von der WorkBench gestartet wurden, wird die StartupMessage ** ** abgeholt und auf unser Directory ein CurrentDir() gemacht. ** ** Unter Kickstart 1.3 wird ein Requester ausgegeben und das Programm ** ** beendet. ** ** Bei ArgsStartup20.o und DetachArgsStartup20.o wird die CLI-Zeile ** ** mittels ReadArgs() geparst. ** ** ** ***************************************************************************** ** ** ** Folgende Variablen werden zur Verfügung gestellt: ** ** ** ** _SysBase - Zeiger auf Exec library base ** ** _DOSBase - Zeiger auf DOS library base ** ** _ProcessBase - Zeiger auf unseren Prozess ** ** _CommandName - Zeiger auf Kommando-Namen (Null-terminated) ** ** _geta4 - Routine zum Laden von A4 auf den Datenbereich ** ** ** ** ** ** Folgende Variablen werden referenziert: ** ** ** ** @Main - Hauptprogramm, erhält folgende Registerwerte: ** ** A0 = Argument-Zeile, D0 = Länge der Argumentzeile ** ** A0 = WB-StartupMsg, D0 = 0 (bei Workbench-Start) ** ** _StdWindowName - Window für WB-Start, z.b. "NIL:" oder "CON:blabla" ** ** ** ** _STACKSIZE - Größe des Stacks in Bytes für Detach startups ** ** ** ** ** ** bei ArgsStartup20 und DetachArgsStartup zusätzlich benötigt: ** ** ** ** _CLI_Template - Das Template für ReadArgs(), z.b. "NAME/A,DELAY/N" ** ** _argv - Genug Platz für alle Argumente (1 Long pro arg) ** ** ** ** ** ** Das Programm kann durch RTS beendet werden (ReturnCode in D0) oder ** ** mittels der Routinen '@Exit' oder '@exit' (ReturnCode in D0). ** ** ** ***************************************************************************** ** ** ** Es existieren zur Zeit 5 verschiedene Versionen: ** ** ** ** Startup20.o - Standard Startup-Code ** ** DetachStartup20.o - Hängt sich vom CLI ab ** ** ArgsStartup20.o - Standard Startup-Code, mit ReadArgs() ** ** ArgsDetachStartup20.o - Hängt sich vom CLI ab, mit ReadArgs() ** ** ** ***************************************************************************** ** ** ** Modification History ** ** -------------------- ** ** ** ** 01-Jul-91 CHW Created this file from Startup.S ** ** 02-Jul-91 CHW Detach bug fixed ** ** 16-Jul-91 CHW ReadArgs() implemented ** ** 05-Apr-92 CHW Genam statt asm, Änderungen von Startup.S V4.4 ** ** 28-May-93 CHW TINY Version gibt's nicht mehr V4.5 ** ** ** ***************************************************************************** IDNT Startup20 SECTION text,CODE INCLUDE "exec/types.i" INCLUDE "exec/macros.i" INCLUDE "exec/execbase.i" INCLUDE "dos/dosextens.i" INCLUDE "dos/dostags.i" INCLUDE "workbench/startup.i" ARGS ***************************************************************************** ** Referenzen XREF @Main ; Hauptprogramm, das aufgerufen wird XREF _LinkerDB ; Start des Datenbereichs XREF __BSSBAS ; Start des __MERGED BSS-Bereichs XREF __BSSLEN ; Länge in LONGS des __MERGED BSS-Bereichs IFD DETACH XREF _STACKSIZE ; Gröss des Stapels ENDC XREF _StdWindowName ; Workbench-Window-Name, z.B. "NIL:" IFD ARGS XREF _CLI_Template ; Template-String für ReadArgs() XREF _argv ; Ziel-Array für ReadArgs() ENDC ***************************************************************************** ** Definitionen XDEF _geta4 ; A4 holen für Small Data XDEF @exit,@Exit ; Fehler-Ausgang XDEF _SysBase XDEF _DOSBase XDEF _ProcessBase ; Zeiger auf unseren Prozess XDEF _CommandName ; Name unter dem das Prg gestartet wurde ***************************************************************************** ** Einsprung FirstByte: bra.b _WbStartup dc.b "CHW",0 ; Für mein Ego :-) dc.b "4.5",20 ; Startup-Version DOSName: dc.b "dos.library",0 *** A4 holen, BSS-Bereich löschen, D0/A0/SP retten _WbStartup: bsr _geta4 lea __BSSBAS(a4),a3 ; get base of BSS move.l #__BSSLEN,d3 ; get length of BSS in longwords bra.b .ClearDBF ; and clear for length given .ClearLoop: clr.l (a3)+ .ClearDBF: dbf d3,.ClearLoop movem.l d0/a0/a7,InitRegs(a4) *** ExecBase(A6), ThisTask(A3) und CLI(A2) holen movea.l (4).W,a6 ; A6: SysBase move.l a6,_SysBase(a4) movea.l ThisTask(a6),a3 ; A3: Task/Process pointer move.l pr_CLI(a3),d0 lsl.l #2,d0 ; BPTR to APTR movea.l d0,a2 ; A2: CLI oder NULL *** Command-Name von BCPL nach CSTR konvertieren nach _CommandName GetCmdName: moveq.l #-1,d0 ; -1 für DBF lea _CommandName(a4),a1 ; Destination movea.l LN_NAME(a3),a0 ; Default: Prozessname move.l a2,d1 ; Vom CLI aufgerufen ? beq.b 1$ ; nein ---> move.l cli_CommandName(a2),d1 ; PrgName holen beq.b 3$ ; kein Name ---> lsl.l #2,d1 ; BSTR to APTR movea.l d1,a0 add.b (a0)+,d0 ; Länge des Strings -1 1$: move.b (a0)+,(a1)+ ; D0+1 bytes kopieren 2$: dbeq d0,1$ ; Nicht '\0' ---> Loop 3$: *** DOS library öffnen, Test ob Kick 2.x lea DOSName(PC),a1 JSRLIB OldOpenLibrary ; DOS-Bibliothek öffnen movea.l d0,a6 ; A6 : DOSBase move.l a6,_DOSBase(a4) ; und in _DOSBase speichern cmpi.w #37,LIB_VERSION(a6) ; Laufen wir unter >= 2.04 ? bcc.b .KickOK ; ja ---> *** Wir laufen unter < 2.x: Requester ausgeben und RTS lea _CommandName(a4),a0 move.l a0,d1 ; Source-APTR moveq.l #40,d2 ; Destination-BSTR add.l d1,d2 lsr.l #2,d2 ; BSTR moveq.l #-31,d0 ; GV: String -> BSTR jsr -28(a6) ; Gibt BSTR in D1 lea Kick20Text(a4),a0 ; "requires Kickstart 2.x" move.l a0,d2 lsr.l #2,d2 ; APTR -> BPTR moveq.l #0,d3 ; Textzeile 2 moveq.l #$34,d0 ; AutoRequest-GV-Nummer jmp -28(a6) ; GV-Routine ausführen, RTS .KickOK: *** Verzweigung WorkBench/CLI move.l a2,d0 ; Vom CLI aufgerufen ? beq.b FromWorkBench ; nein ---> ***************** ***************************************************** ** Start vom CLI *** Falls erwünscht CLI-Args parsen IFD ARGS lea _CLI_Template(a4),a0 move.l a0,d1 lea _argv(a4),a0 move.l a0,d2 moveq.l #0,d3 ; No user-supplied struct RDArgs * JSRLIB ReadArgs move.l d0,RDArgs(a4) bne.b .RdArgsOK ; OK ---> JSRLIB IoErr move.l d0,d1 ; Fault value lea _CommandName(a4),a0 move.l a0,d2 ; Header for PrintFault() JSRLIB PrintFault ; Error-Grund ausgeben moveq.l #RETURN_FAIL,d0 ; Return-Code bra @Exit ; Error ---> .RdArgsOK: ENDC *** Falls erwünscht detachen IFD DETACH move.l cli_Module(a2),CliSegList(a4) ; SegList retten clr.l cli_Module(a2) ; für CLI löschen *** Prozess erzeugen und zurück zum CLI lea NewProcTags(a4),a0 move.l a0,d1 ; TagItems für CreateNewProc() ;; move.l pr_StackSize(a3),d0 ; StackSize ;; lsl.l #2,d0 ; hmm, ist scheinbar in LONGs ;; move.l d0,20(a0) ; in TagArray eintragen move.l InitialA0(a4),28(a0) ; Commandline eintragen JSRLIB CreateNewProc ; Neuen prozess starten moveq.l #0,d0 ; Return-Code rts ; Zum CLI zurück ELSE ; nicht DETACH bra.b StartMain ; ---> ENDC ***************************************************************************** ** Einsprung des neuen Prozesses von CreateNewProc() IFD DETACH NewProcEntry: bsr.b _geta4 move.l SP,InitialSP(a4) movea.l _SysBase(a4),a6 movea.l ThisTask(a6),a3 ; Neue ProcessBase holen movea.l _DOSBase(a4),a6 ; jaja bra.b Windy ; ---> ENDC ***************************************************************************** ** Register A4 holen für small data _geta4: lea _LinkerDB,a4 rts ***************************************************************************** ** Start von der Werkbank FromWorkBench: movea.l _SysBase(a4),a6 lea pr_MsgPort(a3),a0 JSRLIB WaitPort lea pr_MsgPort(a3),a0 JSRLIB GetMsg move.l d0,WBenchMsg(a4) clr.l InitialD0(a4) ; D0 : Null move.l d0,InitialA0(a4) ; A0 : WBStartup-Message movea.l d0,a0 ; Workbench Startup Message movea.l sm_ArgList(a0),a0 ; erstes Argument: wir selbst! move.l wa_Lock(a0),d1 ; Lock unseres Directories movea.l _DOSBase(a4),a6 JSRLIB CurrentDir ; als Current Dir setzen Windy: move.l #_StdWindowName,d1 ; Zu öffnendes Dos-Fenster move.l #MODE_OLDFILE,d2 JSRLIB Open ; Window öffnen move.l d0,OurWindow(a4) ; für Exit() move.l d0,pr_CIS(a3) ; für Input() move.l d0,pr_COS(a3) ; für Output() move.l d0,pr_CES(a3) ; Error-Stream lsl.l #2,d0 ; BPTR to APTR movea.l d0,a0 move.l fh_Type(a0),pr_ConsoleTask(a3) ; für Open("CONSOLE:",mode); **************** ***************************************************** ** Hauptprogramm starten StartMain: move.l a3,_ProcessBase(a4) ; für die Aussenwelt movem.l InitRegs(a4),d0/a0 lea -128(SP),SP ;; $$$$ DEBUG jsr @Main(PC) ; PROGRAMM AUSFÜHREN! *** Programm-Terminierung durch Exit(val) oder return(val) @exit: @Exit: bsr.b _geta4 IFND DETACH move.l d0,d7 ; return-code retten ENDC movea.l InitialSP(a4),SP ; Stackpointer restaurieren movea.l _DOSBase(a4),a6 move.l OurWindow(a4),d1 ; Fenster oder 0 beq.b 1$ JSRLIB Close ; Fenster schliessen 1$: IFD ARGS move.l RDArgs(a4),d1 beq.b 2$ JSRLIB FreeArgs 2$: ENDC movea.l _SysBase(a4),a6 move.l WBenchMsg(a4),d2 ; gibt's was zu beantworten? beq.b 3$ ; nein, CLI ---> JSRLIB Forbid ; sonst werden wir 'entladen' ! movea.l d2,a1 JSRLIB ReplyMsg IFD DETACH bra.b QuitnDie ; ---> raus! ENDC 3$: **************** ***************************************************** * Uns selber freigeben falls degetacht (CLI) IFD DETACH movea.l _DOSBase(a4),a6 move.l CliSegList(a4),d1 ; Uns selbst JMPLIB UnLoadSeg ; freigeben * NOT REACHED ENDC **************** ***************************************************** ** Returncode von D7 holen und Programm beenden QuitnDie: move.l d7,d0 ; return-code rts ; ZURÜCK ZUM DOS! ***************************************************************************** SECTION __MERGED,DATA ; Anscheinend darf die Data-Size im __MERGED-Segment nicht 0 sein, sonst ; erzeugt der Linker einen BSS-Hunk mit Länge 0 im Hunk und Länge 20 im ; Header (?!) _DOSBase: ds.l 1 ; wird hier geöffnet & geschlossen CNOP 0,4 Kick20Text: dc.b 19,"needs Kickstart 2.x!",0 ; BSTR (EVEN LENGTH!) IFD DETACH NewProcTags: dc.l NP_Entry,NewProcEntry ; 0 4 dc.l NP_Name,_CommandName ; 8 12 dc.l NP_StackSize,_STACKSIZE ; 16 20 dc.l NP_Arguments,0 ; 24 28:Will be patched dc.l NP_Input,OurWindow dc.l NP_Output,OurWindow dc.l NP_Error,OurWindow dc.l NP_CloseInput,0 dc.l NP_CloseOutput,0 dc.l NP_CloseError,0 dc.l TAG_DONE ENDC SECTION __MERGED,BSS _SysBase: ds.l 1 _ProcessBase: ds.l 1 ; Address of this process WBenchMsg: ds.l 1 ; Startup-Message oder NULL OurWindow: ds.l 1 ; Zeiger auf unser Window oder NULL IFD ARGS RDArgs: ds.l 1 ; Zeiger auf RDArgs-Struktur ENDC InitRegs: ; Die 3 geretteten Register D0/A0/SP: InitialD0: ds.l 1 InitialA0: ds.l 1 InitialSP: ds.l 1 IFD DETACH CliSegList: ds.l 1 ; Unsere Segmentliste ENDC _CommandName: ds.b 80 END