head    1.6;
access;
symbols;
locks
        simons:1.6; strict;
comment @ * @;


1.6
date    93.09.14.23.13.22;      author simons;  state Stab;
branches;
next    1.5;

1.5
date    93.09.14.22.24.41;      author simons;  state Exp;
branches;
next    1.4;

1.4
date    93.09.14.22.16.07;      author simons;  state Exp;
branches;
next    1.3;

1.3
date    93.09.14.21.58.36;      author simons;  state Exp;
branches;
next    1.2;

1.2
date    93.09.14.20.20.03;      author simons;  state Exp;
branches;
next    1.1;

1.1
date    93.09.14.20.18.32;      author simons;  state Exp;
branches;
next    ;


desc
@This is a replacement for the standard startup module, usually
linked to C programs. This one is modified to fit better with
my _main().
@


1.6
log
@Startup code crashed the machine when the command was started without
parameters.
@
text
@**
**      $Filename: c.asm $
**      $Revision: 1.5 $
**      $Date: 1993/09/14 22:24:41 $
**
**      This is a replacement for the standard startup module, usually
**      linked to C programs. This one is modified to fit better with
**      my _main().
**
**      © Copyright 1993 Peter Simons, Germany
**        All Rights Reserved
**
**      $Id: c.asm,v 1.5 1993/09/14 22:24:41 simons Exp simons $
**
** ------------------------------ log history -----------------------------
** $Log: c.asm,v $
** Revision 1.5  1993/09/14  22:24:41  simons
** Deleted some Workbench related code to make the startup more efficient.
**
** Revision 1.4  1993/09/14  22:16:07  simons
** If started from Workbench, the startup-code returns immediatly.
**
** Revision 1.3  1993/09/14  21:58:36  simons
** The pseudo opcode EVEN is unknown to asm, replaced it.
** Changed the line-parameter for _main() to the shell commandline
** without programname and the terminating return, for usage with my
** modified __main().
**
** Revision 1.2  1993/09/14  20:20:03  simons
** Added RCSId string.
**
** Revision 1.1  1993/09/14  20:18:32  simons
** Initial revision
**
** --------------------------------- flags --------------------------------
** Use the following command line to make c.o
** asm -u -isc:Assembler_Include/ c.a
**
** Use the following command line to make cres.o
** asm -u -isc:Assembler_Include/ -dRESIDENT -ocres.o c.a
**
** Use the following command line to make catch.o (standard GURU catcher)
** asm -u -isc:Assembler_Include/ -dCATCH -ocatch.o c.a
**
** Use the following command line to make catchnr.o (GURU catcher w/out requester)
** asm -u -isc:Assembler_Include/ -dCATCH -dNOREQ -ocatchnr.o c.a
**
** Use the following command line to make catchres.o (resident GURU catcher)
** asm -u -isc:Assembler_Include/ -dCATCH -dRESIDENT -ocatchres.o c.a
**
** Use the following command line to make catchresnr.o (resi GURU catcher w/out req)
** asm -u -isc:Assembler_Include/ -dCATCH -dRESIDENT -dNOREQ -ocatchresnr.o c.a
**

        IFD  CATCH
          IFND NOREQ
AUTOREQ         set        1
          ENDC
        ENDC

        INCLUDE        "exec/types.i"
        INCLUDE        "exec/alerts.i"
        INCLUDE        "exec/nodes.i"
        INCLUDE        "exec/lists.i"
        INCLUDE        "exec/ports.i"
        INCLUDE        "exec/libraries.i"
        INCLUDE        "exec/tasks.i"
        INCLUDE        "exec/memory.i"
        INCLUDE        "exec/execbase.i"
        INCLUDE        "libraries/dos.i"
        INCLUDE        "libraries/dosextens.i"
        INCLUDE        "workbench/startup.i"
        INCLUDE        "Offsets.i"

        IFD   CATCH
        INCLUDE        "intuition/intuition.i"
VERSION  equ    1
REVISION equ    0
        ENDC

MEMFLAGS        EQU        MEMF_CLEAR+MEMF_PUBLIC
AbsExecBase     EQU        4

;;;
;;;   Stack map.
;;;
      OFFSET  0
           ds.b    4
savereg    ds.b    13*4
stackbtm   ds.b    4



; some usefull macros:

callsys macro
        CALLLIB _LVO\1
        endm

        xdef        _XCEXIT                * exit(code) is standard way to leave C.
        xdef        @@_XCEXIT

        xref        LinkerDB        * linker defined base value
        xref        _BSSBAS                * linker defined base of BSS
        xref        _BSSLEN                * linker defined length of BSS
        xref        __stack

       IFD          RESIDENT
        xref        RESLEN
        xref        RESBASE
        xref        NEWDATAL
       ENDC

*       library references

        section text,code

        xref    __main                  * Name of C program to start with.
        xref    _MemCleanup             * Free all allocated memory
        xref    __fpinit                * initialize floating point
        xref    __fpterm                * terminate floating point

start:
        movem.l d1-d6/a0-a6,-(a7)       * save registers

        move.l  a0,a2                   * save command pointer
        move.l  d0,d2                   * and command length
        lea     LinkerDB,a4             * load base register
        move.l  AbsExecBase.W,a6

*---------- check if started from CLI
                move.l  ThisTask(a6),A3
                tst.l   pr_CLI(A3)
                bne.s   fromcli
                movem.l (SP)+,d1-d6/a0-a6
                rts
fromcli:

        IFND        RESIDENT
        lea     _BSSBAS,a3              * get base of BSS
        moveq   #0,d1
        move.l  #_BSSLEN,d0             * get length of BSS in longwords
        bra.s   clr_lp                  * and clear for length given
clr_bss move.l  d1,(a3)+
clr_lp  dbf     d0,clr_bss
        move.l  a7,_StackPtr(A4)        * Save stack ptr
        move.l  a6,SysBase(A4)

*------ get the size of the stack, if CLI use cli_DefaultStack
        move.l        ThisTask(a6),A3
        move.l        pr_CLI(A3),d0
        lsl.l         #2,d0
        move.l        d0,a0
        move.l        cli_DefaultStack(a0),d0
        lsl.l         #2,d0              * # longwords -> # bytes

*------ Set __base for stack checking
        move.l       a7,d1
        sub.l        d0,d1               * get top of stack
        add.l        #128,D1             * allow for parms overflow
        move.l       D1,__base(A4)       * save for stack checking

        cmp.l         __stack(a4),d0
        bcc.s        nochange

*-- current stack is not as big as __stack says it needs
*-- to be. Allocate a new one.
        move.l        __stack(a4),d0
        add.l         #128,d0           * extra room
        move.l        d0,newstacksize(a4)

        move.l        #MEMFLAGS,d1
        callsys       AllocMem
        tst.l         d0
        beq.w         return

        move.l        d0,newstack(a4)
        add.l         #128,d0           * extra room
        move.l        d0,__base(a4)

        add.l         __stack(a4),d0
        move.l        d0,a7

nochange:
        ENDC



        IFD        RESIDENT
        move.l        d2,-(a7)
        movem.l       a0-a2,-(a7)

*------ get the size of the stack, if CLI use cli_DefaultStack
        move.l        ThisTask(a6),A3
        move.l        pr_CLI(A3),d1
        lsl.l         #2,d1
        move.l        d1,a0
        move.l        cli_DefaultStack(a0),d1
        lsl.l         #2,d1             * # longwords -> # bytes
        moveq        #0,d2              * use d2 as flag for newstack or not
        move.l       #RESLEN,d0
        cmp.l        __stack(a4),d1     * This a4 is in the original
                                        * set of data
        bcc.s        nochange
        move.l        __stack(a4),d1
        add.l        d1,d0              * increase size of mem for new stack
        moveq        #1,d2              * set flag

nochange:
        move.l        d1,a3             * save stacksize to set up stack checking
        move.l        #MEMFLAGS,d1
        callsys       AllocMem
        tst.l         d0
        bne.s         ok1
        movem.l       (a7)+,d2/a0-a2
        bra.w         return

ok1:    move.l        d0,a0
        move.l        d0,a2             * a2 now has difference

        move.l        d0,a1
        move.l        #NEWDATAL,d0
        sub.l         #RESBASE,a4

                                        * copy data over
cpy:    move.l        (a4)+,(a0)+
        subq.l        #1,d0
        bne.s         cpy

                                        * a4 now points at number of relocs
        move.l        (a4)+,d0
reloc:  beq.s         nreloc
        move.l        a1,a0
        add.l         (a4)+,a0          * a0 now has add of reloc
        add.l         (a0),a2
        move.l        a2,(a0)
        move.l        a1,a2             * restore offset
        subq.l        #1,d0
        bra.s         reloc

nreloc: move.l        a1,a4             * set up new base register
        add.l         #RESBASE,a4

        move.l        #RESLEN,realdatasize(a4)
        movem.l       (a7)+,a0-a2

        move.l        a6,SysBase(A4)
        tst.b         d2
        movem.l       (a7)+,d2          * restore d2
        movem.l       a7,_StackPtr(A4)  * Save stack ptr (movem doesn't
                                        * change flags
        beq.s         nochg2

*------ set up new stack
        move.l       a4,d0
        sub.l        #RESBASE,d0
        add.l        #RESLEN,d0
        add.l        __stack(a4),d0     * here a4 will be pointing at the
                                        * new data, but __stack will be the
                                        * same if all goes well
        sub.l        #128,d0            * 128 down for good measure
        move.l       d0,a7
        move.l       __stack(a4),d0
        move.l       d0,4(a7)            * fill in size of new stack
        add.l        d0,realdatasize(a4) * need to know how much to free later

nochg2:
*------ Set __base for stack checking
        move.l       a7,d1
        sub.l        a3,d1               * get top of stack
        add.l        #128,D1             * allow for parms overflow
        move.l       D1,__base(A4)       * save for stack checking

        ENDC



        ifd     CATCH
        move.w  AttnFlags(a6),Environment+2(a4) * save copy for dump
        endc



clrwb:
        clr.l        _WBenchMsg(A4)

*-----  clear any pending signals
        moveq         #0,d0
        move.l        #$00003000,d1
        callsys       SetSignal


        move.l        ThisTask(a6),A3

        ifd        CATCH
        move.l        A3,TaskID(a4)

*------ initialize exception handler
*------ Remember to preserve the old handler first
        move.l        TC_TRAPDATA(a3),oldtrapdata(A4)
        move.l        TC_TRAPCODE(a3),d0              ; check current exception
        move.l        d0,oldtrapcode(A4)

        move.l        d0,a1
        callsys TypeOfMem
        tst.l d0
        bne.s        1$                               * somebody else (debugger?) has vector

        move.l        #Exception,TC_TRAPCODE(a3)      * install pointers to code
        move.l        a4,TC_TRAPDATA(a3)              * ...and data
1$:
        ifd         AUTOREQ
*------ attempt to open Intuition library:
        bsr.w                openIntui
        endc
        endc


*------ attempt to open DOS library:
        lea           DOSName(PC),A1
        moveq.l       #0,D0
        callsys       OpenLibrary
        move.l        D0,DOSBase(A4)
        bne.s         ok2
        moveq.l       #100,d0
        bra.w         exit2

ok2:

        move.l        pr_CurrentDir(A3),__curdir(A4)

*=======================================================================
*====== CLI Startup Code ===============================================
*=======================================================================
*
* Entry: D2 = command length
*        A2 = Command pointer
fromCLI:
        ifd        CATCH
        moveq         #-1,d0
        move.l        d0,Starter(a4)        * non-zero means CLI
        move.l        a5,StackTop(a4)
        endc

*------ find command name:
        move.l      pr_CLI(a3),a0
        add.l       a0,a0                   * bcpl pointer conversion
        add.l       a0,a0
        move.l      cli_CommandName(a0),a1

        IFD         CATCH
        IFND        AUTOREQ
        move.l      cli_StandardOutput(a0),GConsole(a4)   * save output fh
        ENDC
        ENDC

        add.l       a1,a1                   * bcpl pointer conversion
        add.l       a1,a1

*------ collect parameters:
        move.l      d2,d0                   * get command line length
        moveq.l     #0,d1
        move.b      (a1)+,d1
        move.l      a1,_ProgramName(A4)
        add.l       d1,d0                   * add length of command name
        addq.l      #7,d0                   * allow for space after command, quotes
                                            * and null terminator, as well as
        andi.w      #$fffc,D0               * force to long word boundary
        move.l      d0,Commandlen(a4)

        movem.l d1/a1,-(a7)
        move.l      #MEMFLAGS,d1
        callsys     AllocMem
        movem.l     (a7)+,d1/a1
        tst.l       d0
        bne.s       ok_copy

        move.l      #1000,d0                * what should the return code be for out of mem?
        move.l      d0,-(a7)                * put a return code on the stack
        beq.w       nodofree                * Was exitToDOS

ok_copy:
        move.l      d0,a0
        move.l      d0,Commandbuf(a4)

*------ copy command line into memory
                move.l  a0,a1
                subq.w  #2,d2
                bmi.b   no_cmd_line
copy_line:      move.b  (a2)+,(a1)+
                dbra    d2,copy_line
no_cmd_line:    clr.b   (a1)+
                pea     (a0)

*=============================================
*------ common code --------
*=============================================

main    jsr        __fpinit(PC)              * Initialize floating point
        jsr        __main(PC)                * call C entrypoint
        moveq.l    #0,d0                     * set successful status
        bra.s      exit2
*

XCEXIT:
_XCEXIT:
        move.l     4(SP),d0                  * extract return code
@@XCEXIT:
@@_XCEXIT:
exit2:
        movea.l    _StackPtr(a4),a7          * restore stack ptr
        move.l     d0,-(a7)
        move.l     _ONEXIT(A4),d0            * exit trap function?
        beq.s      exit3
        move.l     d0,a0
        jsr        (a0)
exit3:
        jsr        __fpterm(PC)              * clean up any floating point
        jsr        _MemCleanup(PC)           * cleanup leftover memory alloc.

        ifnd       RESIDENT
*------ free the stack if we allocated one
        move.l     newstacksize(a4),d0
        beq.s      exit4
        move.l     newstack(a4),a1
        move.l     AbsExecBase.W,A6
        callsys    FreeMem
        endc

exit4:
exitToDOS:
        move.l     AbsExecBase.W,a6

*------ Restore the original exception handler
        ifd    CATCH
        move.l        ThisTask(a6),A3
        move.l        oldtrapdata(A4),TC_TRAPDATA(a3)
        move.l        oldtrapcode(A4),TC_TRAPCODE(a3) * check current exception
         ifd         AUTOREQ
          move.l        IntuiBase(a4),a1
          callsys         CloseLibrary                * close Intuition library
         endc
        ENDC

*------ free the command line buffer
        move.l     Commandlen(a4),d0
        beq.s      nodofree
        move.l     Commandbuf(a4),a1
        callsys    FreeMem

*------ this rts sends us back to DOS:
nodofree:
        move.l     DOSBase(A4),a1
        callsys    CloseLibrary              * close Dos library

        IFD        RESIDENT
        move.l     realdatasize(a4),d0
        move.l     a4,a1
        sub.l      #RESBASE,a1
        callsys    FreeMem
        ENDC
        move.l     (a7)+,d0

return:
        movem.l    (a7)+,d1-d6/a0-a6
        rts

DOSName dc.b    'dos.library',0
RCSId   dc.b    '$Id: c.asm,v 1.5 1993/09/14 22:24:41 simons Exp simons $'
        dc.w    0

        ifd        CATCH
*-----------------------------------------------------------------------
*        Open the Intuition library:

openIntui:
        lea        IntuiName(PC),A1
        moveq.l    #0,D0
        callsys    OpenLibrary
        move.l     D0,IntuiBase(A4)
        beq.s      noDOS
        rts

*-----------------------------------------------------------------------
noDOS:
                moveq.l #100,d0
                bra.w   exit2


IntuiName  dc.b        'intuition.library',0

*-----------------------------------------------------------------------
*        The Exception Handler - catches GURUs and exits (semi)cleanly
Exception:
        movem.l    a0,-(a7)
        move.l     AbsExecBase.W,a0
        move.l     ThisTask(a0),a0
        move.l     TC_TRAPDATA(a0),a0        * ...and data
        move.l     (sp)+,ADump(a0)           * save a0
        move.l     d0,ADump+4(a0)            * and d0

        move.l     (a7)+,d0                  * get exception # from stack
        move.l     d0,GURUNum(a0)            * and save it
        cmpi.l     #3,d0                     * ADDRESS or BUS error?
        bgt.s      1$                        * no, skip adjustment
        btst       #0,Environment+3(a0)      * is it 68010 or 68020?
        bne.s      1$                        * 0 means NO
        addq.l     #8,a7                     * adjust for 68000
1$:
        move.l     2(a7),d0                  * get PC at crash
        move.l     d0,GURUAddr(a0)           * and save it
        move.l     ADump+4(a0),d0            * restore a0 and d0
        move.l     ADump(a0),a0
        move.l     #GURUExit,2(a7)           * use our own exit point
        rte

*-----------------------------------------------------------------------
*        The Exception exit routine - write 'PGTB' IFF chunk to file
*        'SnapShot.TB' in current directory, then exit to system.

GURUExit:
        movem.l    d0-d7/a0-a7,-(sp)         * save all registers
        move.l     AbsExecBase.W,a6          * make sure we are working with Exec
        callsys    GetCC                     * safe way - works with all CPUs
        move.l     ThisTask(a6),a3
        move.l     TC_TRAPDATA(a3),a4        * make sure we have a valid # in a4
        move.l     d0,Flags(a4)              * save area
        movem.l    (sp)+,d0-d7
        movem.l    d0-d7,DDump(a4)           * save data reg contents
        movem.l    (sp)+,d0-d7
        movem.l    d0-d7,ADump(a4)           * save address reg contents
        tst.l      StackPtr(a4)              * if there's something there
        bne        GExit1                    * ...we've been here before!
        lea        TempStore(a4),a0          * calculate addr of TempStore
        move.l     a0,TempAddr(a4)           * ...and save for later access
        move.l     A7Store(a4),d0            * make sure we have proper TOS
        move.l     d0,StackPtr(a4)           * ...and save it
        moveq      #0,d0
        move.l     _ProgramName(a4),a0       * find length of program name

        ifd        AUTOREQ
        move.l     a0,PName(a4)
        endc

        subq.l     #1,a0
        move.b     (a0),d0
        addq.l     #4,d0                     * adjust for shift
        lsr.l      #2,d0
        move.l     d0,NameLen(a4)            * store length
        add.l      d0,FAILlen(a4)            * and sub-chunk total

        moveq      #0,d0                     * clear d0 for use
        lea        VBlankFrequency(a6),a0    * set up a0 to find correct data
        move.b     (a0)+,d0                  * get just in case
        move.l     d0,VBlankFreq(a4)         * ...so we can figure what
        move.b     (a0),d0                   * ...type of machine
        move.l     d0,PowerSupFreq(a4)       * ...we're working on

        lea        start-4(pc),a0            * get seglist ptr
        moveq      #-1,d0                    * always at least 1
2$:
        addq.l     #1,d0
        move.l     (a0),d1                   * find end of list
        beq.s      3$
        lsl.l      #2,d1                     * BPTR!!!!!
        move.l     d1,a0
        bra.s      2$
3$:
        add.l      d0,SegCount(a4)           * store # of seglist pointers
        lsl.l      #1,d0                     * multiply by 2 for longword count
        add.l      d0,FAILlen(a4)            * and sub-chunk length

        move.l     StackTop(a4),d0           * get top of stack
        sub.l      StackPtr(a4),d0           * find number of bytes used
        addq.l     #4,d0                     * adjust for longword conversion
        lsr.l      #2,d0                     * convert from bytes to long
        move.l     d0,StackLen(a4)           * and save
        add.l      d0,s2len(a4)              * and sub-chunk total

        move.l     a5,-(sp)                  * save a5 for later
        callsys    Forbid                    * don't let 'em change while we ask
        move.l     MemList+LH_HEAD(a6),d0    * first node in MemList
checkchip:
        move.l     d0,a5                     * move node address to address reg
        move.w     MH_ATTRIBUTES(a5),d4      * get node attributes
        btst       #MEMB_CHIP,d4             * is it chip?
        beq.s      checkfast                 * no, go on
        lea        chipAvail(a4),a3
        bsr.w      AddIt
checkfast:
        btst       #MEMB_FAST,d4             * is it fast?
        beq.s      next                      * no, go on
        lea        fastAvail(a4),a3
        bsr.w      AddIt
next:
        move.l     LN_SUCC(a5),d0            * get address of next node
        bne.s      checkchip                 * ...and loop back if valid
        callsys    Permit                    * allow others access again
        move.l     #MEMF_CHIP+MEMF_LARGEST,d1 * to find largest hunk in chip ram
        callsys    AvailMem
        move.l     d0,chipLargest(a4)         * store
        move.l     #MEMF_FAST+MEMF_LARGEST,d1 * to find largest hunk in fast ram
        callsys    AvailMem
        move.l     d0,fastLargest(a4)        * store
        move.l     (sp)+,a5                  * and restore a5

        ifd        AUTOREQ
        moveq      #0,d0                     * PosFlag
        move.l     d0,d1                     * NegFlag
        move.l     d0,a0                     * 0 means use current window
        lea        IText1(a4),a1             * Body Text
        lea        IText5(a4),a2             * Positive Gadget Text
        lea        IText6(a4),a3             * Negative Gadget Text
        moveq      #1,d2
        lsl.l      #8,d2                     * quick way to set Width
        moveq      #76,d3                    * Height
        move.l     IntuiBase(a4),a6          * get intuition library pointer
        jsr        -$15c(A6)                 * callsys       AutoRequest
        move.l     AbsExecBase.W,a6
        tst.l      d0                        * save SnapShot?
        beq.w      GExit2                    * no, just exit
        endc

        move.l     DOSBase(a4),a6
        lea        DumpName(a4),a0           * get name of output file
        move.l     a0,d1
        move.l     #MODE_NEWFILE,d2          * create new file
        callsys    Open
        bne.s      4$
        lea        DumpPath(a4),a0           * if error in current dir, try DF1:
        move.l     a0,d1
        move.l     #MODE_NEWFILE,d2
        callsys    Open
        bne.s      4$
        move.b     #'0',DumpPath+2(a4)       * still error?  Try DF0:
        lea        DumpPath(a4),a0
        move.l     a0,d1
        move.l     #MODE_NEWFILE,d2
        callsys    Open

        ifnd        AUTOREQ
        bne.s      4$                        * if no error, continue (finally!)
        move.l     GConsole(a4),d1
        beq.w      GExit2
        lea        failmsg(a4),a0
        move.l     a0,d2
        move.l     #23,d3
        callsys    Write
        endc

        bra.w      GExit2                    * else, print msg & DIE gracefully
4$:
        move.l     d0,d5                     * save file handle for Write
        move.l     d0,fp(a4)                 * ...and in a safe place for later
        move.l     d5,d1                     * get file handle
        lea        PGTB(a4),a0               * first part of fixed
        move.l     a0,d2
        move.l     #chunk_len_1,d3           * length of first
        callsys    Write                     * ...since it gets written over

        move.l     d5,d1                     * get file handle
        move.l     _ProgramName(a4),d2       * get address of program name
        move.l     NameLen(a4),d3            * get # longs in program name
        lsl.l      #2,d3                     * ..and convert to bytes
        callsys    Write

        move.l     d5,d1                     * get file handle
        lea        Environment(a4),a0        * second part of fixed
        move.l     a0,d2
        move.l     #chunk_len_2,d3           * length of second part
        callsys    Write

        lea        start-8(pc),a0            * address of seglist (size of seg)
        move.l     (a0)+,d0                  * segsize
        move.l     d0,TempStore+4(a4)        * save it
        move.l     a0,TempStore(a4)          * store first number
        move.l     SegCount(a4),d4
5$:
        move.l     d5,d1                     * get file handle
        move.l     TempAddr(a4),d2           * address of write buffer
        moveq      #TempSize,d3              * size of segment pointer
        callsys    Write
        move.l     TempStore(a4),a0          * retrieve pointer
        move.l     (a0),d0                   * get next seg pointer
        lsl.l      #2,d0                     * adjust
        move.l     d0,TempStore(a4)          * ..and save
        move.l     d0,a0
        beq.b      donesegs                  * last segment?
        move.l     -4(a0),d0                 * get segsize
        move.l     d0,TempStore+4(a4)        * ...and save it
        subq.l     #1,d4                     * done yet?
        bne.s      5$                        * no, do next

donesegs:
        tst.l      _FMEM(a4)                 * do they want memory reported?
        beq.s      55$                       * no, forget it
        move.l     d5,d1
        lea        subFMEM(a4),a0
        move.l     a0,d2
        move.l     #FMEMlen,d3
        callsys    Write

55$:
        move.l     d5,d1                     * (get the idea?)
        lea        subREGS(a4),a0            * third part of fixed
        move.l     a0,d2
        move.l     #chunk_len_3,d3           * length of third
        callsys    Write

        move.l     StackLen(a4),d0           * get length of stack used
        cmpi.l     #2048,d0                  * > 8k ?
        bgt.s      6$                        * yes, dump two chunks
        move.l     d5,d1
        lea        STAK2(a4),a0              * whole stack chunk
        move.l     a0,d2
        moveq      #STAK2len,d3              * length of fixed part
        callsys    Write

        move.l     d5,d1
        move.l     StackPtr(a4),d2           * address of stack
        move.l     StackLen(a4),d3           * get # longwords on stack
        lsl.l      #2,d3                     * ..and convert to bytes
        callsys    Write
        bra.s      7$
6$:
        move.l     d5,d1
        lea        STAK3(a4),a0              * top4k chunk
        move.l     a0,d2
        moveq      #STAK3len,d3              * length of fixed part
        callsys    Write

        move.l     d5,d1
        move.l     StackTop(a4),d2           * find top of stack
        sub.l      #4096,d2                  * find top-4k
        move.l     #4096,d3                  * # bytes to write
        callsys    Write

        move.l     d5,d1
        lea        STAK4(a4),a0              * bottom4k chunk
        move.l     a0,d2
        moveq      #STAK4len,d3              * length of fixed part
        callsys    Write

        move.l     d5,d1
        move.l     StackPtr(a4),d2           * current stack address
        move.l     #4096,d3                  * # bytes to write
        callsys    Write
7$:
        move.l     _STAKOffset(a4),d3
        beq.s      8$
        lsr.l      #2,d3
        addq.l     #1,d3
        move.l     d3,_STAKOffset(a4)
        addq.l     #1,d3
        move.l     d5,d1
        lea        STAK5(a4),a0
        move.l     a0,d2
        moveq      #STAK5len,d3
        callsys    Write

        move.l     d5,d1
        move.l     StackPtr(a4),d2
        move.l     _STAKOffset(a4),d3
        subq.l     #1,d3
        move.l     StackLen(a4),d4
        cmp.l      d3,d4
        bge.s      75$
        move.l     StackLen(a4),d3
75$:
        lsl.l      #2,d3
        callsys    Write
8$:
        tst.l      _ONGURU(A4)               * user GURU function?
        beq.s      9$
        move.l     d5,-(sp)
        move.l     d5,d1
        lea        UDAT(a4),a0
        move.l     a0,d2
        move.l     #UDATlen,d3
        callsys    Write
        move.l     d5,d1
        moveq      #0,d2                     * zero offset
        moveq      #1,d3                     * ...from EOF
        callsys    Seek
        move.l     d0,SeekStore(a4)
        move.l     _ONGURU(a4),a0
        jsr        (a0)
        addq.l     #4,sp
9$:
        move.l     fp(a4),d5
        move.l     d5,d1
        moveq      #0,d2                     * offset from EOF
        moveq      #1,d3                     * OFFSET_END
        callsys    Seek                      * Seek returns OLD position
        move.l     d0,d1
        andi.l     #3,d1                     * did user write even longwords?
        beq.s      10$                       * Yep!        Nice Human.
        move.l     d1,d6                     * Nope, save for later.
        clr.l      TempStore(a4)             * clear temp storage
        move.l     d5,d1
        move.l     TempAddr(a4),d2
        moveq      #4,d3
        sub.l      d6,d3                     * find how many NULLs to pad
        callsys    Write
        bra.s      9$
10$:
        tst.l      SeekStore(a4)             * did we write UDAT?
        beq.s      11$                       * nope!
        sub.l      SeekStore(a4),d0          * find length of UDAT section
        lsr.l      #2,d0                     * adjust to longwords
        move.l     d0,TempStore(a4)          * save UDAT length for write
        move.l     d5,d1
        move.l     SeekStore(a4),d2          * find where to write it
        subq.l     #4,d2
        moveq      #-1,d3                    * OFFSET_BEGINNING
        callsys    Seek
        move.l     d5,d1
        move.l     TempAddr(a4),d2
        move.l     #4,d3
        callsys    Write                     * write length of UDAT field to file
11$:
        move.l     d5,d1
        moveq      #0,d2                     * offset to 'Length' field
        moveq      #1,d3                     * OFFSET_END
        callsys    Seek                      * make sure we are at end of file
        move.l     d5,d1
        moveq      #4,d2                     * offset to 'Length' field
        moveq      #-1,d3                    * OFFSET_BEGINNING
        callsys    Seek
        subq.l     #8,d0                     * adjust total length
        lsr.l      #2,d0                     * adjust to longwords
        move.l     d0,TempStore(a4)          * save for write
        move.l     d5,d1
        move.l     TempAddr(a4),d2
        move.l     #4,d3
        callsys    Write                     * write 'Length' field
GExit1:
        move.l     fp(a4),d1
        beq.s      GExit2
        move.l     DOSBase(a4),a6
        callsys    Close

        ifnd        AUTOREQ
        move.l      GConsole(a4),d1
        beq.s       GExit2
        lea         success(a4),a0
        move.l      a0,d2
        move.l      #32,d3
        callsys     Write
        endc

GExit2:
        move.l       TaskID(a4),a6
        move.l       AbsExecBase.W,a6
        moveq        #$47,d0
        bra.w        exit2

*-----------------------------------------------------------------------
* AddIt:        routine to add memory parts to variables

AddIt:
        move.l       MH_FREE(a5),d0
        add.l        d0,(a3)                 * add to available
        move.l       MH_UPPER(a5),d0
        sub.l        MH_LOWER(a5),d0
        add.l        d0,4(a3)                * add to Max section
        rts
        endc


        IFD     CATCH
        section __MERGED,DATA
_ONGURU        dc.l        0
IntuiBase      dc.l        0
TaskID         dc.l        0
oldtrapcode    dc.l        0
oldtrapdata    dc.l        0

        ifnd        AUTOREQ
GConsole        dc.l        0
failmsg         dc.b        7,'Can''t write SnapShot!',10
success         dc.b        7,'GURU caught; SnapShot written!',10
        endc

        cnop        0,4
_FMEM           dc.l        0
fp              dc.l        0                  * save SnapShot file pointer
DumpPath        dc.b        'DF1:'
DumpName        dc.b        'SnapShot.TB',0
SeekStore       dc.l        0
TempAddr        dc.l        0                  * Storage for &TempStore
TempStore       dc.l        0,0                * Temporary storage for BPTR -> APTR
TempSize        equ        *-TempStore

        cnop        0,4
        ifd        AUTOREQ
TAttr:                                         * Text attributes for font
        dc.l        TName                      * name of font
        dc.w        TOPAZ_EIGHTY               * font size
        dc.b        FS_NORMAL                  * font style
        dc.b        FPF_ROMFONT                * font preferences
TName:
        dc.b        'topaz.font',0
        cnop        0,4

IText1:                                        * Text definitions for AutoReq call
        dc.b        3,0,RP_JAM1,0              * front & back pens, drawmode and filler byte
        dc.w        6,4                        * XY origin relative to container TopLeft
        dc.l        TAttr                      * font pointer or NULL for default
        dc.l        ITextText1                 * pointer to text
        dc.l        IText2                     * next IntuiText structure
ITextText1:
        dc.b        'Program:',0
        cnop 0,4
IText2:
        dc.b        3,0,RP_JAM1,0
        dc.w        78,4
        dc.l        TAttr
PName   dc.l        0
        dc.l        IText3
        cnop        0,4
IText3:
        dc.b        3,0,RP_JAM1,0
        dc.w        55,16
        dc.l        TAttr
        dc.l        ITextText3
        dc.l        IText4
ITextText3:
        dc.b        'I caught a GURU!',0
        cnop 0,4
IText4:
        dc.b        3,0,RP_JAM1,0
        dc.w        20,28
        dc.l        TAttr
        dc.l        ITextText4
        dc.l        0
ITextText4:
        dc.b        'Should I make a SnapShot?',0
        cnop 0,4
IText5:
        dc.b        3,0,RP_JAM2,0
        dc.w        6,3
        dc.l        TAttr
        dc.l        ITextText5
        dc.l        0
ITextText5:
        dc.b        'YES',0
        cnop 0,4
IText6:
        dc.b        3,0,RP_JAM2,0
        dc.w        6,3
        dc.l        TAttr
        dc.l        ITextText6
        dc.l        0
ITextText6:
        dc.b        'NO',0
        endc

        cnop 0,4

*--------------------------------------------------------------------------
* New IFF chunk format -
*        PGTB = Program Traceback, header for chunk
*        FAIL = reason for and environment of crash
*        REGS = registers at time of crash, including PC and CCR
*        VERS = version, revision, name of this program
*        STAK = ENTIRE stack at time of crash or, alternately,
*                the top and bottom 4k if the stack used is > 8k
*        UDAT = optional user data dump (if _ONGURU is set to a
*                function pointer in the user's program)
*--------------------------------------------------------------------------

PGTB            dc.b        'PGTB'
Length          dc.l        0                * length of chunk (in longwords)

subFAIL         dc.b        'FAIL'
FAILlen         dc.l        9
NameLen         dc.l        0                * length of program name
chunk_len_1     equ         *-PGTB
Environment     dc.l        0                * CPU (, Math)
VBlankFreq      dc.l        0                *        PAL = 50, NTSC = 60 (approx.)
PowerSupFreq    dc.l        0                * Europe = 50,        USA = 60 (approx.)
Starter         dc.l        0                * 0 = WB, -1 = CLI
GURUNum         dc.l        0                * cause of crash (GURU #)
SegCount        dc.l        1                * # hunks in seglist
chunk_len_2     equ         *-Environment

subFMEM         dc.b        'FMEM'           * FMEM - free memory at crash
                dc.l        6
chipAvail       dc.l        0                * available chip memory
chipMax         dc.l        0                *        maximum chip memory
chipLargest     dc.l        0                *        largest chip memory
fastAvail       dc.l        0                * available fast memory
fastMax         dc.l        0                *        maximum fast memory
fastLargest     dc.l        0                *        largest fast memory
FMEMlen         equ         *-subFMEM

subREGS         dc.b        'REGS'           * REGS - register storage field
REGSlen         dc.l        18
GURUAddr        dc.l        0                * PC at time of crash
Flags           dc.l        0                * Condition Code Register (CCR)
DDump           dc.l        0,0,0,0,0,0,0,0  * data registers
ADump           dc.l        0,0,0,0,0,0,0    * address registers
A7Store         dc.l        0

subVERS         dc.b        'VERS'           * VERS - program version field
                dc.l        6
                dc.l        VERSION          * version #
                dc.l        REVISION         * revision #
                dc.l        3                * length of name of program
                IFD        RESIDENT
                dc.b        'catchres.o',0,0 * name
                ENDC
                IFND        RESIDENT
                dc.b        'catch.o   ',0,0 * name
                ENDC

subSTAK         dc.b        'STAK'           * STAK - stack field
STAKlen         dc.l        4
Type            dc.l        0                * 0 = Info
StackTop        dc.l        0                * top of stack pointer
StackPtr        dc.l        0                * current Stack Pointer
StackLen        dc.l        0                * # bytes used on stack
chunk_len_3     equ         *-subREGS

STAK2           dc.b        'STAK'
s2len           dc.l        1                * length of subtype
                dc.l        1                * 1 = whole stack
STAK2len        equ         *-STAK2

STAK3           dc.b        'STAK'
                dc.l        1025
                dc.l        2                * 2 = top 4k of stack
STAK3len        equ         *-STAK3

STAK4           dc.b        'STAK'
                dc.l        1025
                dc.l        3                * 3 = bottom 4k of stack
STAK4len        equ         *-STAK4

STAK5           dc.b        'STAK'
_STAKOffset     dc.l        0
                dc.l        4                * 4 = user defined amount
STAK5len        equ         *-STAK5

UDAT            dc.b        'UDAT'
                dc.l        0
UDATlen         equ         *-UDAT
        endc



        section __MERGED,BSS

        xref    DOSBase

        xdef    NULL,SysBase,_WBenchMsg
        xdef    __curdir
        xdef    _OSERR,_FPERR,_SIGFPE,_ONERR,_ONEXIT,_ONBREAK
        xdef    _SIGINT
        xdef    _ProgramName,_StackPtr,__base
        ifd        CATCH
        xdef        _ONGURU,_FMEM,_STAKOffset
        endc



NULL         ds.b    4
__base       ds.b    4                   * base of stack
_OSERR       ds.b    4
_FPERR       ds.b    4
_SIGFPE      ds.b    4
_SIGINT      ds.b    4
_ONERR       ds.b    4
_ONEXIT      ds.b    4
_ONBREAK     ds.b    4
__curdir     ds.b    4
SysBase      ds.b    4
_WBenchMsg   ds.b    4
_StackPtr    ds.b    4
_ProgramName ds.b    4
Commandbuf   ds.b    4
Commandlen   ds.b    4

        ifd        RESIDENT
realdatasize ds.b    4                   * size of memory allocated for data +
                                         * possible stack
        endc
        ifnd       RESIDENT
newstack     ds.b    4                   * pointer to new stack (if needed)
newstacksize ds.b    4                   * size of new stack
        endc

             END
@


1.5
log
@Deleted some Workbench related code to make the startup more efficient.
@
text
@d3 2
a4 2
**      $Revision: 1.4 $
**      $Date: 1993/09/14 22:16:07 $
d13 1
a13 1
**      $Id: c.asm,v 1.4 1993/09/14 22:16:07 simons Exp simons $
d17 3
d389 1
d392 1
a392 1
                clr.b   (a1)+
d469 1
a469 1
RCSId   dc.b    '$Id: c.asm,v 1.4 1993/09/14 22:16:07 simons Exp simons $'
@


1.4
log
@If started from Workbench, the startup-code returns immediatly.
@
text
@d3 2
a4 2
**      $Revision: 1.3 $
**      $Date: 1993/09/14 21:58:36 $
d13 1
a13 1
**      $Id: c.asm,v 1.3 1993/09/14 21:58:36 simons Exp simons $
d17 3
a146 1
*------                                 if WB use a7 - TC_SPLOWER
a148 1
        beq.s         fromwb
d152 1
a152 7
        lsl.l         #2,d0             * # longwords -> # bytes
        bra.s         dostack

fromwb:
        move.l        a7,d0
        sub.l         TC_SPLOWER(a3),d0
dostack:
a190 1
*------                                 if WB use a7 - TC_SPLOWER
a192 1
        beq.s         fromwb
a196 6
        bra.s         dostack

fromwb:
        move.l        a7,d1
        sub.l         TC_SPLOWER(a3),d1
dostack:
a326 1
*------ are we running as a son of Workbench?
a327 2
        tst.l         pr_CLI(A3)
        beq.w         fromWorkbench
a389 38
                bra.s   main                    ; call C entrypoint

*=======================================================================
*====== Workbench Startup Code =========================================
*=======================================================================

fromWorkbench:

        ifd        CATCH
        move.l     TC_SPUPPER(a3),StackTop(a4)  * set top of stack
        endc


*------ we are now set up.  wait for a message from our starter
        lea        pr_MsgPort(A3),a0         * our process base
        callsys    WaitPort
        lea        pr_MsgPort(A3),a0         * our process base
        callsys    GetMsg
        move.l     d0,_WBenchMsg(a4)
        move.l     d0,-(SP)

        move.l     d0,a2                     * get first argument
        move.l     sm_ArgList(a2),d0
        beq.s      do_main
        move.l     DOSBase(a4),a6
        move.l     d0,a0
        move.l     wa_Lock(a0),d1
        callsys    DupLock
        move.l     d0,__curdir(A4)
        move.l     d0,d1
        callsys    CurrentDir

do_main:
        move.l     _WBenchMsg(A4),a0         * get address of workbench message
        move.l     a0,-(a7)                  * push argv
        pea        NULL(a4)                  * push argc
        move.l     sm_ArgList(a0),a0         * get address of arguments
        move.l     wa_Name(a0),_ProgramName(A4) * get name of program
a426 17
*------ if we ran from CLI, skip workbench cleanup:
        tst.l      _WBenchMsg(A4)
        beq.s      exitToDOS
        move.l     DOSBase(A4),a6
        move.l     __curdir(a4),d1
        beq.s      done_5
        callsys    UnLock
done_5:
*------ return the startup message to our parent
*       we forbid so workbench can't UnLoadSeg() us
*       before we are done:
        move.l     AbsExecBase.W,A6
        callsys    Forbid
        move.l     _WBenchMsg(a4),a1
        callsys    ReplyMsg
        bra.s      nodofree

d465 1
a465 1
RCSId   dc.b    '$Id: c.asm,v 1.3 1993/09/14 21:58:36 simons Exp simons $'
@


1.3
log
@The pseudo opcode EVEN is unknown to asm, replaced it.
Changed the line-parameter for _main() to the shell commandline
without programname and the terminating return, for usage with my
modified __main().
@
text
@d3 2
a4 2
**      $Revision: 1.2 $
**      $Date: 1993/09/14 20:20:03 $
d13 1
a13 1
**      $Id: c.asm,v 1.2 1993/09/14 20:20:03 simons Exp simons $
d17 6
d125 7
d536 1
a536 1
RCSId   dc.b    '$Id: c.asm,v 1.2 1993/09/14 20:20:03 simons Exp simons $'
@


1.2
log
@Added RCSId string.
@
text
@d3 2
a4 2
**      $Revision: 1.1 $
**      $Date: 1993/09/14 20:18:32 $
d13 1
a13 1
**      $Id: c.asm,v 1.1 1993/09/14 20:18:32 simons Exp simons $
d17 3
d371 1
a371 1
        movem.l     d1/a1,-(a7)
d387 7
a393 18
        move.l     d2,d0                    * get command line length
        subq.l     #1,d0
        add.l      d1,d2

copy_line:
        move.b     0(A2,D0.W),2(A0,D2.W)    * copy command line to stack
        subq.l     #1,d2
        dbf        d0,copy_line
        move.b     #' ',2(a0,d2.w)          * add space between command and parms
        subq.l     #1,d2
        move.b     #'"',2(a0,d2.w)          * add end quote

copy_cmd:
        move.b     0(a1,d2.w),1(a0,d2.w)    * copy command name to stack
        dbf        d2,copy_cmd
        move.b     #'"',(a0)
        move.l     A0,-(A7)                 * push command line address
        bra.s      main                     * call C entrypoint
d523 2
a524 2
RCSId   dc.b    '$Id$',0
        EVEN
@


1.1
log
@Initial revision
@
text
@d3 2
a4 2
**      $Revision$
**      $Date$
d13 1
a13 1
**      $Id$
d16 3
a18 1
** $Log$
d531 2
@
