home *** CD-ROM | disk | FTP | other *** search
/ Virtual Reality Zone / VRZONE.ISO / mac / PC / REND386 / JIREND / INTMATHX.C < prev    next >
C/C++ Source or Header  |  1993-04-11  |  17KB  |  770 lines

  1. /* Routines for moving, scaling and rotating objects */
  2. /* Matrix math, assembly by Dave Stampe */
  3.   
  4. /* Copyright 1992 by Dave Stampe and Bernie Roehl.
  5.     May be freely used to write software for release into the public domain;
  6.     all commercial endeavours MUST contact Bernie Roehl and Dave Stampe
  7.     for permission to incorporate any part of this software into their
  8.     products!
  9.  */
  10.   
  11. /* Contact: broehl@sunee.waterloo.edu or dstampe@sunee.waterloo.edu */
  12.   
  13. #pragma inline
  14.   
  15. #include <stdio.h>
  16. #include "3dstruct.h"
  17.   
  18. #define XFSC 536870912   /* 2**29 for shifting xform coeffs to long */
  19.   
  20. /*************** TRIGNOMETRIC FUNCTIONS *****************/
  21.   
  22. /* (from inttrig.c) */
  23.   
  24. extern long isine(long x);
  25. extern long icosine(long x);
  26. extern long arcsine(long x);
  27. extern long arccosine(long x);
  28. extern long arctan2(long y, long x);
  29.   
  30. /*************** MATRIX MANIPULATION *****************/
  31.   
  32. /* (from matrix.c) */
  33.   
  34. #define RXYZ 1    /* matrix rotation types */
  35. #define RYXZ 0          /* ONLY RYXZ guaranteed to be tested */
  36. #define RXZY 2
  37. #define RZYX 5
  38. #define RZXY 4
  39. #define RYZX 6
  40.   
  41. extern void matrix_point(MATRIX m, long *xp, long *yp, long *zp);
  42. extern void matrix_rotate(MATRIX m, long *xp, long *yp, long *zp);
  43. extern void cross_column(MATRIX m, int col);
  44. extern long m_mult(long a, long b);    /* perform mult. by matrix element */
  45. extern long dot_prod_29(long a, long b, long c, long x, long y, long z);
  46. extern void matrix_mult(MATRIX a, MATRIX b, MATRIX c);
  47. extern void matrix_product(MATRIX a, MATRIX b, MATRIX c);
  48. extern void matrix_transpose(MATRIX a, MATRIX b);
  49. extern void inverse_matrix(MATRIX a, MATRIX b);
  50. extern void identity_matrix(MATRIX m);
  51. extern void matrix_copy(MATRIX m, MATRIX n);
  52. extern void matrix_rot_copy(MATRIX m, MATRIX n);
  53.   
  54.              /* create rotation/translation */
  55.              /* "matrix" from angle data    */
  56.   
  57. /******************** APPLY MATRIX TO OBJECTS **************/
  58.   
  59. void matmove_rep(REP *rep, MATRIX m)
  60. {
  61.    int i;
  62.    VERTEX *v = rep->verts;     /* use "matrix" to rotate then translate */
  63.    POLY   *p = rep->polys;
  64.    int vs = sizeof(VERTEX);
  65.    int ps = sizeof(POLY);
  66.    int vc = rep->nverts;
  67.    int pc = rep->npolys;
  68.    long rx,ry,rz;
  69.   
  70.    asm {
  71.       .386
  72.       push  ds
  73.       push  si
  74.       push  di
  75.       push  cx
  76.       push  dx
  77.       lds   si,DWORD PTR m
  78.   
  79.       les   di,DWORD PTR v   /* rotate/translate all vertices */
  80.    }
  81.    vconv:
  82.    asm {
  83.       mov   eax,ds:[si]
  84.       imul  DWORD PTR es:[di].(VERTEX)ox
  85.       mov   ecx,edx
  86.       mov   ebx,eax
  87.       mov   eax,ds:[si+4]
  88.       imul  DWORD PTR es:[di].(VERTEX)oy
  89.       add   ebx,eax
  90.       adc   ecx,edx
  91.       mov   eax,ds:[si+8]
  92.       imul  DWORD PTR es:[di].(VERTEX)oz
  93.       add   eax,ebx
  94.       adc   edx,ecx
  95.       shrd  eax,edx,29
  96.       adc   eax,ds:[si+36]
  97.       mov   es:[di].(VERTEX)x,eax
  98.   
  99.       mov   eax,ds:[si+12]
  100.       imul  DWORD PTR es:[di].(VERTEX)ox
  101.       mov   ecx,edx
  102.       mov   ebx,eax
  103.       mov   eax,ds:[si+16]
  104.       imul  DWORD PTR es:[di].(VERTEX)oy
  105.       add   ebx,eax
  106.       adc   ecx,edx
  107.       mov   eax,ds:[si+20]
  108.       imul  DWORD PTR es:[di].(VERTEX)oz
  109.       add   eax,ebx
  110.       adc   edx,ecx
  111.       shrd  eax,edx,29
  112.       adc   eax,ds:[si+40]
  113.       mov   es:[di].(VERTEX)y,eax
  114.   
  115.       mov   eax,ds:[si+24]
  116.       imul  DWORD PTR es:[di].(VERTEX)ox
  117.       mov   ecx,edx
  118.       mov   ebx,eax
  119.       mov   eax,ds:[si+28]
  120.       imul  DWORD PTR es:[di].(VERTEX)oy
  121.       add   ebx,eax
  122.       adc   ecx,edx
  123.       mov   eax,ds:[si+32]
  124.       imul  DWORD PTR es:[di].(VERTEX)oz
  125.       add   eax,ebx
  126.       adc   edx,ecx
  127.       shrd  eax,edx,29
  128.       adc   eax,ds:[si+44]
  129.       mov   es:[di].(VERTEX)z,eax
  130.   
  131.       add   di,vs
  132.       dec     WORD PTR vc
  133.       jz      vconve
  134.       jmp   vconv
  135.    }
  136.    vconve:
  137.    asm {
  138.       les   di,DWORD PTR p      /* rotate all normals */
  139.    }
  140.    pconv:
  141.    asm {
  142.       mov   eax,ds:[si]
  143.       imul  DWORD PTR es:[di].(POLY)onormalx
  144.       mov   ecx,edx
  145.       mov   ebx,eax
  146.       mov   eax,ds:[si+4]
  147.       imul  DWORD PTR es:[di].(POLY)onormaly
  148.       add   ebx,eax
  149.       adc   ecx,edx
  150.       mov   eax,ds:[si+8]
  151.       imul  DWORD PTR es:[di].(POLY)onormalz
  152.       add   eax,ebx
  153.       adc   edx,ecx
  154.       shrd  eax,edx,29
  155.       adc   eax,0
  156.       mov   es:[di].(POLY)normalx,eax
  157.   
  158.       mov   eax,ds:[si+12]
  159.       imul  DWORD PTR es:[di].(POLY)onormalx
  160.       mov   ecx,edx
  161.       mov   ebx,eax
  162.       mov   eax,ds:[si+16]
  163.       imul  DWORD PTR es:[di].(POLY)onormaly
  164.       add   ebx,eax
  165.       adc   ecx,edx
  166.       mov   eax,ds:[si+20]
  167.       imul  DWORD PTR es:[di].(POLY)onormalz
  168.       add   eax,ebx
  169.       adc   edx,ecx
  170.       shrd  eax,edx,29
  171.       adc   eax,0
  172.       mov   es:[di].(POLY)normaly,eax
  173.   
  174.       mov   eax,ds:[si+24]
  175.       imul  DWORD PTR es:[di].(POLY)onormalx
  176.       mov   ecx,edx
  177.       mov   ebx,eax
  178.       mov   eax,ds:[si+28]
  179.       imul  DWORD PTR es:[di].(POLY)onormaly
  180.       add   ebx,eax
  181.       adc   ecx,edx
  182.       mov   eax,ds:[si+32]
  183.       imul  DWORD PTR es:[di].(POLY)onormalz
  184.       add   eax,ebx
  185.       adc   edx,ecx
  186.       shrd  eax,edx,29
  187.       adc   eax,0
  188.       mov   es:[di].(POLY)normalz,eax
  189.   
  190.       add   di,ps
  191.       dec     WORD PTR pc
  192.       jz      pconve
  193.       jmp   pconv
  194.    }
  195.    pconve:
  196.    asm {
  197.       pop   dx
  198.       pop   cx
  199.       pop   di
  200.       pop   si
  201.       pop   ds
  202.    }
  203.   
  204.    rep->update_count++;
  205. }
  206.   
  207.   
  208. void matmove_osphere(OBJECT *obj, MATRIX m)
  209. {
  210.    asm {                            /* rotate/translate sphere center */
  211.       .386
  212.       push  ds
  213.       push  si
  214.       push  di
  215.       push  cx
  216.       push  dx
  217.       lds   si,DWORD PTR m
  218.   
  219.       les   di,DWORD PTR obj
  220.       mov   eax,ds:[si]
  221.       imul  DWORD PTR es:[di].(OBJECT)osphx
  222.       mov   ecx,edx
  223.       mov   ebx,eax
  224.       mov   eax,ds:[si+4]
  225.       imul  DWORD PTR es:[di].(OBJECT)osphy
  226.       add   ebx,eax
  227.       adc   ecx,edx
  228.       mov   eax,ds:[si+8]
  229.       imul  DWORD PTR es:[di].(OBJECT)osphz
  230.       add   eax,ebx
  231.       adc   edx,ecx
  232.       shrd  eax,edx,29
  233.       adc   eax,ds:[si+36]
  234.       mov   es:[di].(OBJECT)sphx,eax
  235.   
  236.       mov   eax,ds:[si+12]
  237.       imul  DWORD PTR es:[di].(OBJECT)osphx
  238.       mov   ecx,edx
  239.       mov   ebx,eax
  240.       mov   eax,ds:[si+16]
  241.       imul  DWORD PTR es:[di].(OBJECT)osphy
  242.       add   ebx,eax
  243.       adc   ecx,edx
  244.       mov   eax,ds:[si+20]
  245.       imul  DWORD PTR es:[di].(OBJECT)osphz
  246.       add   eax,ebx
  247.       adc   edx,ecx
  248.       shrd  eax,edx,29
  249.       adc   eax,ds:[si+40]
  250.       mov   es:[di].(OBJECT)sphy,eax
  251.   
  252.       mov   eax,ds:[si+24]
  253.       imul  DWORD PTR es:[di].(OBJECT)osphx
  254.       mov   ecx,edx
  255.       mov   ebx,eax
  256.       mov   eax,ds:[si+28]
  257.       imul  DWORD PTR es:[di].(OBJECT)osphy
  258.       add   ebx,eax
  259.       adc   ecx,edx
  260.       mov   eax,ds:[si+32]
  261.       imul  DWORD PTR es:[di].(OBJECT)osphz
  262.       add   eax,ebx
  263.       adc   edx,ecx
  264.       shrd  eax,edx,29
  265.       adc   eax,ds:[si+44]
  266.       mov   es:[di].(OBJECT)sphz,eax
  267.   
  268.       pop   dx
  269.       pop   cx
  270.       pop   di
  271.       pop   si
  272.       pop   ds
  273.    }
  274.   
  275.    obj->update_count++;
  276. }
  277.                                              /* works as if only current rep existed */
  278.   
  279. void apply_matrix(OBJECT *obj, MATRIX m)
  280. {
  281.    REP *rep = obj->current_rep;
  282.    if(rep==NULL) return;
  283.   
  284.    matmove_osphere(obj, m);
  285.    matmove_rep(rep, m);
  286.    obj->update_count++;
  287.    rep->update_count++;
  288. }
  289.   
  290. /* used to compute floor/ceiling of areas */
  291. long plane_y(long a, long b, long c, long d, long x, long z)
  292. {
  293.  /* computes (Ax + Cz + D)/-B */
  294.   
  295.    long result;
  296.   
  297.    asm {
  298.       push  si
  299.       push  di
  300.   
  301.       mov   eax,a
  302.       imul  DWORD PTR x
  303.       mov   esi,eax
  304.       mov   edi,edx
  305.   
  306.       mov   eax,c
  307.       imul  DWORD PTR z
  308.       add   eax,esi
  309.       adc   edx,edi
  310.   
  311.       add   eax,DWORD PTR d
  312.       adc   edx,0
  313.       idiv  DWORD PTR b
  314.       mov   result,eax
  315.   
  316.       pop   di
  317.       pop   si
  318.    }
  319.    return result;
  320. }
  321.   
  322. /************ COLLISION DETECTION AND SELECTION ***********/
  323.   
  324. long sphere_pretest(OBJECT *obj, long x, long y, long z)
  325. {
  326.    long dist = 0;     /* returns 0x7FFFFFFF if not in, else (D) */
  327.   
  328.    long sx = obj->sphx;
  329.    long sy = obj->sphy;
  330.    long sz = obj->sphz;
  331.    long sr = obj->sphr;
  332.   
  333.    asm {
  334.       push  cx
  335.   
  336.       mov   eax,sx   /* x bounds */
  337.       sub   eax,x
  338.       cmp   eax,sr
  339.       jg notin
  340.       neg   eax
  341.       cmp   eax,sr
  342.       jg notin
  343.   
  344.       mov   eax,sy   /* y bounds */
  345.       sub   eax,y
  346.       cmp   eax,sr
  347.       jg notin
  348.       neg   eax
  349.       cmp   eax,sr
  350.       jg notin
  351.   
  352.       mov   eax,sz   /* z bounds */
  353.       sub   eax,z
  354.       cmp   eax,sr
  355.       jg notin
  356.       neg   eax
  357.       cmp   eax,sr
  358.       jg notin
  359.   
  360.       imul  eax      /* square of distance to center */
  361.       mov   ebx,eax
  362.       mov   ecx,edx
  363.   
  364.       mov   eax,sx
  365.       sub   eax,x
  366.       imul  eax
  367.       add   ebx,eax
  368.       adc   ecx,edx
  369.   
  370.       mov   eax,sy
  371.       sub   eax,y
  372.       imul  eax
  373.       add   ebx,eax
  374.       adc   ecx,edx
  375.   
  376.       mov   eax,sr   /* square of radius */
  377.       imul  eax
  378.       cmp   edx,ecx
  379.       ja in
  380.       jb notin
  381.       cmp   eax,ebx
  382.       jae   in
  383.    }
  384.    notin:                   /* outside of sphere */
  385.    asm pop cx;
  386.    return 0x7FFFFFFF;      /* big never wins */
  387.   
  388.    in:
  389.    asm {
  390.       test  ebx,-1         /* shift so denom. is 32-bit or less */
  391.       jz nolo1
  392.       mov   eax,edx
  393.       xor   edx,edx
  394.       mov   ebx,ecx
  395.       xor   ecx,ecx
  396.    }
  397.    nolo1:
  398.    asm {
  399.       mov   eax,x    /* abs(x-sx)+abs(y-sy)+abs(z-sz) approx. dist from center */
  400.       sub   eax,sx
  401.       cdq
  402.       xor   eax,edx
  403.       sub   eax,edx
  404.       mov   ebx,eax
  405.   
  406.       mov   eax,x
  407.       sub   eax,sx
  408.       cdq
  409.       xor   eax,edx
  410.       sub   eax,edx
  411.       add   ebx,eax
  412.   
  413.       mov   eax,x
  414.       sub   eax,sx
  415.       cdq
  416.       xor   eax,edx
  417.       sub   eax,edx
  418.       add   ebx,eax
  419.   
  420.       mov   dist, ebx
  421.       pop   cx
  422.    }
  423.    return dist;      /* for comparison between objects: smallest wins */
  424. }
  425.   
  426.   
  427.   
  428. /************* POLYGON NORMAL COMPUTATION *************/
  429.   
  430.      /* returns abs(x1-x2) + abs(y1-y2) + abs(z1-z2) */
  431.   
  432. long big_dist(long x1, long y1, long z1,
  433. long x2, long y2, long z2 )
  434. {
  435.    long dist;
  436.   
  437.    asm {
  438.       mov     eax,x1
  439.       sub   eax,x2
  440.       cdq
  441.       xor   eax,edx
  442.       sub   eax,edx
  443.       mov   ecx,eax
  444.   
  445.       mov     eax,y1
  446.       sub   eax,y2
  447.       cdq
  448.       xor   eax,edx
  449.       sub   eax,edx
  450.       add   ecx,eax
  451.   
  452.       mov     eax,z1
  453.       sub   eax,z2
  454.       cdq
  455.       xor   eax,edx
  456.       sub   eax,edx
  457.       add   ecx,eax
  458.   
  459.       mov   dist,ecx
  460.    }
  461.    return dist;
  462. }
  463.   
  464.   
  465.    /* compute, unitize (3.29 format) normal to plane.   */
  466.    /* returns -1 if normal is zero, else log2(length)   */
  467.   
  468. int find_normal(long x1, long y1, long z1,
  469. long x2, long y2, long z2,
  470. long x3, long y3, long z3,
  471. long *xn, long *yn, long *zn)
  472. {
  473.    long xh, xl, yh, yl, zh, zl;
  474.    long xah, xal, yah, yal, zah, zal;
  475.    int length;
  476.   
  477.    extern int sqrtable[1024];
  478.   
  479.    asm {
  480.       push  dx
  481.       push  cx
  482.       push  si
  483.       push  di
  484.   
  485.       mov   eax,y2        /* compute 64-bit cross product   */
  486.       sub   eax,y1        /* and also abs. value for shifts */
  487.       mov   ecx,z3
  488.       sub   ecx,z2
  489.       imul  ecx
  490.       mov   edi,edx
  491.       mov   esi,eax
  492.       mov   eax,y3
  493.       sub   eax,y2
  494.       mov   ecx,z2
  495.       sub   ecx,z1
  496.       imul  ecx
  497.       sub   esi,eax
  498.       sbb   edi,edx
  499.       mov   xh,edi
  500.       mov   xl,esi
  501.       jge   stax
  502.       not   edi
  503.       not   esi
  504.       add   esi,1
  505.       adc   edi,0
  506.    }
  507.    stax:
  508.    asm {
  509.       mov   xah,edi
  510.       mov   xal,esi
  511.   
  512.       mov   eax,z2
  513.       sub   eax,z1
  514.       mov   ecx,x3
  515.       sub   ecx,x2
  516.       imul  ecx
  517.       mov   edi,edx
  518.       mov   esi,eax
  519.       mov   eax,z3
  520.       sub   eax,z2
  521.       mov   ecx,x2
  522.       sub   ecx,x1
  523.       imul  ecx
  524.       sub   esi,eax
  525.       sbb   edi,edx
  526.       mov   yh,edi
  527.       mov   yl,esi
  528.       jge   stay
  529.       not   edi
  530.       not   esi
  531.       add   esi,1
  532.       adc   edi,0
  533.    }
  534.    stay:
  535.    asm {
  536.       mov   yah,edi
  537.       mov   yal,esi
  538.   
  539.       mov   eax,x2
  540.       sub   eax,x1
  541.       mov   ecx,y3
  542.       sub   ecx,y2
  543.       imul  ecx
  544.       mov   edi,edx
  545.       mov   esi,eax
  546.       mov   eax,x3
  547.       sub   eax,x2
  548.       mov   ecx,y2
  549.       sub   ecx,y1
  550.       imul  ecx
  551.       sub   esi,eax
  552.       sbb   edi,edx
  553.       mov   zh,edi
  554.       mov   zl,esi
  555.       jge   staz
  556.       not   edi
  557.       not   esi
  558.       add   esi,1
  559.       adc   edi,0
  560.    }
  561.    staz:
  562.    asm {
  563.       mov   zah,edi
  564.       mov   zal,esi
  565.    }
  566.   
  567.    asm {               /* now normalize to 3.29 */
  568.       or esi,yal
  569.       or esi,xal
  570.       or edi,yah
  571.       or edi,xah
  572.       jz zero_h
  573.   
  574.       xor   ax,ax           /* ax is shift count */
  575.       test  edi,0FFFF0000h  /* top word not zero: cnvt to 1.n <3.29> */
  576.       jz z16h
  577.       add   ax,16
  578.       shr   edi,16
  579.    }
  580.    z16h:
  581.    asm {
  582.       test  di,0FF00h
  583.       jz z8h
  584.       add   ax,8
  585.       shr   edi,8
  586.    }
  587.    z8h:
  588.    asm {
  589.       shl   edi,8       /* most ecomonical pos'n */
  590.       bsr   cx,di       /* get exact shift */
  591.       sub   cx,5
  592.       add     cx,ax
  593.   
  594.       mov   eax,xh      /* convert cross product to 1.n */
  595.       shrd  xl,eax,cl
  596.       mov   eax,yh
  597.       shrd  yl,eax,cl
  598.       mov   eax,zh
  599.       shrd  zl,eax,cl
  600.   
  601.       add   cx,29
  602.       mov   length,cx
  603.   
  604.       jmp   dshnorm
  605.    }
  606.   
  607.    zero_h:
  608.    asm {
  609.       or esi,esi
  610.       jz zero_normal
  611.       mov   ax,24
  612.       test  esi,0FFFF0000h  /* top word is zero: cnvt to 1.n <3.29> */
  613.       jz z16l
  614.       sub   ax,16
  615.       shr   esi,16
  616.    }
  617.    z16l:
  618.    asm {
  619.       test  si,0FF00h
  620.       jz z8l
  621.       sub   ax,8
  622.       shr   esi,8
  623.    }
  624.    z8l:
  625.    asm {
  626.       shl   esi,8       /* most ecomonical pos'n */
  627.       bsr   cx,si       /* get exact shift */
  628.       neg   cx
  629.       add   cx,13
  630.       add   cx,ax
  631.   
  632.       jz noshiftl
  633.       jg lshiftl
  634.   
  635.       neg   cx
  636.       mov   eax,xh      /* convert cross product to 1.n   */
  637.       shrd  xl,eax,cl   /* need ext. for borderline cases */
  638.       mov   eax,yh
  639.       shrd  yl,eax,cl
  640.       mov   eax,zh
  641.       shrd  zl,eax,cl
  642.    }
  643.    noshiftl:
  644.    asm {
  645.       add   cx,29
  646.       mov   length,cx
  647.   
  648.       jmp   dshnorm
  649.    }
  650.    lshiftl:
  651.    asm {
  652.       shl   DWORD PTR xl,cl
  653.       shl   DWORD PTR yl,cl
  654.       shl   DWORD PTR zl,cl
  655.   
  656.       mov   ax,29
  657.       sub   ax,cx
  658.       mov   length,ax
  659.    }
  660.    dshnorm:  goto finish;
  661.   
  662.    zero_normal:
  663.    asm {
  664.       pop   di
  665.       pop   si
  666.       pop   cx
  667.       pop   dx
  668.    }
  669.    *xn = *yn = *zn = -1;
  670.    return 0;
  671.   
  672.    finish:             /* compute magnitude, convert to unit length */
  673.   
  674.    asm {
  675.       mov   eax,xl            /* compute squares */
  676.       sar   eax,16
  677.       imul  ax
  678.       mov   bx,dx
  679.       mov   cx,ax
  680.   
  681.       mov   eax,yl
  682.       sar   eax,16
  683.       imul  ax
  684.       add   cx,ax
  685.       adc   bx,dx
  686.   
  687.       mov   eax,zl
  688.       sar   eax,16
  689.       imul  ax
  690.       add   cx,ax
  691.       adc   bx,dx
  692.   
  693.       shr   bx,4             /* magnitude << 13 */
  694.       shl   bx,1
  695.       mov   cx,sqrtable[bx]
  696.       movzx ecx,cx
  697.   
  698.       mov   eax,xl           /* scale cross product */
  699.       cdq
  700.       shld  edx,eax,13
  701.       shl   eax,13
  702.       idiv  ecx
  703.       mov   xl,eax
  704.   
  705.       mov   eax,yl
  706.       cdq
  707.       shld  edx,eax,13
  708.       shl   eax,13
  709.       idiv  ecx
  710.       mov   yl,eax
  711.   
  712.       mov   eax,zl
  713.       cdq
  714.       shld  edx,eax,13
  715.       shl   eax,13
  716.       idiv  ecx
  717.       mov   zl,eax
  718.   
  719.       pop   di
  720.       pop   si
  721.       pop   cx
  722.       pop   dx
  723.    }
  724.   
  725.    *xn = -xl;    /* left-hand coordinate system */
  726.    *yn = -yl;
  727.    *zn = -zl;
  728.   
  729.    return length;
  730. }
  731.   
  732.   
  733. long scale_16(long s, long a, long x)    /* perform scaling by 16.16 number */
  734. {
  735.    long result;
  736.   
  737.    asm {
  738.       mov   eax,DWORD PTR x
  739.       add eax,DWORD PTR a
  740.       imul  DWORD PTR s
  741.       shrd  eax,edx,16
  742.       adc   eax,0
  743.       mov   DWORD PTR result,eax
  744.    }
  745.    return result;
  746. }
  747.   
  748. long calc_scale_16(long a, long b, long s)   /* compute 16.16 scaling factor */
  749. {
  750.    long result = 0;
  751.   
  752.    asm {
  753.       mov   ebx,DWORD PTR a
  754.       sub   ebx,DWORD PTR b
  755.       je cdiv
  756.       mov   eax, DWORD PTR s
  757.       cdq
  758.       shld  edx,eax,17
  759.       shl   eax,17
  760.       idiv  ebx
  761.       mov   DWORD PTR result,eax
  762.    }
  763.    cdiv:
  764.    return result;
  765. }
  766.   
  767.   
  768.   
  769.   
  770.