home *** CD-ROM | disk | FTP | other *** search
/ GEMini Atari / GEMini_Atari_CD-ROM_Walnut_Creek_December_1993.iso / files / program / relmod / relmod.asm < prev   
Encoding:
Assembly Source File  |  1987-08-24  |  11.4 KB  |  409 lines

  1. *
  2. *    New version of relmod.
  3. *    Made by J.A.M.Vermaseren, 17-12-1986.
  4. *    Public domain. This program may be copied for free only.
  5. *    Anybody selling public domain disks with whatever tiny profit
  6. *    beyond the direct costs should send me Dfl 2,-- per copy ( $1 ).
  7. *    My address : J.Vermaseren, Leerdamhof 441, 1108CL Amsterdam.
  8. *    Be fair : If you get something for the trouble I want something
  9. *    for mine.
  10. *
  11. ******************************************************************************
  12. *                                         *
  13. *    Variables in the heap :    ( a6 is heap pointer )                 *
  14. *                                         *
  15. *    0    Number of characters read into input buffer             *
  16. *    4    Output error information from reloc.                 *
  17. *    8    Last relocation address.                     *
  18. *    12    Little trap routine.                         *
  19. *    24    Input name.                             *    
  20. *                                         *
  21. *    Variables in the registers :                         *
  22. *                                         *
  23. *    d7    Input file handle                         *
  24. *    d6    Output file handle                         *
  25. *    d5    (reloc) characters in output buffer                 *
  26. *    d4    (reloc)    characters in input buffer                 *
  27. *    d3    Length of the buffers                         *
  28. *    d2    (reloc)    Distance to start of text                 *
  29. *    a5    Output buffer                             *
  30. *    a4    (reloc) Input buffer                         *
  31. *    a3    (reloc) Next position in output buffer                 *
  32. *    a2    (reloc) Next position in input buffer                 *    
  33. *                                         *
  34. ******************************************************************************
  35. *
  36. *    The startup is done in a particular way, to build the heap before
  37. *    the setblock is done. The Atari ROM refuses to execute trap functions
  38. *    and return to the ROM safely. This way a little routine like
  39. *        move.l    (sp)+,offset+8(a6)
  40. *        trap    #1
  41. *        jmp    unimportant
  42. *    can be put at offset(a6) and all trap #1 replaced by jmp offset(a6).
  43. *    In this program offset is 12, so jmp 12(a6) is equivalent to trap #1
  44. *    This has to be done before the first trap call, ie the setblock.
  45. *
  46. start:    move.l    4(sp),a3        * Base page address.
  47.     move.l    12(a3),d0        * Length of text.
  48.     add.l    20(a3),d0        * Initialized data.
  49.     add.l    28(a3),d0        * Uninitialized data.
  50.     add.l    #$100,d0        * + 100 bytes basepage.
  51.     lea    (a3,d0.l),a6        * Heap pointer.
  52.     add.l    #$200,d0        * Heap + stack space.
  53.     move.l    sp,d3            * Top of available memory.
  54.     lea    (a3,d0.l),sp        * Install new stack pointer
  55.     sub.l    sp,d3            * Available for copying.
  56.     andi.l    #$FFFFF800,d3        * Make multiple of 2048.
  57.     beq    nomemory        * Not enough memory.
  58.     add.l    d3,d0            * Total memory requirement.
  59.     lsr.l    #1,d3            * Space for each buffer.
  60.     move.l    sp,-(sp)        * Input buffer for later.
  61.     lea    (sp,d3.l),a5        * Output buffer.
  62. *
  63. *    Just for fun. I don't expect you to put it in the ROM cartridge.
  64. *
  65.     move.l    #$2D5F0014,12(a6)    * move.l (sp)+,20(a6)
  66.     move.l    #$4E414EF9,16(a6)    * trap     #1
  67. *                    * jmp     .....
  68. *
  69.     move.l    d0,-(sp)        * Total reservation.
  70.     move.l    a3,-(sp)        * Start address.
  71.     clr.w    -(sp)            * For GEMDOS. It eats its stack!!!!!!
  72.     move.w    #$4A,-(sp)        * Setblock.
  73.     jsr    12(a6)            * This is trap #1
  74.     lea    12(sp),sp        * Reset the stack.
  75.     tst.l    d0
  76.     bne    nomemory
  77. *
  78. *    Study the command tail. Problem : What if there ain't any.
  79. *    Normally : Pascal string : One byte with the length of the rest, and
  80. *                   then the rest.
  81. *    Is none     : 60,1A or something. So if 60, then look at offset 18. If
  82. *           no tail there is a zero there. With tail there ain't.
  83. *
  84.     lea    $80(a3),a4        * The beginning of the command tail
  85.     moveq.l    #0,d5
  86.     move.b    (a4)+,d5        * String length. String at a4.
  87.     beq    notail            * Length 0.
  88.     cmpi.w    #$60,d5
  89.     bne    istail            * There is a command tail.
  90.     tst.b    17(a4)
  91.     beq    notail            * No commmand tail --> error message.
  92. istail:    lea    (a4,d5.w),a3        * First address beyond the tail.
  93.     moveq.l    #0,d0
  94.     moveq.l    #$20,d2            * This is a blank.
  95. loop1:    move.b    (a4)+,d0        * Get one character.
  96.     cmp.b    d2,d0
  97.     beq    loop1            * Strip leading blanks.
  98.     cmpi.b    #$2D,d0
  99.     bne    nodash
  100.     move.b    (a4)+,d0        * Skip a dash.
  101. nodash:    cmp.l    a4,a3            * Do we have a nontrivial character ?
  102.     blt    notail
  103.     lea    24(a6),a0        * For storage.
  104.     move.l    a0,a1            * For later to find the extention.
  105.     move.l    a0,a2            * Keep track of the '.'
  106. loop2:    cmp.b    #$2E,d0
  107.     bne    loop2a
  108.     move.l    a0,a2            * Address of the last period
  109. loop2a:    move.b    d0,(a0)+
  110.     move.b    (a4)+,d0
  111.     cmp.b    d2,d0            * Go till blank or end of tail
  112.     beq    endpar
  113.     cmp.l    a4,a3
  114.     bge    loop2            * A good character --> copy.
  115. endpar:
  116.     cmp.l    a2,a1            * Was there a period ?
  117.     bne    fullnm            * Got a full name.
  118.     move.l    a0,a2
  119.     move.b    #$2E,(a0)+        * '.'
  120.     move.b    #$36,(a0)+        * '6'
  121.     move.b    #$38,(a0)+        * '8'
  122.     move.b    #$4B,(a0)+        * 'K'
  123. fullnm:    clr.b    (a0)
  124.     clr.w    -(sp)            * Reading this file only.
  125.     move.l    a1,-(sp)        * Address of the file name.
  126.     move.w    #$3D,-(sp)        * Fopen.
  127.     jsr    12(a6)            * This is trap #1
  128.     addq.l    #8,sp
  129.     tst.l    d0            * Did the file get opened?
  130.     bmi    filerr
  131.     move.l    d0,d7            * Store the handle.
  132. *
  133.     moveq.l    #0,d0
  134. loop3:    move.b    (a4)+,d0
  135.     cmp.b    d2,d0
  136.     beq    loop3
  137.     cmp.l    a4,a3
  138.     bmi    only1            * Only one parameter --> transform.
  139.     lea    -1(a4),a1        * Start of second name.
  140. loop4:    move.b    (a4)+,d0
  141.     cmp.b    d2,d0
  142.     beq    param2
  143.     cmp.l    a4,a3
  144.     bge    loop4
  145.     bra    param2
  146. only1:    lea    1(a2),a4
  147.     move.b    #$50,(a4)+
  148.     move.b    #$52,(a4)+
  149.     move.b    #$47,(a4)+
  150.     addq.l    #1,a4
  151. param2:    subq.l    #1,a4
  152.     move.b    (a4),d4            * Save old character
  153.     clr.b    (a4)            * End on 0 for GEMDOS.
  154.     clr.w    -(sp)            * Read and write.
  155.     move.l    a1,-(sp)
  156.     move.w    #$3C,-(sp)        * Fcreate
  157.     jsr    12(a6)            * This is trap #1
  158.     addq.l    #8,sp
  159.     move.b    d4,(a4)            * Restore old character.
  160.     tst.l    d0
  161.     bmi    filer2
  162.     move.l    d0,d6            * Save the output handle.
  163. *
  164. *    Now we have two opened files and the buffers are ready.
  165. *
  166.           move.l    (sp)+,a4        * Input buffer.
  167.     bsr    reloc            * Make the relocation table.
  168.     move.w    d6,-(sp)        * Output file.
  169.     bsr    fclose
  170.     move.w    d7,(sp)            * Input file.
  171.     bsr    fclose
  172.     addq.l    #2,sp
  173.     move.w    4(a6),-(sp)        * Error code from reloc ( or none ).
  174.     move.w    #$4C,-(sp)        * Pterm: exit with possible error code.
  175.     jsr    12(a6)            * This is trap #1
  176. *
  177. *    Error messages when a file cannot be opened.
  178. *
  179. filer2:    move.w    d7,-(sp)
  180.     bsr    fclose            * First close the input file.
  181.     addq.l    #2,sp
  182. *
  183. filerr:    pea    nofil(pc)        * First part of error message.
  184.     bsr    out_str
  185.     addq.l    #4,sp
  186.     move.l    a1,-(sp)        * Pointer to the name of the file.
  187. conti:    bsr    out_str
  188.     addq.l    #4,sp
  189.     pea    newlin(pc)        * CR+linefeed.
  190.     bsr    out_str
  191.     addq.l    #4,sp
  192.     bra    errext
  193. *
  194. nomemory:
  195.     pea    nomem(pc)        * Shortage of memory.
  196.     bra    conti
  197. *
  198. notail:    pea    use(pc)            * Show correct usage.
  199.     bsr    out_str
  200.     addq.l    #4,sp
  201. errext:
  202.     move.w    #-1,-(sp)
  203.     move.w    #$4C,-(sp)
  204.     jsr    12(a6)            * Pterm with errorflag.
  205. *
  206. use:    dc.b    'Usage: FASTREL [-]file[.68K] [output file]'
  207. newlin:    dc.b    $0D,$0A,0,0
  208. nofil:    dc.b    'Cannot open file ',0
  209. nomem:    dc.b    'Not enough memory available.',0,0
  210. errrel:    dc.b    'File error.',0
  211. *
  212. *    Close a file
  213. *
  214. fclose:    move.w    4(sp),-(sp)
  215.     move.w    #$3E,-(sp)        * Fclose
  216.     jsr    12(a6)            * This is trap #1
  217.     addq.l    #4,sp
  218.     rts
  219. *
  220. *    Routine to write a zero terminated string to the screen.
  221. *
  222. out_str:
  223.     move.l    4(sp),-(sp)
  224.     move.w    #9,-(sp)
  225.     jsr    12(a6)            * This is trap #1
  226.     addq.l    #6,sp
  227.     rts
  228. *
  229. *    The routine to make a relocation table.
  230. *
  231. reloc:    bsr    readin            * Read the first buffer.
  232.     bmi    error
  233.     moveq.l    #28,d4            * Header length.
  234.     add.l    2(a4),d4        * Text length.
  235.     add.l    6(a4),d4        * Data segment.
  236.     add.l    14(a4),d4        * Symbol table.
  237.     bsr    copyd4            * Copy this piece to the output buffer.
  238.     bmi    error
  239.     clr.l    8(a6)            * Start of relocation
  240.     moveq.l    #-4,d2            * Running counter.
  241. rloop:    addq.l    #2,d2
  242. rloopp:    addq.l    #2,d2
  243.     bsr    getone            * Get a single relocation number in d1.
  244.     bne    relend
  245.     andi.w    #7,d1
  246.     cmpi.w    #5,d1
  247.     bne    rloopp            * Not relevant on the ST.
  248.     bsr    getone            * Upper half of a long word. Get next.
  249.     bne    relend            * Originally:
  250.     subq.w    #1,d1            * 1 relative to data segment
  251.     andi.w    #7,d1            * 2 relative to text segment
  252.     cmp.w    #3,d1            * 3 relative to bss
  253.     bge    rloop            * On the ST its all relative to text.
  254. relo1:    tst.l    8(a6)            * First relocation?
  255.     bne    relo2            * No
  256.     move.l    d2,8(a6)
  257.     move.l    d2,d1
  258.     rol.l    #8,d1            * Put now the 4 bytes of d1.
  259.     bsr    putone
  260.     bne    error
  261.     rol.l    #8,d1
  262.     bsr    putone
  263.     bne    error
  264.     rol.l    #8,d1
  265.     bsr    putone
  266.     bne    error
  267.     rol.l    #8,d1
  268.     bsr    putone
  269.     beq    rloop
  270.     bra    error
  271. relo2:    move.l    d2,d1
  272.     sub.l    8(a6),d1        * Difference with the previous one.
  273.     move.l    d2,8(a6)        * The new 'previous one'
  274.     bra    relo4
  275. relo3:    move.l    d1,d2            * If > 254 --> write a 1
  276.     sub.l    #254,d2            * and subtract 254.
  277.     moveq.l    #1,d1
  278.     bsr    putone
  279.     bne    error
  280.     move.l    d2,d1
  281.     move.l    8(a6),d2        * We needed register d2 for scratch.
  282. relo4:    cmp.l    #254,d1
  283.     bgt    relo3
  284.     bsr    putone            * Put the relocation increment.
  285.     beq    rloop    
  286. error:    move.w    #-1,4(a6)        * Error code.
  287.     rts
  288. relend:    cmp.w    #-1,d0            * End of relocation.
  289.     bne    error            * Here due to e read error.
  290.     bsr    wrttail            * Empty the buffer.
  291.     move.w    #0,4(a6)        * Exit with OK code.
  292.     rts
  293. *
  294. *    Routine fills the input buffer. Returns the normal d0.
  295. *
  296. readin:    move.l    a4,-(sp)        * Input buffer.
  297.     move.l    d3,-(sp)        * Length of the buffer.
  298.     move.w    d7,-(sp)        * Handle.
  299.     move.w    #$3F,-(sp)        * Fread.
  300.     jsr    12(a6)            * This is trap #1
  301.     lea    12(sp),sp        * Restore the stack.
  302.     move.l    d0,(a6)            * Number of bytes read.
  303.     rts
  304. *
  305. *    Get one character from the input buffer. If it is empty, fill it
  306. *    or return an EOF message. Entry is 'getone'
  307. *
  308. getbuf:    cmp.l    (a6),d3        * Was it a full buffer?
  309.     bne    eof
  310.     move.l    a4,-(sp)
  311.     move.l    d3,-(sp)
  312.     move.w    d7,-(sp)
  313.     move.w    #$3F,-(sp)
  314.     jsr    12(a6)        * This is trap #1
  315.     lea    12(sp),sp
  316.     tst.l    d0
  317.     bmi    inerr
  318.     move.l    d0,(a6)
  319.     moveq.l    #0,d4
  320.     move.l    a4,a2
  321. *                * Now the main entry.
  322. getone:    cmp.l    (a6),d4        * Buffer used completely?
  323.     bge    getbuf        * Still characters in the buffer.
  324.     move.w    (a2)+,d1
  325.     addq.l    #2,d4
  326.     moveq.l    #0,d0
  327.     rts
  328. eof:    moveq.l    #-1,d0
  329. inerr:    rts
  330. *
  331. *    Routine copies the normal program segment to the output buffer.
  332. *    If this segment is longer than one buffer it is written to file and
  333. *    a new buffer is read till the leftover fits.
  334. *
  335. copyd4:    cmp.l    d4,d3            * Does it fit ?
  336.     bgt    itfits
  337.     move.l    a4,-(sp)        * The buffer.
  338.     move.l    d3,-(sp)        * Its length.
  339.     move.w    d6,-(sp)        * Output handle.
  340.     move.w    #$40,-(sp)        * Fwrite.
  341.     jsr    12(a6)            * This is trap #1
  342.     lea    12(sp),sp        * Restore the stack.
  343.     tst.l    d0
  344.     bmi    cdone
  345.     sub.l    d3,d4            * This much left.
  346.     bsr    readin            * Read a new buffer
  347.     bmi    cdone
  348.     bra    copyd4
  349. itfits:    move.l    d4,d1            * Number of bytes.
  350.     addq.l    #3,d1            * For rounding up.
  351.     lsr.l    #2,d1            * Converted to words of 4 bytes.
  352.     move.l    a4,a2
  353.     move.l    a5,a3
  354.     bra    copyl2
  355. copyl1:    move.l    (a2)+,(a3)+        * Even addresses --> use long words.
  356. copyl2:    dbra    d1,copyl1
  357.     lea    (a5,d4.l),a3        * Put the addresses right.
  358.     lea    (a4,d4.l),a2
  359.     move.l    d4,d5            * Characters in output buffer.
  360.     moveq.l    #0,d0            * No errors.
  361. cdone:    rts
  362. *
  363. *    Write the rest of the output buffer, followed by one zero if there
  364. *    was a relocation and by 4 of them if there wasn't.
  365. *
  366. wrttail:
  367.     moveq.l    #0,d1
  368.     tst.l    8(a6)            * Zero if no relocations.
  369.     bne    wrtone            * Write only one byte.
  370.     bsr    putone            * Write four zero bytes.
  371.     bne    wrtok
  372.     bsr    putone
  373.     bne    wrtok
  374.     bsr    putone
  375.     bne    wrtok
  376. wrtone:    bsr    putone
  377.     bne    wrtok
  378.     tst.l    d5
  379.     beq    wrtok
  380.     move.l    a5,-(sp)        * Output buffer.
  381.     move.l    d5,-(sp)        * Number of bytes to be written.
  382.     move.w    d6,-(sp)        * Output handle.
  383.     move.w    #$40,-(sp)        * Fwrite
  384.     jsr    12(a6)            * This is trap #1
  385.     lea    12(sp),sp
  386. wrtok:    rts
  387. *
  388. *    Routine adds one character to the output buffer. If it is full the
  389. *    buffer is emptied by writing to file. The character is expected in d1.
  390. *
  391. putone:    move.b    d1,(a3)+        * Put the character in the buffer.
  392.     addq.l    #1,d5            * One more.
  393.     cmp.l    d5,d3            * Buffer full?
  394.     bgt    putok            * No
  395.     move.l    a5,-(sp)        * Output buffer.
  396.     move.l    d5,-(sp)        * Number of characters.
  397.     move.w    d6,-(sp)        * Output handle.
  398.     move.w    #$40,-(sp)        * Fwrite.
  399.     jsr    12(a6)            * This is trap #1
  400.     lea    12(sp),sp        * Restore the stack.
  401.     move.l    a5,a3            * Start of buffer again.
  402.     cmp.l    d5,d0            * Wrote enough bytes?
  403.     bne    putex            * Return with status at ne.
  404.     moveq.l    #0,d5            * Zero bytes in buffer.
  405. putok:    moveq.l    #0,d0            * Condition is eq.
  406. putex:    rts
  407.  
  408. public:    dc.b    'Program by Jos Vermaseren 17-12-86'
  409.