* ** Startup.Easy v1.1 * ** Author: Jörg van de Loo ** Hövel 15 ** 47559 Kranenburg ** Germany ** ...this material was written using HiSoft's "Devpac Assembler 3". * ** This file is FreeWare (I would say public domain but this gives criminal ** people the right to add "their" copyright remark, so to protect myself from ** excluding of the use of this startup-code, it's FreeWare and I'm the ** copyright holder). ** HiSoft (UK) is it allowed to use/spread/include this file if they like to, ** also in modified form, for free. * ** Date: 5.21.1993 * ** I cannot be held for any failures may happen using this startup-code. ** Unnecessary to tell that you use it at your own risk. * * ** This startup-code is reentrant, so if your code is it too, you may use ** Shell command "Resident". * * ** The BaseTable is only readable! Don't go messing with 'em or weird things ** may happen. * * ** The BaseTable used by this startup-code is 68 bytes large. If you define a ** label called "_TableSize" before you include the startup-code (it's ** important!) then you can specify the bytesize of the table on your own, ** e.g. 1024 bytes. Up from offset 68 you can now store your own datas, ** e.g. _GfxBase. * ** Note: This startup-code offers only 32KB of datas that can be reached - ** BSS relative to A5. * * ** Example: ** * STRUCTURE mytable,68 ; begin at offset 68 * APTR _GfxBase ; offset 68 * APTR _IntuitionBase ; offset 72 * UBYTE _myFlag ; offset 76 * LABEL _TableSize * ; size for "BaseTable" and! "mytable" (here 77 bytes) - * ; automatically allocated when startup-code is executed. * * include include/startup.easy ; insert startup-code * * _main ; this label is the entry point for your code! * .... * .... * ** ** The label "_main" will be called out of the startup-code. There your own ** code has to start. ** When your code returns to the exit-routine, all things allocated/opened by ** the startup-code are freed/closed. * ** The address register where the BaseTable is stored, is the processor ** register A5. Now you can store/read constants out of it, e.g. * * movea.l _DOSBase(A5),A6 ; get base of dos-lib * * ** To exit your code there are different ways. * ** 1. By "RTS" stack must be ok! ** 2. By calling "bsr _exit" no need for corrected stack ** 3. By calling "bra _exit" ditto ** 4. By calling "jsr _exit" ditto ** 5. By calling "jmp _exit" ditto * ** It's not necessary to restore the stack nor to restore the A5 register when ** using exits 2,3,4,5. * * ** This startup-code is a thined version of a startup-code which I use ** normally. Because I wrote a few programs for the PD and I don't want to ** spread my hard worked made startup-code (it's a lot time better than the ** original of Commodore), I wrote this one. * IFND STARTUP_EASY STARTUP_EASY SET 1 * incdir :include/ IFND EXEC_TYPES_I include exec/types.i ENDC IFND EXEC_MEMORY_I include exec/memory.i ENDC IFND EXEC_TASKS_I include exec/tasks.i ENDC IFND EXEC_LIBRARIES_I include exec/libraries.i ENDC IFND CALLEXEC include exec/exec_lib.i ENDC * include exec/execbase.i IFND CALLDOS include dos/dos_lib.i ENDC IFND DOS_DOSEXTENS_I include dos/dosextens.i ENDC IFND WORKBENCH_STARTUP_I include workbench/startup.i ENDC * include workbench/icon_lib.i IFND WORKBENCH_WORKBENCH_I include workbench/workbench.i ENDC IFND AbsExecBase AbsExecBase EQU 4 ENDC IFND ThisTask ThisTask EQU 276 ENDC IFND _LVOGetDiskObject _LVOGetDiskObject EQU -78 ENDC IFND _LVOFreeDiskObject _LVOFreeDiskObject EQU -90 ENDC StoreTableSize MACRO IFND _TableSize move.l #256,D0 ; Default, if nothing is specified ELSE IFLE _TableSize-127 ; If _TableSize < 128 use moveq moveq #_TableSize,D0 ELSE IFLE _TableSize-32767 ; _TableSize not larger than 32KB move.l #_TableSize,D0 ELSE FAIL ; else tell user ENDC ENDC ENDC addq.l #7,D0 ; ...make size divisible andi.l #-8,D0 ; through eight -> for exec's AllocMem()... ENDM * ** This is the BaseTable.... * STRUCTURE BaseTable,0 ; begin at offset NULL APTR bt_Reserved0 ; currently unused - do not use! APTR _SysBase ; pointer to exec-base (readable) ; NOTE: « movea.l _SysBase.w,A6 » still work APTR bt_Reserved1 ; currently unused - do not use! APTR bt_Reserved2 ; currently unused - do not use! APTR _DOSBase ; pointer to dos-base (opened/readable) APTR _IconBase ; pointer to icon-base (readable, may not opened) APTR _argv ; pointer to dos/WB-arguments (readable, may NULL) ULONG _argc ; numbers of dos/WB-arguments (readable, may NULL) APTR _OwnTask ; pointer to own-process-structure (readable) APTR _OwnName ; pointer to own-program-name ; (readable, Shell: with path, WB: name only) ULONG _CmdNameSize ; PRIVATE!!! APTR _WBenchMsg ; pointer to Workbench-message (readable, may NULL) APTR _ToolTypesArray ; pointer to tooltypes (readable, may NULL) APTR _OwnDiskObject ; pointer to own-program-icon-structure (readable, * may NULL) APTR _stdin ; pointer to standard output-handle (readable, * may NULL) APTR _stdout ; pointer to standard input-handle (readable, * may NULL) ULONG _errno ; place into this constant the returncode of * your program LABEL bt_SIZEOF ; size of this table: 68 bytes - next free offset: 68! * ** Where "may NULL" stands it's possible that this values are not initialized ** if running from Workbench or when running from Shell. * * Examples: The WBenchMsg will be NULL if running under Shell. * The stdin or stdout will be NULL when running from Workbench. * So watch out! _startup movem.l D0/A0,-(sp) move.l AbsExecBase.w,A6 StoreTableSize ; MACRO - bytesize of "_TableSize" move.l #MEMF_PUBLIC|MEMF_CLEAR,D1 jsr _LVOAllocMem(A6) ; Allocate BaseTable and user's BSS tst.l D0 beq.w __noTable movea.l D0,A5 ; Pointer to BaseTable into A5 move.l A6,_SysBase(A5) move.l (sp)+,_argc(A5) ; Number of chars in commandline move.l (sp)+,_argv(A5) ; Address commandline (if Shell) move.l A5,-(sp) ; Save BaseTable right in front * of ReturnAddr of task cmpi.w #32,LIB_VERSION(A6) ; Say: I need at least kickstart 1.2 bls.w __fastout lea _DOSName(pc),A1 moveq #0,D0 ; Say: any version up from Kickstart 1.2 jsr _LVOOpenLibrary(A6) move.l D0,_DOSBase(A5) beq.w __fastout ; ...only for savety... sub.l A1,A1 jsr _LVOFindTask(A6) move.l D0,_OwnTask(A5) ; Pointer to process-structure movea.l D0,A2 tst.l pr_CLI(A2) ; Are we called from CLI or WBench? bne.s .fromDOS * ...it was Workbench lea pr_MsgPort(A2),A0 jsr _LVOWaitPort(A6) ; Wait for WB-message lea pr_MsgPort(A2),A0 jsr _LVOGetMsg(A6) ; Get message move.l D0,_WBenchMsg(A5) ; and save message for later movea.l D0,A0 ; Message move.l sm_NumArgs(A0),_argc(A5) ; Number of files move.l sm_ArgList(A0),_argv(A5) ; Array of locks and files lea _IconName(pc),A1 moveq #33,D0 jsr _LVOOpenLibrary(A6) ; Open Icon-library move.l D0,_IconBase(A5) beq.s .skipToolTypes tst.l _argv(A5) ; Array empty? beq.s .skipToolTypes movea.l _argv(A5),A0 ; Array of: * lock[0],file[0], lock[1],file[1], lock[2],file[2] and so on move.l (A0),D1 ; wa_Lock(A0),D1 (home-lock) beq.s .skipLock movea.l _DOSBase(A5),A6 jsr _LVOCurrentDir(A6) ; Change directory to PROGDIR tst.l D0 bmi.s .skipToolTypes .skipLock movea.l _IconBase(A5),A6 movea.l _argv(A5),A0 movea.l wa_Name(A0),A0 ; Our name... move.l A0,_OwnName(A5) ; Remember name of prg jsr _LVOGetDiskObject(A6) ; Read program-icon tst.l D0 beq.s .skipToolTypes move.l D0,_OwnDiskObject(A5) ; Remember icon-structure of our prg movea.l D0,A0 move.l do_ToolTypes(A0),_ToolTypesArray(A5) .skipToolTypes bra.s __main * ...Shell start... .fromDOS movea.l _DOSBase(A5),A6 jsr _LVOInput(A6) move.l D0,_stdin(A5) jsr _LVOOutput(A6) move.l D0,_stdout(A5) movea.l _OwnTask(A5),A0 movea.l pr_CLI(A0),A0 adda.l A0,A0 adda.l A0,A0 movea.l cli_CommandName(A0),A2 ; BSTR to our prg-name adda.l A2,A2 adda.l A2,A2 ; APTR moveq #0,D2 move.b (A2)+,D2 ; Get length of our name move.l #103,_errno(A5) ; Setup possible error move.l D2,D0 ; Length addq.w #8,D0 ; plus 1 byte (NULL-byte) plus 7 & andi.w #-8,D0 ; "and" with -8 = make length divisible through 8 move.l D0,_CmdNameSize(A5) ; Remember size for later move.l #MEMF_PUBLIC|MEMF_CLEAR,D1 movea.l _SysBase(A5),A6 jsr _LVOAllocMem(A6) ; Allocate name-buffer move.l D0,_OwnName(A5) ; Save pointer to name-buffer beq.s __closeAndFree clr.l _errno(A5) ; Tell: no error occurred movea.l D0,A0 ; Name-buffer bra.s .doIt ; Because of DBF .StoreName move.b (A2)+,(A0)+ ; Copy CMD-name into own buffer .doIt dbf D2,.StoreName clr.b (A0) ; Not needed.... __main move.l _SysBase(A5),A6 bsr.w _main ; Call user's code with: * ·A5 BaseTable, A6 SysBase· _exit movea.l AbsExecBase.w,A6 ; Execbase suba.l A1,A1 ; 0 = own task (process) jsr _LVOFindTask(A6) ; Find our process movea.l D0,A0 ; Pointer to A0 movea.l pr_ReturnAddr(A0),A0 ; Program's exit address subq.l #8,A0 move.l A0,sp ; Correct Stackpointer move.l (sp)+,A5 ; Place basetable pointer in A5 * and make a "RTS" using right address tst.l _WBenchMsg(A5) beq.s .fromDOS tst.l _IconBase(A5) beq.s .ReplyMsg tst.l _OwnDiskObject(A5) beq.s .ReplyMsg movea.l _OwnDiskObject(A5),A0 movea.l _IconBase(A5),A6 jsr _LVOFreeDiskObject(A6) .ReplyMsg movea.l _SysBase(A5),A6 tst.l _IconBase(A5) beq.s .skipIt movea.l _IconBase(A5),A1 jsr _LVOCloseLibrary(A6) .skipIt jsr _LVOForbid(A6) movea.l _WBenchMsg(A5),A1 jsr _LVOReplyMsg(A6) bra.s __closeAndFree .fromDOS movea.l _SysBase(A5),A6 move.l _CmdNameSize(A5),D0 movea.l _OwnName(A5),A1 jsr _LVOFreeMem(A6) __closeAndFree move.l _errno(A5),D2 movea.l _DOSBase(A5),A1 movea.l _SysBase(A5),A6 jsr _LVOCloseLibrary(A6) movea.l _OwnTask(A5),A2 movea.l A5,A1 StoreTableSize jsr _LVOFreeMem(A6) move.l D2,D0 move.l D0,pr_Result2(A2) ; Back to Shell/WB with returncode in D0 rts ; and a valid Result2 constant... * ------------------------------------- * __noTable addq.w #8,sp moveq #103,D0 move.l ThisTask(A6),A0 move.l D0,pr_Result2(A0) rts __fastout movea.l A5,A1 StoreTableSize jsr _LVOFreeMem(A6) moveq #121,D0 move.l ThisTask(A6),A0 move.l D0,pr_Result2(A0) rts _DOSName dc.b 'dos.library',0 _IconName dc.b 'icon.library',0 CNOP 0,4 ENDC * ------------------------------------- *