home *** CD-ROM | disk | FTP | other *** search
/ Amiga ACS 1998 #6 / amigaacscoverdisc1998-061998.iso / games / descent / source / includes / psmacros.inc < prev    next >
Text File  |  1998-06-08  |  9KB  |  382 lines

  1. ;THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
  2. ;SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
  3. ;END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
  4. ;ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
  5. ;IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
  6. ;SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
  7. ;FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
  8. ;CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
  9. ;AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.  
  10. ;COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
  11. ;
  12. ; $Source: f:/miner/source/includes/rcs/psmacros.inc $
  13. ; $Revision: 1.12 $
  14. ; $Author: matt $
  15. ; $Date: 1994/12/06 14:32:19 $
  16. ;
  17. ; Useful macros.  Everyone should use these.
  18. ;
  19. ; $Log: psmacros.inc $
  20. ; Revision 1.12  1994/12/06  14:32:19  matt
  21. ; Made mprintf turn off if NMONO set
  22. ; Revision 1.11  1994/11/27  23:18:19  matt
  23. ; Made mprintf go away when debugging turned off
  24. ; Revision 1.10  1994/03/25  18:00:34  matt
  25. ; Added imulc of 6
  26. ; Revision 1.9  1994/02/10  18:00:58  matt
  27. ; Changed 'if DEBUG_ON' to 'ifndef NDEBUG'
  28. ; Revision 1.8  1993/11/22  23:47:06  matt
  29. ; debug macros were trashing eax
  30. ; Revision 1.7  1993/11/04  12:39:25  mike
  31. ; Modify imulc macro to support fast multiply by 36
  32. ; and multiply anything using imul, but give warning.
  33. ; Revision 1.6  1993/10/19  21:17:31  matt
  34. ; Added abs_eax macro
  35. ; Revision 1.5  1993/09/26  22:28:21  matt
  36. ; Removed extra register pushes in mprintf
  37. ; Make DEBUG_ON all uppercase since we seem to have case sensitivity on
  38. ; Revision 1.4  1993/09/26  19:22:30  matt
  39. ; Added imulc macro, to multiply a register by a constant.  It does not
  40. ; at this time support arbitrary constants, only 0,1,3,5,9, and powers of 2
  41. ; Revision 1.3  1993/09/13  11:50:57  matt
  42. ; Added 'b' & 'w', aliases for 'byte ptr' and 'word ptr'
  43. ; Revision 1.2  1993/09/03  19:00:03  matt
  44. ; Added breakpoint macros
  45. ; Revision 1.1  1993/08/24  12:51:52  matt
  46. ; Initial revision
  47. ;
  48. ;
  49.  
  50. ;Shortcuts for casting
  51.  
  52. w equ word ptr
  53. b equ byte ptr
  54.  
  55.  
  56. ;The macros @ArgCount() & @ArgRev() are from the file MACROS.INC, provided 
  57. ;with MASM.  I have included them here because MACROS.INC has bugs, so I 
  58. ;couldn't just include it.
  59.  
  60. ; Utility Macros - Version 1.0 - for Microsoft Macro Assembler 6.0
  61. ; (C) Copyright Microsoft Corporation, 1987,1988,1989,1990
  62.  
  63. ;* @ArgCount - Macro function returns the number of arguments in a
  64. ;* VARARG list.
  65. ;*
  66. ;* Params:  arglist - arguments to be counted
  67.  
  68. @ArgCount MACRO arglist:VARARG
  69.     LOCAL count
  70.     count = 0
  71.     FOR arg, <arglist>
  72.         count = count + 1
  73.     ENDM
  74.     EXITM %count
  75. ENDM
  76.  
  77. ;* @ArgRev - Macro function returns a reversed order version of a
  78. ;* VARARG list.
  79. ;*
  80. ;* Shows:   Operators           - <>         !        %
  81. ;*          String directive    - SUBSTR
  82. ;*          Predefined function - @SizeStr
  83. ;*
  84. ;* Params:  arglist - arguments to be reversed
  85.  
  86. @ArgRev MACRO arglist:vararg
  87.     LOCAL txt, arg
  88.     txt TEXTEQU <>
  89. %   FOR arg, <arglist>
  90.         txt CATSTR <arg>, <!,>, txt
  91.     ENDM
  92.  
  93.     txt SUBSTR  txt, 1, @SizeStr( %txt ) - 1
  94.     txt CATSTR  <!<>, txt, <!>>
  95.     EXITM txt
  96. ENDM
  97.  
  98. ;These macros are used for decalaring external vars and functions
  99.  
  100. ;this macro is used to declare several symbols of the same type
  101. ;usage is:  extdef  type,sym0,sym1,...
  102. extdef    macro    type,syms:vararg
  103.     for    sym,<syms>
  104.      externdef sym:type
  105.     endm
  106.     endm
  107.  
  108. ;this macro is used to generate ext<type> macros 
  109. extgen    macro    type,id
  110. ext&id    macro    syms:vararg
  111.     extdef    type,syms
  112.     endm
  113.     endm
  114.  
  115. ;macros for common types, such as word (extw), byte (extb), & near (extn)
  116.  
  117.     extgen    word,w
  118.     extgen    byte,b
  119.     extgen    dword,d
  120.     extgen    near,n
  121.  
  122.  
  123. ;compute the absolute value of eax.  afterwards, edx=sign (0 or -1)
  124. abs_eax    macro
  125.     cdq
  126.     xor    eax,edx
  127.     sub    eax,edx
  128.     endm
  129.  
  130. ;PUSHM & POPM are used for multiple registers.  Note that POPM pops in the
  131. ;reverse order from PUSHM, so the list of regs shouls be the same for both.
  132. ;You can also define a constant which is a register list, and use it as the
  133. ;argument to both macros.
  134.  
  135. ;push multiple registers
  136. pushm    macro    args:vararg
  137.     local    arg
  138.     for    arg,<args>
  139.      push    arg
  140.     endm
  141.     endm
  142.  
  143. ;pop multiple registers
  144. popm    macro    args:vararg
  145.     local    arg
  146. %    for    arg,@ArgRev(args)
  147.      pop    arg
  148.     endm
  149.     endm
  150.  
  151. ;PUSHLONG pushes a long, zero extending the argument if necessary
  152. ;it trashes no registers
  153. pushlong    macro    arg
  154.     local    s
  155. s = TYPE arg
  156.     if    s EQ 0    ;constant, I think
  157.      push    arg
  158.     elseif    s LT 4
  159.      push    eax
  160.      movzx    eax,arg
  161.      xchg    eax,[esp]
  162.     else
  163.      push    arg
  164.     endif
  165.  
  166.     endm
  167.  
  168. ;PUSHML is pushm using pushlong
  169. pushml    macro    args:vararg
  170.     local    arg
  171.     for    arg,<args>
  172.      pushlong    arg
  173.     endm
  174.     endm
  175.  
  176.  
  177. ;DBSTR stores a string with occurances of \n converted to newlines
  178. ;this macro expects quotes around the string
  179. ;
  180. ;note the 'fudge' variable.  This fixes an odd problem with the way
  181. ;the string macros deal with backslashes - @InStr() treats them like
  182. ;any other character, but @SubStr() ignores them
  183. dbstr    macro    str
  184.     local    pos,oldpos,len,fudge
  185.  
  186.     oldpos = 2    ;skip initial quote
  187.     fudge = 0
  188.     len = @SizeStr(str)
  189.  
  190.     pos = @InStr(oldpos,str,<\n>)
  191.  
  192.     while    pos GE oldpos
  193.  
  194.      if    pos GT oldpos
  195.       %db    '&@SubStr(<&str>,&oldpos-&fudge,&pos-&oldpos)'
  196.      endif
  197.      db    10
  198.      oldpos = pos+2
  199.      fudge = fudge+1
  200.  
  201.      pos = @InStr(oldpos,<str>,<\n>)
  202.  
  203.     endm
  204.  
  205.     if    oldpos LT len
  206. ;;;     %db    '&@SubStr(&str,&oldpos-&fudge,&len-&oldpos-1)'
  207.      %db    '&@SubStr(&str,&oldpos-&fudge,&len-&oldpos)'
  208.     endif
  209.  
  210.     endm
  211.  
  212.  
  213. ;MPRINTF is a macro interface to the mprintf funcion.  It puts the format
  214. ;string in the code segment at the current location, pushes the args, and
  215. ;calls mprintf. If window is not specified, zero is assumed
  216. mprintf    macro    window:=<0>,format:req,args:vararg
  217.     local    string,skip
  218.     ifndef    NDEBUG
  219.     ifndef    NMONO
  220.     extn    _mprintf_
  221.     jmp    skip
  222. string    label    byte
  223.     dbstr    format
  224.     db    0
  225. skip:
  226.     ifnb    <args>
  227. %     pushml    @ArgRev(args)
  228.     endif
  229.     pushml    offset string,window
  230.     call    _mprintf_
  231.     add    esp,(@ArgCount(args)+2)*4    ;fix stack
  232.     endif
  233.     endif
  234.     endm
  235.  
  236.  
  237. ;MPRINTF_AT - version of mprintf with coordinates
  238. mprintf_at    macro    window:=<0>,row,col,format:req,args:vararg
  239.     local    string,skip
  240.     ifndef    NDEBUG
  241.     ifndef    NMONO
  242.     extn    _mprintf_at_
  243.     jmp    skip
  244. string    label    byte
  245.     dbstr    format
  246.     db    0
  247. skip:
  248.     ifnb    <args>
  249. %     pushml    @ArgRev(args)
  250.     endif
  251.     pushml    offset string,col,row,window
  252.     call    _mprintf_at_
  253.     add    esp,(@ArgCount(args)+4)*4    ;fix stack
  254.     endif
  255.     endif
  256.     endm
  257.  
  258.  
  259. ;DEBUG calls mprintf with window 0, preserving all registers and flags
  260. ;is is conditionall assembled based on the DEBUG_ON flags
  261. debug    macro    format:req,args:vararg
  262.     ifndef    NDEBUG
  263.      pushf        ;save flags
  264.      push    eax    ;mprintf trashes eax
  265.      mprintf    ,format,args
  266.      pop    eax
  267.      popf
  268.     endif
  269.     endm
  270.  
  271. ;DEBUG_AT - version of debug with coordinates
  272. debug_at    macro    row,col,format:req,args:vararg
  273.     ifndef    NDEBUG
  274.      pushf        ;save flags
  275.      push    eax    ;mprintf trashes eax
  276.      mprintf_at ,row,col,format,args
  277.      pop    eax
  278.      popf
  279.     endif
  280.     endm
  281.  
  282. ;Debugging breakpoint macros
  283.  
  284. ;print a message, and do an int3 to pop into the debugger  
  285. debug_brk    macro    str
  286.     ifndef    NDEBUG
  287.      debug    str
  288.      int    3
  289.     endif
  290.     endm
  291.  
  292. break_if    macro    cc,str
  293.     local    skip,yes_break
  294.     ifndef    NDEBUG
  295.      j&cc    yes_break
  296.      jmp    skip
  297. yes_break:     debug_brk str
  298. skip:
  299.     endif
  300.     endm
  301.  
  302. ;returns the bit number of the highest bit
  303. @HighBit    macro    n
  304.     local    t,c
  305.     if    n EQ 0
  306.      exitm    <-1>    ;error!
  307.     else
  308.      t = n
  309.      c = 0
  310.      while    t GT 1
  311.       t = t SHR 1
  312.       c = c+1
  313.      endm
  314.      exitm    <c>
  315.     endif
  316.     endm
  317.  
  318. ;returns the bit number of the lowest bit
  319. @LowBit    macro    n
  320.     ;local    t,c
  321.     local    c
  322.     if    n EQ 0
  323.      exitm    <-1>    ;error!
  324.     else
  325.      t = n
  326.      c = 0
  327.      while    (t and 1) EQ 0
  328.       t = t SHR 1
  329.       c = c+1
  330.      endm
  331.      exitm    <c>
  332.     endif
  333.     endm
  334.  
  335.  
  336. ;"multiply" the given register by a constant, using whatever method is
  337. ;best for the given constant
  338. imulc    macro    reg,c
  339.     local    low,high
  340.  
  341.     if    c EQ 0
  342.      xor    reg,reg
  343.     elseif    c EQ 1
  344.     elseif    c EQ 3
  345.      lea    reg,[reg*2+reg]
  346.     elseif    c EQ 5
  347.      lea    reg,[reg*4+reg]
  348.     elseif    c EQ 6
  349.      lea    reg,[reg*2+reg]    ;*3
  350.      shl    reg,1    ;*6
  351.     elseif    c EQ 9
  352.      lea    reg,[reg*8+reg]
  353.     elseif    c EQ 36
  354.      lea    reg,[reg*8+reg]
  355.      sal    reg,2
  356.     else
  357.      low = @LowBit(c)
  358.      high = @HighBit(c)
  359.      if    low EQ high
  360.       shl    reg,@LowBit(c)
  361.      else
  362.       imul    reg,c
  363.       echo    Warning: Using imul, to perform multiply by &c
  364.       ;; .err
  365.      endif
  366.     endif
  367.  
  368.     endm
  369.  
  370.