home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus Extra 1997 #5 / AmigaPlus_Extra-CD_5-97.iso / online-tools / mail / pgp_mip / pgpsendmail / source / c.asm next >
Assembly Source File  |  1993-09-24  |  40KB  |  1,099 lines

  1. **
  2. **      $Filename: c.asm $
  3. **      $Revision: 1.6 $
  4. **      $Date: 1993/09/14 23:13:22 $
  5. **
  6. **      This is a replacement for the standard startup module, usually
  7. **      linked to C programs. This one is modified to fit better with
  8. **      my _main().
  9. **
  10. **      © Copyright 1993 Peter Simons, Germany
  11. **        All Rights Reserved
  12. **
  13. **      $Id: c.asm,v 1.6 1993/09/14 23:13:22 simons Stab simons $
  14. **
  15. ** ------------------------------ log history -----------------------------
  16. ** $Log: c.asm,v $
  17. ** Revision 1.6  1993/09/14  23:13:22  simons
  18. ** Startup code crashed the machine when the command was started without
  19. ** parameters.
  20. **
  21. ** Revision 1.5  1993/09/14  22:24:41  simons
  22. ** Deleted some Workbench related code to make the startup more efficient.
  23. **
  24. ** Revision 1.4  1993/09/14  22:16:07  simons
  25. ** If started from Workbench, the startup-code returns immediatly.
  26. **
  27. ** Revision 1.3  1993/09/14  21:58:36  simons
  28. ** The pseudo opcode EVEN is unknown to asm, replaced it.
  29. ** Changed the line-parameter for _main() to the shell commandline
  30. ** without programname and the terminating return, for usage with my
  31. ** modified __main().
  32. **
  33. ** Revision 1.2  1993/09/14  20:20:03  simons
  34. ** Added RCSId string.
  35. **
  36. ** Revision 1.1  1993/09/14  20:18:32  simons
  37. ** Initial revision
  38. **
  39. ** --------------------------------- flags --------------------------------
  40. ** Use the following command line to make c.o
  41. ** asm -u -isc:Assembler_Include/ c.a
  42. **
  43. ** Use the following command line to make cres.o
  44. ** asm -u -isc:Assembler_Include/ -dRESIDENT -ocres.o c.a
  45. **
  46. ** Use the following command line to make catch.o (standard GURU catcher)
  47. ** asm -u -isc:Assembler_Include/ -dCATCH -ocatch.o c.a
  48. **
  49. ** Use the following command line to make catchnr.o (GURU catcher w/out requester)
  50. ** asm -u -isc:Assembler_Include/ -dCATCH -dNOREQ -ocatchnr.o c.a
  51. **
  52. ** Use the following command line to make catchres.o (resident GURU catcher)
  53. ** asm -u -isc:Assembler_Include/ -dCATCH -dRESIDENT -ocatchres.o c.a
  54. **
  55. ** Use the following command line to make catchresnr.o (resi GURU catcher w/out req)
  56. ** asm -u -isc:Assembler_Include/ -dCATCH -dRESIDENT -dNOREQ -ocatchresnr.o c.a
  57. **
  58.  
  59.         IFD  CATCH
  60.           IFND NOREQ
  61. AUTOREQ         set        1
  62.           ENDC
  63.         ENDC
  64.  
  65.         INCLUDE        "exec/types.i"
  66.         INCLUDE        "exec/alerts.i"
  67.         INCLUDE        "exec/nodes.i"
  68.         INCLUDE        "exec/lists.i"
  69.         INCLUDE        "exec/ports.i"
  70.         INCLUDE        "exec/libraries.i"
  71.         INCLUDE        "exec/tasks.i"
  72.         INCLUDE        "exec/memory.i"
  73.         INCLUDE        "exec/execbase.i"
  74.         INCLUDE        "libraries/dos.i"
  75.         INCLUDE        "libraries/dosextens.i"
  76.         INCLUDE        "workbench/startup.i"
  77.         INCLUDE        "Offsets.i"
  78.  
  79.         IFD   CATCH
  80.         INCLUDE        "intuition/intuition.i"
  81. VERSION  equ    1
  82. REVISION equ    0
  83.         ENDC
  84.  
  85. MEMFLAGS        EQU        MEMF_CLEAR+MEMF_PUBLIC
  86. AbsExecBase     EQU        4
  87.  
  88. ;;;
  89. ;;;   Stack map.
  90. ;;;
  91.       OFFSET  0
  92.            ds.b    4
  93. savereg    ds.b    13*4
  94. stackbtm   ds.b    4
  95.  
  96.  
  97.  
  98. ; some usefull macros:
  99.  
  100. callsys macro
  101.         CALLLIB _LVO\1
  102.         endm
  103.  
  104.         xdef        _XCEXIT                * exit(code) is standard way to leave C.
  105.         xdef        @_XCEXIT
  106.  
  107.         xref        LinkerDB        * linker defined base value
  108.         xref        _BSSBAS                * linker defined base of BSS
  109.         xref        _BSSLEN                * linker defined length of BSS
  110.         xref        __stack
  111.  
  112.        IFD          RESIDENT
  113.         xref        RESLEN
  114.         xref        RESBASE
  115.         xref        NEWDATAL
  116.        ENDC
  117.  
  118. *       library references
  119.  
  120.         section text,code
  121.  
  122.         xref    __main                  * Name of C program to start with.
  123.         xref    _MemCleanup             * Free all allocated memory
  124.         xref    __fpinit                * initialize floating point
  125.         xref    __fpterm                * terminate floating point
  126.  
  127. start:
  128.         movem.l d1-d6/a0-a6,-(a7)       * save registers
  129.  
  130.         move.l  a0,a2                   * save command pointer
  131.         move.l  d0,d2                   * and command length
  132.         lea     LinkerDB,a4             * load base register
  133.         move.l  AbsExecBase.W,a6
  134.  
  135. *---------- check if started from CLI
  136.                 move.l  ThisTask(a6),A3
  137.                 tst.l   pr_CLI(A3)
  138.                 bne.s   fromcli
  139.                 movem.l (SP)+,d1-d6/a0-a6
  140.                 rts
  141. fromcli:
  142.  
  143.         IFND        RESIDENT
  144.         lea     _BSSBAS,a3              * get base of BSS
  145.         moveq   #0,d1
  146.         move.l  #_BSSLEN,d0             * get length of BSS in longwords
  147.         bra.s   clr_lp                  * and clear for length given
  148. clr_bss move.l  d1,(a3)+
  149. clr_lp  dbf     d0,clr_bss
  150.         move.l  a7,_StackPtr(A4)        * Save stack ptr
  151.         move.l  a6,SysBase(A4)
  152.  
  153. *------ get the size of the stack, if CLI use cli_DefaultStack
  154.         move.l        ThisTask(a6),A3
  155.         move.l        pr_CLI(A3),d0
  156.         lsl.l         #2,d0
  157.         move.l        d0,a0
  158.         move.l        cli_DefaultStack(a0),d0
  159.         lsl.l         #2,d0              * # longwords -> # bytes
  160.  
  161. *------ Set __base for stack checking
  162.         move.l       a7,d1
  163.         sub.l        d0,d1               * get top of stack
  164.         add.l        #128,D1             * allow for parms overflow
  165.         move.l       D1,__base(A4)       * save for stack checking
  166.  
  167.         cmp.l         __stack(a4),d0
  168.         bcc.s        nochange
  169.  
  170. *-- current stack is not as big as __stack says it needs
  171. *-- to be. Allocate a new one.
  172.         move.l        __stack(a4),d0
  173.         add.l         #128,d0           * extra room
  174.         move.l        d0,newstacksize(a4)
  175.  
  176.         move.l        #MEMFLAGS,d1
  177.         callsys       AllocMem
  178.         tst.l         d0
  179.         beq.w         return
  180.  
  181.         move.l        d0,newstack(a4)
  182.         add.l         #128,d0           * extra room
  183.         move.l        d0,__base(a4)
  184.  
  185.         add.l         __stack(a4),d0
  186.         move.l        d0,a7
  187.  
  188. nochange:
  189.         ENDC
  190.  
  191.  
  192.  
  193.         IFD        RESIDENT
  194.         move.l        d2,-(a7)
  195.         movem.l       a0-a2,-(a7)
  196.  
  197. *------ get the size of the stack, if CLI use cli_DefaultStack
  198.         move.l        ThisTask(a6),A3
  199.         move.l        pr_CLI(A3),d1
  200.         lsl.l         #2,d1
  201.         move.l        d1,a0
  202.         move.l        cli_DefaultStack(a0),d1
  203.         lsl.l         #2,d1             * # longwords -> # bytes
  204.         moveq        #0,d2              * use d2 as flag for newstack or not
  205.         move.l       #RESLEN,d0
  206.         cmp.l        __stack(a4),d1     * This a4 is in the original
  207.                                         * set of data
  208.         bcc.s        nochange
  209.         move.l        __stack(a4),d1
  210.         add.l        d1,d0              * increase size of mem for new stack
  211.         moveq        #1,d2              * set flag
  212.  
  213. nochange:
  214.         move.l        d1,a3             * save stacksize to set up stack checking
  215.         move.l        #MEMFLAGS,d1
  216.         callsys       AllocMem
  217.         tst.l         d0
  218.         bne.s         ok1
  219.         movem.l       (a7)+,d2/a0-a2
  220.         bra.w         return
  221.  
  222. ok1:    move.l        d0,a0
  223.         move.l        d0,a2             * a2 now has difference
  224.  
  225.         move.l        d0,a1
  226.         move.l        #NEWDATAL,d0
  227.         sub.l         #RESBASE,a4
  228.  
  229.                                         * copy data over
  230. cpy:    move.l        (a4)+,(a0)+
  231.         subq.l        #1,d0
  232.         bne.s         cpy
  233.  
  234.                                         * a4 now points at number of relocs
  235.         move.l        (a4)+,d0
  236. reloc:  beq.s         nreloc
  237.         move.l        a1,a0
  238.         add.l         (a4)+,a0          * a0 now has add of reloc
  239.         add.l         (a0),a2
  240.         move.l        a2,(a0)
  241.         move.l        a1,a2             * restore offset
  242.         subq.l        #1,d0
  243.         bra.s         reloc
  244.  
  245. nreloc: move.l        a1,a4             * set up new base register
  246.         add.l         #RESBASE,a4
  247.  
  248.         move.l        #RESLEN,realdatasize(a4)
  249.         movem.l       (a7)+,a0-a2
  250.  
  251.         move.l        a6,SysBase(A4)
  252.         tst.b         d2
  253.         movem.l       (a7)+,d2          * restore d2
  254.         movem.l       a7,_StackPtr(A4)  * Save stack ptr (movem doesn't
  255.                                         * change flags
  256.         beq.s         nochg2
  257.  
  258. *------ set up new stack
  259.         move.l       a4,d0
  260.         sub.l        #RESBASE,d0
  261.         add.l        #RESLEN,d0
  262.         add.l        __stack(a4),d0     * here a4 will be pointing at the
  263.                                         * new data, but __stack will be the
  264.                                         * same if all goes well
  265.         sub.l        #128,d0            * 128 down for good measure
  266.         move.l       d0,a7
  267.         move.l       __stack(a4),d0
  268.         move.l       d0,4(a7)            * fill in size of new stack
  269.         add.l        d0,realdatasize(a4) * need to know how much to free later
  270.  
  271. nochg2:
  272. *------ Set __base for stack checking
  273.         move.l       a7,d1
  274.         sub.l        a3,d1               * get top of stack
  275.         add.l        #128,D1             * allow for parms overflow
  276.         move.l       D1,__base(A4)       * save for stack checking
  277.  
  278.         ENDC
  279.  
  280.  
  281.  
  282.         ifd     CATCH
  283.         move.w  AttnFlags(a6),Environment+2(a4) * save copy for dump
  284.         endc
  285.  
  286.  
  287.  
  288. clrwb:
  289.         clr.l        _WBenchMsg(A4)
  290.  
  291. *-----  clear any pending signals
  292.         moveq         #0,d0
  293.         move.l        #$00003000,d1
  294.         callsys       SetSignal
  295.  
  296.  
  297.         move.l        ThisTask(a6),A3
  298.  
  299.         ifd        CATCH
  300.         move.l        A3,TaskID(a4)
  301.  
  302. *------ initialize exception handler
  303. *------ Remember to preserve the old handler first
  304.         move.l        TC_TRAPDATA(a3),oldtrapdata(A4)
  305.         move.l        TC_TRAPCODE(a3),d0              ; check current exception
  306.         move.l        d0,oldtrapcode(A4)
  307.  
  308.         move.l        d0,a1
  309.         callsys TypeOfMem
  310.         tst.l d0
  311.         bne.s        1$                               * somebody else (debugger?) has vector
  312.  
  313.         move.l        #Exception,TC_TRAPCODE(a3)      * install pointers to code
  314.         move.l        a4,TC_TRAPDATA(a3)              * ...and data
  315. 1$:
  316.         ifd         AUTOREQ
  317. *------ attempt to open Intuition library:
  318.         bsr.w                openIntui
  319.         endc
  320.         endc
  321.  
  322.  
  323. *------ attempt to open DOS library:
  324.         lea           DOSName(PC),A1
  325.         moveq.l       #0,D0
  326.         callsys       OpenLibrary
  327.         move.l        D0,DOSBase(A4)
  328.         bne.s         ok2
  329.         moveq.l       #100,d0
  330.         bra.w         exit2
  331.  
  332. ok2:
  333.  
  334.         move.l        pr_CurrentDir(A3),__curdir(A4)
  335.  
  336. *=======================================================================
  337. *====== CLI Startup Code ===============================================
  338. *=======================================================================
  339. *
  340. * Entry: D2 = command length
  341. *        A2 = Command pointer
  342. fromCLI:
  343.         ifd        CATCH
  344.         moveq         #-1,d0
  345.         move.l        d0,Starter(a4)        * non-zero means CLI
  346.         move.l        a5,StackTop(a4)
  347.         endc
  348.  
  349. *------ find command name:
  350.         move.l      pr_CLI(a3),a0
  351.         add.l       a0,a0                   * bcpl pointer conversion
  352.         add.l       a0,a0
  353.         move.l      cli_CommandName(a0),a1
  354.  
  355.         IFD         CATCH
  356.         IFND        AUTOREQ
  357.         move.l      cli_StandardOutput(a0),GConsole(a4)   * save output fh
  358.         ENDC
  359.         ENDC
  360.  
  361.         add.l       a1,a1                   * bcpl pointer conversion
  362.         add.l       a1,a1
  363.  
  364. *------ collect parameters:
  365.         move.l      d2,d0                   * get command line length
  366.         moveq.l     #0,d1
  367.         move.b      (a1)+,d1
  368.         move.l      a1,_ProgramName(A4)
  369.         add.l       d1,d0                   * add length of command name
  370.         addq.l      #7,d0                   * allow for space after command, quotes
  371.                                             * and null terminator, as well as
  372.         andi.w      #$fffc,D0               * force to long word boundary
  373.         move.l      d0,Commandlen(a4)
  374.  
  375.         movem.l d1/a1,-(a7)
  376.         move.l      #MEMFLAGS,d1
  377.         callsys     AllocMem
  378.         movem.l     (a7)+,d1/a1
  379.         tst.l       d0
  380.         bne.s       ok_copy
  381.  
  382.         move.l      #1000,d0                * what should the return code be for out of mem?
  383.         move.l      d0,-(a7)                * put a return code on the stack
  384.         beq.w       nodofree                * Was exitToDOS
  385.  
  386. ok_copy:
  387.         move.l      d0,a0
  388.         move.l      d0,Commandbuf(a4)
  389.  
  390. *------ copy command line into memory
  391.                 move.l  a0,a1
  392.                 subq.w  #2,d2
  393.                 bmi.b   no_cmd_line
  394. copy_line:      move.b  (a2)+,(a1)+
  395.                 dbra    d2,copy_line
  396. no_cmd_line:    clr.b   (a1)+
  397.                 pea     (a0)
  398.  
  399. *=============================================
  400. *------ common code --------
  401. *=============================================
  402.  
  403. main    jsr        __fpinit(PC)              * Initialize floating point
  404.         jsr        __main(PC)                * call C entrypoint
  405.         moveq.l    #0,d0                     * set successful status
  406.         bra.s      exit2
  407. *
  408.  
  409. XCEXIT:
  410. _XCEXIT:
  411.         move.l     4(SP),d0                  * extract return code
  412. @XCEXIT:
  413. @_XCEXIT:
  414. exit2:
  415.         movea.l    _StackPtr(a4),a7          * restore stack ptr
  416.         move.l     d0,-(a7)
  417.         move.l     _ONEXIT(A4),d0            * exit trap function?
  418.         beq.s      exit3
  419.         move.l     d0,a0
  420.         jsr        (a0)
  421. exit3:
  422.         jsr        __fpterm(PC)              * clean up any floating point
  423.         jsr        _MemCleanup(PC)           * cleanup leftover memory alloc.
  424.  
  425.         ifnd       RESIDENT
  426. *------ free the stack if we allocated one
  427.         move.l     newstacksize(a4),d0
  428.         beq.s      exit4
  429.         move.l     newstack(a4),a1
  430.         move.l     AbsExecBase.W,A6
  431.         callsys    FreeMem
  432.         endc
  433.  
  434. exit4:
  435. exitToDOS:
  436.         move.l     AbsExecBase.W,a6
  437.  
  438. *------ Restore the original exception handler
  439.         ifd    CATCH
  440.         move.l        ThisTask(a6),A3
  441.         move.l        oldtrapdata(A4),TC_TRAPDATA(a3)
  442.         move.l        oldtrapcode(A4),TC_TRAPCODE(a3) * check current exception
  443.          ifd         AUTOREQ
  444.           move.l        IntuiBase(a4),a1
  445.           callsys         CloseLibrary                * close Intuition library
  446.          endc
  447.         ENDC
  448.  
  449. *------ free the command line buffer
  450.         move.l     Commandlen(a4),d0
  451.         beq.s      nodofree
  452.         move.l     Commandbuf(a4),a1
  453.         callsys    FreeMem
  454.  
  455. *------ this rts sends us back to DOS:
  456. nodofree:
  457.         move.l     DOSBase(A4),a1
  458.         callsys    CloseLibrary              * close Dos library
  459.  
  460.         IFD        RESIDENT
  461.         move.l     realdatasize(a4),d0
  462.         move.l     a4,a1
  463.         sub.l      #RESBASE,a1
  464.         callsys    FreeMem
  465.         ENDC
  466.         move.l     (a7)+,d0
  467.  
  468. return:
  469.         movem.l    (a7)+,d1-d6/a0-a6
  470.         rts
  471.  
  472. DOSName dc.b    'dos.library',0
  473. RCSId   dc.b    '$Id: c.asm,v 1.6 1993/09/14 23:13:22 simons Stab simons $'
  474.         dc.w    0
  475.  
  476.         ifd        CATCH
  477. *-----------------------------------------------------------------------
  478. *        Open the Intuition library:
  479.  
  480. openIntui:
  481.         lea        IntuiName(PC),A1
  482.         moveq.l    #0,D0
  483.         callsys    OpenLibrary
  484.         move.l     D0,IntuiBase(A4)
  485.         beq.s      noDOS
  486.         rts
  487.  
  488. *-----------------------------------------------------------------------
  489. noDOS:
  490.                 moveq.l #100,d0
  491.                 bra.w   exit2
  492.  
  493.  
  494. IntuiName  dc.b        'intuition.library',0
  495.  
  496. *-----------------------------------------------------------------------
  497. *        The Exception Handler - catches GURUs and exits (semi)cleanly
  498. Exception:
  499.         movem.l    a0,-(a7)
  500.         move.l     AbsExecBase.W,a0
  501.         move.l     ThisTask(a0),a0
  502.         move.l     TC_TRAPDATA(a0),a0        * ...and data
  503.         move.l     (sp)+,ADump(a0)           * save a0
  504.         move.l     d0,ADump+4(a0)            * and d0
  505.  
  506.         move.l     (a7)+,d0                  * get exception # from stack
  507.         move.l     d0,GURUNum(a0)            * and save it
  508.         cmpi.l     #3,d0                     * ADDRESS or BUS error?
  509.         bgt.s      1$                        * no, skip adjustment
  510.         btst       #0,Environment+3(a0)      * is it 68010 or 68020?
  511.         bne.s      1$                        * 0 means NO
  512.         addq.l     #8,a7                     * adjust for 68000
  513. 1$:
  514.         move.l     2(a7),d0                  * get PC at crash
  515.         move.l     d0,GURUAddr(a0)           * and save it
  516.         move.l     ADump+4(a0),d0            * restore a0 and d0
  517.         move.l     ADump(a0),a0
  518.         move.l     #GURUExit,2(a7)           * use our own exit point
  519.         rte
  520.  
  521. *-----------------------------------------------------------------------
  522. *        The Exception exit routine - write 'PGTB' IFF chunk to file
  523. *        'SnapShot.TB' in current directory, then exit to system.
  524.  
  525. GURUExit:
  526.         movem.l    d0-d7/a0-a7,-(sp)         * save all registers
  527.         move.l     AbsExecBase.W,a6          * make sure we are working with Exec
  528.         callsys    GetCC                     * safe way - works with all CPUs
  529.         move.l     ThisTask(a6),a3
  530.         move.l     TC_TRAPDATA(a3),a4        * make sure we have a valid # in a4
  531.         move.l     d0,Flags(a4)              * save area
  532.         movem.l    (sp)+,d0-d7
  533.         movem.l    d0-d7,DDump(a4)           * save data reg contents
  534.         movem.l    (sp)+,d0-d7
  535.         movem.l    d0-d7,ADump(a4)           * save address reg contents
  536.         tst.l      StackPtr(a4)              * if there's something there
  537.         bne        GExit1                    * ...we've been here before!
  538.         lea        TempStore(a4),a0          * calculate addr of TempStore
  539.         move.l     a0,TempAddr(a4)           * ...and save for later access
  540.         move.l     A7Store(a4),d0            * make sure we have proper TOS
  541.         move.l     d0,StackPtr(a4)           * ...and save it
  542.         moveq      #0,d0
  543.         move.l     _ProgramName(a4),a0       * find length of program name
  544.  
  545.         ifd        AUTOREQ
  546.         move.l     a0,PName(a4)
  547.         endc
  548.  
  549.         subq.l     #1,a0
  550.         move.b     (a0),d0
  551.         addq.l     #4,d0                     * adjust for shift
  552.         lsr.l      #2,d0
  553.         move.l     d0,NameLen(a4)            * store length
  554.         add.l      d0,FAILlen(a4)            * and sub-chunk total
  555.  
  556.         moveq      #0,d0                     * clear d0 for use
  557.         lea        VBlankFrequency(a6),a0    * set up a0 to find correct data
  558.         move.b     (a0)+,d0                  * get just in case
  559.         move.l     d0,VBlankFreq(a4)         * ...so we can figure what
  560.         move.b     (a0),d0                   * ...type of machine
  561.         move.l     d0,PowerSupFreq(a4)       * ...we're working on
  562.  
  563.         lea        start-4(pc),a0            * get seglist ptr
  564.         moveq      #-1,d0                    * always at least 1
  565. 2$:
  566.         addq.l     #1,d0
  567.         move.l     (a0),d1                   * find end of list
  568.         beq.s      3$
  569.         lsl.l      #2,d1                     * BPTR!!!!!
  570.         move.l     d1,a0
  571.         bra.s      2$
  572. 3$:
  573.         add.l      d0,SegCount(a4)           * store # of seglist pointers
  574.         lsl.l      #1,d0                     * multiply by 2 for longword count
  575.         add.l      d0,FAILlen(a4)            * and sub-chunk length
  576.  
  577.         move.l     StackTop(a4),d0           * get top of stack
  578.         sub.l      StackPtr(a4),d0           * find number of bytes used
  579.         addq.l     #4,d0                     * adjust for longword conversion
  580.         lsr.l      #2,d0                     * convert from bytes to long
  581.         move.l     d0,StackLen(a4)           * and save
  582.         add.l      d0,s2len(a4)              * and sub-chunk total
  583.  
  584.         move.l     a5,-(sp)                  * save a5 for later
  585.         callsys    Forbid                    * don't let 'em change while we ask
  586.         move.l     MemList+LH_HEAD(a6),d0    * first node in MemList
  587. checkchip:
  588.         move.l     d0,a5                     * move node address to address reg
  589.         move.w     MH_ATTRIBUTES(a5),d4      * get node attributes
  590.         btst       #MEMB_CHIP,d4             * is it chip?
  591.         beq.s      checkfast                 * no, go on
  592.         lea        chipAvail(a4),a3
  593.         bsr.w      AddIt
  594. checkfast:
  595.         btst       #MEMB_FAST,d4             * is it fast?
  596.         beq.s      next                      * no, go on
  597.         lea        fastAvail(a4),a3
  598.         bsr.w      AddIt
  599. next:
  600.         move.l     LN_SUCC(a5),d0            * get address of next node
  601.         bne.s      checkchip                 * ...and loop back if valid
  602.         callsys    Permit                    * allow others access again
  603.         move.l     #MEMF_CHIP+MEMF_LARGEST,d1 * to find largest hunk in chip ram
  604.         callsys    AvailMem
  605.         move.l     d0,chipLargest(a4)         * store
  606.         move.l     #MEMF_FAST+MEMF_LARGEST,d1 * to find largest hunk in fast ram
  607.         callsys    AvailMem
  608.         move.l     d0,fastLargest(a4)        * store
  609.         move.l     (sp)+,a5                  * and restore a5
  610.  
  611.         ifd        AUTOREQ
  612.         moveq      #0,d0                     * PosFlag
  613.         move.l     d0,d1                     * NegFlag
  614.         move.l     d0,a0                     * 0 means use current window
  615.         lea        IText1(a4),a1             * Body Text
  616.         lea        IText5(a4),a2             * Positive Gadget Text
  617.         lea        IText6(a4),a3             * Negative Gadget Text
  618.         moveq      #1,d2
  619.         lsl.l      #8,d2                     * quick way to set Width
  620.         moveq      #76,d3                    * Height
  621.         move.l     IntuiBase(a4),a6          * get intuition library pointer
  622.         jsr        -$15c(A6)                 * callsys       AutoRequest
  623.         move.l     AbsExecBase.W,a6
  624.         tst.l      d0                        * save SnapShot?
  625.         beq.w      GExit2                    * no, just exit
  626.         endc
  627.  
  628.         move.l     DOSBase(a4),a6
  629.         lea        DumpName(a4),a0           * get name of output file
  630.         move.l     a0,d1
  631.         move.l     #MODE_NEWFILE,d2          * create new file
  632.         callsys    Open
  633.         bne.s      4$
  634.         lea        DumpPath(a4),a0           * if error in current dir, try DF1:
  635.         move.l     a0,d1
  636.         move.l     #MODE_NEWFILE,d2
  637.         callsys    Open
  638.         bne.s      4$
  639.         move.b     #'0',DumpPath+2(a4)       * still error?  Try DF0:
  640.         lea        DumpPath(a4),a0
  641.         move.l     a0,d1
  642.         move.l     #MODE_NEWFILE,d2
  643.         callsys    Open
  644.  
  645.         ifnd        AUTOREQ
  646.         bne.s      4$                        * if no error, continue (finally!)
  647.         move.l     GConsole(a4),d1
  648.         beq.w      GExit2
  649.         lea        failmsg(a4),a0
  650.         move.l     a0,d2
  651.         move.l     #23,d3
  652.         callsys    Write
  653.         endc
  654.  
  655.         bra.w      GExit2                    * else, print msg & DIE gracefully
  656. 4$:
  657.         move.l     d0,d5                     * save file handle for Write
  658.         move.l     d0,fp(a4)                 * ...and in a safe place for later
  659.         move.l     d5,d1                     * get file handle
  660.         lea        PGTB(a4),a0               * first part of fixed
  661.         move.l     a0,d2
  662.         move.l     #chunk_len_1,d3           * length of first
  663.         callsys    Write                     * ...since it gets written over
  664.  
  665.         move.l     d5,d1                     * get file handle
  666.         move.l     _ProgramName(a4),d2       * get address of program name
  667.         move.l     NameLen(a4),d3            * get # longs in program name
  668.         lsl.l      #2,d3                     * ..and convert to bytes
  669.         callsys    Write
  670.  
  671.         move.l     d5,d1                     * get file handle
  672.         lea        Environment(a4),a0        * second part of fixed
  673.         move.l     a0,d2
  674.         move.l     #chunk_len_2,d3           * length of second part
  675.         callsys    Write
  676.  
  677.         lea        start-8(pc),a0            * address of seglist (size of seg)
  678.         move.l     (a0)+,d0                  * segsize
  679.         move.l     d0,TempStore+4(a4)        * save it
  680.         move.l     a0,TempStore(a4)          * store first number
  681.         move.l     SegCount(a4),d4
  682. 5$:
  683.         move.l     d5,d1                     * get file handle
  684.         move.l     TempAddr(a4),d2           * address of write buffer
  685.         moveq      #TempSize,d3              * size of segment pointer
  686.         callsys    Write
  687.         move.l     TempStore(a4),a0          * retrieve pointer
  688.         move.l     (a0),d0                   * get next seg pointer
  689.         lsl.l      #2,d0                     * adjust
  690.         move.l     d0,TempStore(a4)          * ..and save
  691.         move.l     d0,a0
  692.         beq.b      donesegs                  * last segment?
  693.         move.l     -4(a0),d0                 * get segsize
  694.         move.l     d0,TempStore+4(a4)        * ...and save it
  695.         subq.l     #1,d4                     * done yet?
  696.         bne.s      5$                        * no, do next
  697.  
  698. donesegs:
  699.         tst.l      _FMEM(a4)                 * do they want memory reported?
  700.         beq.s      55$                       * no, forget it
  701.         move.l     d5,d1
  702.         lea        subFMEM(a4),a0
  703.         move.l     a0,d2
  704.         move.l     #FMEMlen,d3
  705.         callsys    Write
  706.  
  707. 55$:
  708.         move.l     d5,d1                     * (get the idea?)
  709.         lea        subREGS(a4),a0            * third part of fixed
  710.         move.l     a0,d2
  711.         move.l     #chunk_len_3,d3           * length of third
  712.         callsys    Write
  713.  
  714.         move.l     StackLen(a4),d0           * get length of stack used
  715.         cmpi.l     #2048,d0                  * > 8k ?
  716.         bgt.s      6$                        * yes, dump two chunks
  717.         move.l     d5,d1
  718.         lea        STAK2(a4),a0              * whole stack chunk
  719.         move.l     a0,d2
  720.         moveq      #STAK2len,d3              * length of fixed part
  721.         callsys    Write
  722.  
  723.         move.l     d5,d1
  724.         move.l     StackPtr(a4),d2           * address of stack
  725.         move.l     StackLen(a4),d3           * get # longwords on stack
  726.         lsl.l      #2,d3                     * ..and convert to bytes
  727.         callsys    Write
  728.         bra.s      7$
  729. 6$:
  730.         move.l     d5,d1
  731.         lea        STAK3(a4),a0              * top4k chunk
  732.         move.l     a0,d2
  733.         moveq      #STAK3len,d3              * length of fixed part
  734.         callsys    Write
  735.  
  736.         move.l     d5,d1
  737.         move.l     StackTop(a4),d2           * find top of stack
  738.         sub.l      #4096,d2                  * find top-4k
  739.         move.l     #4096,d3                  * # bytes to write
  740.         callsys    Write
  741.  
  742.         move.l     d5,d1
  743.         lea        STAK4(a4),a0              * bottom4k chunk
  744.         move.l     a0,d2
  745.         moveq      #STAK4len,d3              * length of fixed part
  746.         callsys    Write
  747.  
  748.         move.l     d5,d1
  749.         move.l     StackPtr(a4),d2           * current stack address
  750.         move.l     #4096,d3                  * # bytes to write
  751.         callsys    Write
  752. 7$:
  753.         move.l     _STAKOffset(a4),d3
  754.         beq.s      8$
  755.         lsr.l      #2,d3
  756.         addq.l     #1,d3
  757.         move.l     d3,_STAKOffset(a4)
  758.         addq.l     #1,d3
  759.         move.l     d5,d1
  760.         lea        STAK5(a4),a0
  761.         move.l     a0,d2
  762.         moveq      #STAK5len,d3
  763.         callsys    Write
  764.  
  765.         move.l     d5,d1
  766.         move.l     StackPtr(a4),d2
  767.         move.l     _STAKOffset(a4),d3
  768.         subq.l     #1,d3
  769.         move.l     StackLen(a4),d4
  770.         cmp.l      d3,d4
  771.         bge.s      75$
  772.         move.l     StackLen(a4),d3
  773. 75$:
  774.         lsl.l      #2,d3
  775.         callsys    Write
  776. 8$:
  777.         tst.l      _ONGURU(A4)               * user GURU function?
  778.         beq.s      9$
  779.         move.l     d5,-(sp)
  780.         move.l     d5,d1
  781.         lea        UDAT(a4),a0
  782.         move.l     a0,d2
  783.         move.l     #UDATlen,d3
  784.         callsys    Write
  785.         move.l     d5,d1
  786.         moveq      #0,d2                     * zero offset
  787.         moveq      #1,d3                     * ...from EOF
  788.         callsys    Seek
  789.         move.l     d0,SeekStore(a4)
  790.         move.l     _ONGURU(a4),a0
  791.         jsr        (a0)
  792.         addq.l     #4,sp
  793. 9$:
  794.         move.l     fp(a4),d5
  795.         move.l     d5,d1
  796.         moveq      #0,d2                     * offset from EOF
  797.         moveq      #1,d3                     * OFFSET_END
  798.         callsys    Seek                      * Seek returns OLD position
  799.         move.l     d0,d1
  800.         andi.l     #3,d1                     * did user write even longwords?
  801.         beq.s      10$                       * Yep!        Nice Human.
  802.         move.l     d1,d6                     * Nope, save for later.
  803.         clr.l      TempStore(a4)             * clear temp storage
  804.         move.l     d5,d1
  805.         move.l     TempAddr(a4),d2
  806.         moveq      #4,d3
  807.         sub.l      d6,d3                     * find how many NULLs to pad
  808.         callsys    Write
  809.         bra.s      9$
  810. 10$:
  811.         tst.l      SeekStore(a4)             * did we write UDAT?
  812.         beq.s      11$                       * nope!
  813.         sub.l      SeekStore(a4),d0          * find length of UDAT section
  814.         lsr.l      #2,d0                     * adjust to longwords
  815.         move.l     d0,TempStore(a4)          * save UDAT length for write
  816.         move.l     d5,d1
  817.         move.l     SeekStore(a4),d2          * find where to write it
  818.         subq.l     #4,d2
  819.         moveq      #-1,d3                    * OFFSET_BEGINNING
  820.         callsys    Seek
  821.         move.l     d5,d1
  822.         move.l     TempAddr(a4),d2
  823.         move.l     #4,d3
  824.         callsys    Write                     * write length of UDAT field to file
  825. 11$:
  826.         move.l     d5,d1
  827.         moveq      #0,d2                     * offset to 'Length' field
  828.         moveq      #1,d3                     * OFFSET_END
  829.         callsys    Seek                      * make sure we are at end of file
  830.         move.l     d5,d1
  831.         moveq      #4,d2                     * offset to 'Length' field
  832.         moveq      #-1,d3                    * OFFSET_BEGINNING
  833.         callsys    Seek
  834.         subq.l     #8,d0                     * adjust total length
  835.         lsr.l      #2,d0                     * adjust to longwords
  836.         move.l     d0,TempStore(a4)          * save for write
  837.         move.l     d5,d1
  838.         move.l     TempAddr(a4),d2
  839.         move.l     #4,d3
  840.         callsys    Write                     * write 'Length' field
  841. GExit1:
  842.         move.l     fp(a4),d1
  843.         beq.s      GExit2
  844.         move.l     DOSBase(a4),a6
  845.         callsys    Close
  846.  
  847.         ifnd        AUTOREQ
  848.         move.l      GConsole(a4),d1
  849.         beq.s       GExit2
  850.         lea         success(a4),a0
  851.         move.l      a0,d2
  852.         move.l      #32,d3
  853.         callsys     Write
  854.         endc
  855.  
  856. GExit2:
  857.         move.l       TaskID(a4),a6
  858.         move.l       AbsExecBase.W,a6
  859.         moveq        #$47,d0
  860.         bra.w        exit2
  861.  
  862. *-----------------------------------------------------------------------
  863. * AddIt:        routine to add memory parts to variables
  864.  
  865. AddIt:
  866.         move.l       MH_FREE(a5),d0
  867.         add.l        d0,(a3)                 * add to available
  868.         move.l       MH_UPPER(a5),d0
  869.         sub.l        MH_LOWER(a5),d0
  870.         add.l        d0,4(a3)                * add to Max section
  871.         rts
  872.         endc
  873.  
  874.  
  875.         IFD     CATCH
  876.         section __MERGED,DATA
  877. _ONGURU        dc.l        0
  878. IntuiBase      dc.l        0
  879. TaskID         dc.l        0
  880. oldtrapcode    dc.l        0
  881. oldtrapdata    dc.l        0
  882.  
  883.         ifnd        AUTOREQ
  884. GConsole        dc.l        0
  885. failmsg         dc.b        7,'Can''t write SnapShot!',10
  886. success         dc.b        7,'GURU caught; SnapShot written!',10
  887.         endc
  888.  
  889.         cnop        0,4
  890. _FMEM           dc.l        0
  891. fp              dc.l        0                  * save SnapShot file pointer
  892. DumpPath        dc.b        'DF1:'
  893. DumpName        dc.b        'SnapShot.TB',0
  894. SeekStore       dc.l        0
  895. TempAddr        dc.l        0                  * Storage for &TempStore
  896. TempStore       dc.l        0,0                * Temporary storage for BPTR -> APTR
  897. TempSize        equ        *-TempStore
  898.  
  899.         cnop        0,4
  900.         ifd        AUTOREQ
  901. TAttr:                                         * Text attributes for font
  902.         dc.l        TName                      * name of font
  903.         dc.w        TOPAZ_EIGHTY               * font size
  904.         dc.b        FS_NORMAL                  * font style
  905.         dc.b        FPF_ROMFONT                * font preferences
  906. TName:
  907.         dc.b        'topaz.font',0
  908.         cnop        0,4
  909.  
  910. IText1:                                        * Text definitions for AutoReq call
  911.         dc.b        3,0,RP_JAM1,0              * front & back pens, drawmode and filler byte
  912.         dc.w        6,4                        * XY origin relative to container TopLeft
  913.         dc.l        TAttr                      * font pointer or NULL for default
  914.         dc.l        ITextText1                 * pointer to text
  915.         dc.l        IText2                     * next IntuiText structure
  916. ITextText1:
  917.         dc.b        'Program:',0
  918.         cnop 0,4
  919. IText2:
  920.         dc.b        3,0,RP_JAM1,0
  921.         dc.w        78,4
  922.         dc.l        TAttr
  923. PName   dc.l        0
  924.         dc.l        IText3
  925.         cnop        0,4
  926. IText3:
  927.         dc.b        3,0,RP_JAM1,0
  928.         dc.w        55,16
  929.         dc.l        TAttr
  930.         dc.l        ITextText3
  931.         dc.l        IText4
  932. ITextText3:
  933.         dc.b        'I caught a GURU!',0
  934.         cnop 0,4
  935. IText4:
  936.         dc.b        3,0,RP_JAM1,0
  937.         dc.w        20,28
  938.         dc.l        TAttr
  939.         dc.l        ITextText4
  940.         dc.l        0
  941. ITextText4:
  942.         dc.b        'Should I make a SnapShot?',0
  943.         cnop 0,4
  944. IText5:
  945.         dc.b        3,0,RP_JAM2,0
  946.         dc.w        6,3
  947.         dc.l        TAttr
  948.         dc.l        ITextText5
  949.         dc.l        0
  950. ITextText5:
  951.         dc.b        'YES',0
  952.         cnop 0,4
  953. IText6:
  954.         dc.b        3,0,RP_JAM2,0
  955.         dc.w        6,3
  956.         dc.l        TAttr
  957.         dc.l        ITextText6
  958.         dc.l        0
  959. ITextText6:
  960.         dc.b        'NO',0
  961.         endc
  962.  
  963.         cnop 0,4
  964.  
  965. *--------------------------------------------------------------------------
  966. * New IFF chunk format -
  967. *        PGTB = Program Traceback, header for chunk
  968. *        FAIL = reason for and environment of crash
  969. *        REGS = registers at time of crash, including PC and CCR
  970. *        VERS = version, revision, name of this program
  971. *        STAK = ENTIRE stack at time of crash or, alternately,
  972. *                the top and bottom 4k if the stack used is > 8k
  973. *        UDAT = optional user data dump (if _ONGURU is set to a
  974. *                function pointer in the user's program)
  975. *--------------------------------------------------------------------------
  976.  
  977. PGTB            dc.b        'PGTB'
  978. Length          dc.l        0                * length of chunk (in longwords)
  979.  
  980. subFAIL         dc.b        'FAIL'
  981. FAILlen         dc.l        9
  982. NameLen         dc.l        0                * length of program name
  983. chunk_len_1     equ         *-PGTB
  984. Environment     dc.l        0                * CPU (, Math)
  985. VBlankFreq      dc.l        0                *        PAL = 50, NTSC = 60 (approx.)
  986. PowerSupFreq    dc.l        0                * Europe = 50,        USA = 60 (approx.)
  987. Starter         dc.l        0                * 0 = WB, -1 = CLI
  988. GURUNum         dc.l        0                * cause of crash (GURU #)
  989. SegCount        dc.l        1                * # hunks in seglist
  990. chunk_len_2     equ         *-Environment
  991.  
  992. subFMEM         dc.b        'FMEM'           * FMEM - free memory at crash
  993.                 dc.l        6
  994. chipAvail       dc.l        0                * available chip memory
  995. chipMax         dc.l        0                *        maximum chip memory
  996. chipLargest     dc.l        0                *        largest chip memory
  997. fastAvail       dc.l        0                * available fast memory
  998. fastMax         dc.l        0                *        maximum fast memory
  999. fastLargest     dc.l        0                *        largest fast memory
  1000. FMEMlen         equ         *-subFMEM
  1001.  
  1002. subREGS         dc.b        'REGS'           * REGS - register storage field
  1003. REGSlen         dc.l        18
  1004. GURUAddr        dc.l        0                * PC at time of crash
  1005. Flags           dc.l        0                * Condition Code Register (CCR)
  1006. DDump           dc.l        0,0,0,0,0,0,0,0  * data registers
  1007. ADump           dc.l        0,0,0,0,0,0,0    * address registers
  1008. A7Store         dc.l        0
  1009.  
  1010. subVERS         dc.b        'VERS'           * VERS - program version field
  1011.                 dc.l        6
  1012.                 dc.l        VERSION          * version #
  1013.                 dc.l        REVISION         * revision #
  1014.                 dc.l        3                * length of name of program
  1015.                 IFD        RESIDENT
  1016.                 dc.b        'catchres.o',0,0 * name
  1017.                 ENDC
  1018.                 IFND        RESIDENT
  1019.                 dc.b        'catch.o   ',0,0 * name
  1020.                 ENDC
  1021.  
  1022. subSTAK         dc.b        'STAK'           * STAK - stack field
  1023. STAKlen         dc.l        4
  1024. Type            dc.l        0                * 0 = Info
  1025. StackTop        dc.l        0                * top of stack pointer
  1026. StackPtr        dc.l        0                * current Stack Pointer
  1027. StackLen        dc.l        0                * # bytes used on stack
  1028. chunk_len_3     equ         *-subREGS
  1029.  
  1030. STAK2           dc.b        'STAK'
  1031. s2len           dc.l        1                * length of subtype
  1032.                 dc.l        1                * 1 = whole stack
  1033. STAK2len        equ         *-STAK2
  1034.  
  1035. STAK3           dc.b        'STAK'
  1036.                 dc.l        1025
  1037.                 dc.l        2                * 2 = top 4k of stack
  1038. STAK3len        equ         *-STAK3
  1039.  
  1040. STAK4           dc.b        'STAK'
  1041.                 dc.l        1025
  1042.                 dc.l        3                * 3 = bottom 4k of stack
  1043. STAK4len        equ         *-STAK4
  1044.  
  1045. STAK5           dc.b        'STAK'
  1046. _STAKOffset     dc.l        0
  1047.                 dc.l        4                * 4 = user defined amount
  1048. STAK5len        equ         *-STAK5
  1049.  
  1050. UDAT            dc.b        'UDAT'
  1051.                 dc.l        0
  1052. UDATlen         equ         *-UDAT
  1053.         endc
  1054.  
  1055.  
  1056.  
  1057.         section __MERGED,BSS
  1058.  
  1059.         xref    DOSBase
  1060.  
  1061.         xdef    NULL,SysBase,_WBenchMsg
  1062.         xdef    __curdir
  1063.         xdef    _OSERR,_FPERR,_SIGFPE,_ONERR,_ONEXIT,_ONBREAK
  1064.         xdef    _SIGINT
  1065.         xdef    _ProgramName,_StackPtr,__base
  1066.         ifd        CATCH
  1067.         xdef        _ONGURU,_FMEM,_STAKOffset
  1068.         endc
  1069.  
  1070.  
  1071.  
  1072. NULL         ds.b    4
  1073. __base       ds.b    4                   * base of stack
  1074. _OSERR       ds.b    4
  1075. _FPERR       ds.b    4
  1076. _SIGFPE      ds.b    4
  1077. _SIGINT      ds.b    4
  1078. _ONERR       ds.b    4
  1079. _ONEXIT      ds.b    4
  1080. _ONBREAK     ds.b    4
  1081. __curdir     ds.b    4
  1082. SysBase      ds.b    4
  1083. _WBenchMsg   ds.b    4
  1084. _StackPtr    ds.b    4
  1085. _ProgramName ds.b    4
  1086. Commandbuf   ds.b    4
  1087. Commandlen   ds.b    4
  1088.  
  1089.         ifd        RESIDENT
  1090. realdatasize ds.b    4                   * size of memory allocated for data +
  1091.                                          * possible stack
  1092.         endc
  1093.         ifnd       RESIDENT
  1094. newstack     ds.b    4                   * pointer to new stack (if needed)
  1095. newstacksize ds.b    4                   * size of new stack
  1096.         endc
  1097.  
  1098.              END
  1099.