home *** CD-ROM | disk | FTP | other *** search
/ The Party 1994: Try This At Home / disk_image.bin / source / gallery / a_rays.asm < prev    next >
Assembly Source File  |  1994-06-14  |  12KB  |  418 lines

  1. ;  A_RAYS.ASM -- Ray tracer // A.R-M. 7/93
  2. ; Ported from original TP6.0 assembler to TASM "not-so-" Ideal
  3.  
  4.  
  5. ; This is the heart of the whole thing.
  6.  
  7. ; (c) 1993, ARM. All rights reserved.
  8. ;                Protected by Federal Law.
  9. ;                Violators will be prosecuted.
  10. ;                Trespassers will be shot.
  11. ;                Keep off the grass.
  12. ;                Wet paint.
  13. ;                No U turn.
  14. ;                Speed limit 55 MPH.
  15.  
  16.  
  17.         IDEAL
  18.         MODEL Compact, Pascal
  19.         RADIX 16
  20.         P286
  21.  
  22.  
  23.         INCLUDE "a_ray_t.inc"       ; include SRay type def
  24.  
  25. ; slope data structure
  26.  
  27. STRUC   SSlope
  28.  
  29.         DistFactor      DW      ?
  30.         Slope           DW      ?
  31.  
  32. ENDS    SSlope
  33.  
  34.  
  35. ; sector data structure
  36.  
  37. STRUC   SSector
  38.  
  39.         Along           DW      ?
  40.         Across          DW      ?
  41.         AcrossWall      DB      ?
  42.         AlongWall       DB      ?
  43.         hit             DB      ?
  44.                         DB      ?     ; makes length 8 bytes
  45.  
  46. ENDS    SSector
  47.  
  48. ; * MAP SIZE *
  49.  
  50. mps = 64d        ; 64 x 64 map
  51.  
  52. IF (mps NE 64d)
  53. IF (mps NE 128d)
  54.   Display "A_RAYS.ASM:  mps invalid (only 64d or 128d supported)."
  55.   ERR
  56. ENDIF
  57. ENDIF
  58.  
  59.         DATASEG
  60.  
  61. PUBLIC  Map, NumberOfBearings  ; might want to play with map from outside!
  62.  
  63. Map:
  64.  
  65. HERE = $
  66. %NOLIST
  67.         RADIX 16
  68.         INCLUDE "data\mapdata.inc"   ; Map (mpsxmps byte map)
  69. %LIST
  70.  
  71. ; quick check on mapdata.inc file:
  72.  
  73. IF $-HERE NE mps*mps
  74.   Display "A_RAYS.ASM:  mapdata.inc size does not match mps value!"
  75.   ERR
  76. ENDIF
  77.  
  78. ; NumberOfBearings and SlopeData defined in slopes.inc
  79.  
  80. HERE = $
  81. %NOLIST
  82.         RADIX 10
  83.         INCLUDE "data\slopes.inc"
  84. %LIST
  85.  
  86. ; more checks:
  87.  
  88. IFNDEF NumberOfBearings
  89.   Display "A_RAYS.ASM:  slopes.inc does not define NumberOfBearings : Word"
  90.   ERR
  91. ENDIF
  92.  
  93. IFNDEF SlopeData
  94.   Display "A_RAYS.ASM:  slopes.inc does not define SlopeData"
  95.   ERR
  96. ENDIF
  97.  
  98. ; SectorData. Increments & hit coords for the 8 45° sectors:
  99.  
  100.  
  101. SectorData:
  102.  
  103.         SSector < +mps, +  1, 3,0, 00b >  ; sector 0
  104.         SSector < +  1, +mps, 0,3, 00b >  ;        1
  105.         SSector < -  1, +mps, 0,1, 01b >  ;        2
  106.         SSector < +mps, -  1, 1,0, 10b >  ;        3
  107.         SSector < -mps, -  1, 1,2, 11b >  ;        4
  108.         SSector < -  1, -mps, 2,1, 11b >  ;        5
  109.         SSector < +  1, -mps, 2,3, 10b >  ;        6
  110.         SSector < -mps, +  1, 3,2, 01b >  ;        7
  111.  
  112.         RADIX 16
  113.  
  114.         CODESEG
  115.  
  116. PUBLIC  ShootRay        ;(var Ray : SRay ):byte. Shoots Ray till
  117.                         ; first hit w/ a wall. Returns map array
  118.                         ; byte at that point.
  119.  
  120.         ;NOTE:  Shoots ray from inRay. Returns:
  121.         ;       - impact location and path length
  122.         ;           in outRay.MapX,MapY,FineX,FineY,Length.
  123.         ;       - map contents at hit in AL
  124.         ;       - wall side in AH (0=S, 1=W, 2=N, 3=E)
  125.         ;       - wall side hit offset (0..32768) in DX
  126.  
  127. MACRO   SubFrom1 r   ; calculates 32768-Rx
  128. P386
  129.         or r&x,1     ;; "neg Rx, and Rh,7f" trick doesn't
  130.         neg r&x      ;;   with Rx=0.
  131.         and r&h,7fh
  132. P286
  133.         ENDM
  134.  
  135. ; I'm sure no one would care to try to crack this code,
  136. ; but in case someone does let's have some fun:
  137.  
  138.         db 'Polygon list too long'
  139.  
  140. ; That ought to throw 'em way off track... }:-DDD
  141.  
  142.         PROC ShootRay NEAR
  143.         ARG inRay : NEAR PTR SRay, outRay : NEAR PTR SRay
  144.         LOCAL DistanceFactor : Word, X0 : Word, \
  145.               HitOfs : Word, Walls : Word, Contents : Byte
  146.           pusha
  147.  
  148. ; Those [es:di+SRay.Angle] & the like below were the only way I
  149. ; could figure out to get the darn things to assemble, should've
  150. ; been "SRay ptr [es:di].Angle" like in good ol' TP6.0's ASM :-(
  151.  
  152.           mov di, [inRay]
  153.           mov si, [outRay]
  154.           mov dx, [di+SRay.Angle]          ; dx = angle offset
  155.           mov cx, [di+SRay.Sector]         ; cl = sector; ch = 0
  156.           and cl, 7                        ;  (take mod 8)
  157.  
  158. ; copy constant values from inRay to outRay
  159.  
  160.           mov [si+SRay.Angle], dx
  161.           mov [si+SRay.Sector], cx
  162.           mov ax,[di+SRay.length]
  163.           mov [si+SRay.length], ax
  164. P386
  165.           xor ax, ax
  166.           bts ax, cx
  167.           mov ch, al                       ; ch = bit-mapped sector
  168. P286
  169.           test cl, 1    ; sector no. odd?
  170.           jz @@skipodd
  171.           neg dx        ; if odd, offset=NumberOfBearings-offset
  172.           add dx, [NumberOfBearings]
  173.  
  174. @@skipodd:
  175.  
  176. ; └── here ch:cl=sector; dx = corrected bearing
  177.  
  178.           shl dx, 2                  ; dx <- dx * sizeof SlopeData
  179.           mov si, offset SlopeData
  180.           add si, dx                 ; ds:si -> SlopeArray[offset]
  181.           mov ax, [si+SSlope.DistFactor]
  182.           mov [DistanceFactor], ax   ; save DistFactor for later
  183.           mov bx, [si+SSlope.Slope]  ; bx = slope
  184.  
  185. ; └── here ch:cl=sector; bx=slope, "distancefactor"
  186.  
  187.           mov ah, [di+SRay.MapY]
  188.           xor al, al
  189. IF mps EQ 128d                        ; 128x128 map:
  190.           shr ax, 1                   ; ax = 128*MapY
  191. ENDIF
  192. IF mps EQ 64d                         ; 64x64 map:
  193.           shr ax, 2                   ; ax =  64*MapY
  194. ENDIF
  195.           mov dl, [di+SRay.MapX]
  196.           xor dh, dh
  197.           add ax, dx                  ; ax = mps*MapY + MapX
  198.           add ax, offset Map
  199.           mov si, ax                  ; ds:si -> Map[MapY,MapX]
  200.  
  201. ;  └── here ch:cl=sector; bx = slope; ds:si->MapContents
  202.  
  203. ; load map coordinates:
  204.  
  205.           mov dx, [di+SRay.FineX]     ; dx = FineX
  206.           mov ax, [di+SRay.FineY]     ; ax = FineY
  207.  
  208. ; swap FX <-> FY for sectors 1, 2, 5, and 6
  209.  
  210.           test ch, 01100110b     ; sector bit in 1,2,5,6 ?
  211.           jz @@skipswitch
  212.           xchg ax, dx            ; ...if so, swap
  213. @@skipswitch:
  214.  
  215. ; └── here ch:cl=sector; ds:si->Map; ax=across; dx=along; bx=slope
  216.  
  217. ; NOTE: no test is made for walls at observer's position [MapY,MapX]
  218.  
  219. ; * calculate initial step to first border *
  220.  
  221.           ; dx = FX
  222.           mov [X0], dx          ; save initial X0
  223.  
  224.           test ch, 10000111b    ; sectors 0,1,2,7 ?
  225.           jz @@skipPreSubX
  226.           SubFrom1 d            ; dx = 1 - dx
  227. @@skipPreSubX:
  228.           mov di, ax            ; save "across"
  229.           mov ax, bx            ; ax = slope
  230.           mul dx                ; dx:ax = increment*32768
  231.           shl ax,1
  232.           rol dx,1              ; dx = increment
  233.           mov ax, di
  234.           test ch, 10110100b    ; sectors 4,5,2,7 ?
  235.           jz @@add
  236. @@subtract:
  237.           sub ax, dx
  238.           jmp @@continue
  239. @@add:
  240.           add ax, dx
  241. @@continue:
  242.  
  243. ; └── here ch:cl=sector; ds:si->Map; ax=across; bx=slope
  244.  
  245. ; * load registers to enter ray-tracing loop *
  246.  
  247.           mov di, offset SectorData
  248.           mov dl, cl
  249.           xor dh, dh            ; dx = sector
  250.           shl dx,3
  251.           add di, dx            ; di <- di + 8*sector
  252.  
  253.           mov dx, [word ptr di+SSector.AcrossWall]
  254.           mov [Walls], dx
  255.  
  256.           mov cl, [di+SSector.hit]
  257.           mov dx, [di+SSector.along]
  258.           mov di, [di+SSector.across]
  259.  
  260.           xchg bx, di           ; bx = SectorData.across; di = slope
  261.  
  262.           test ch, 10110100b
  263.           jz @@skipNegativeSlope
  264.           neg di                ; sectors 4,5,2,7 have negative slope
  265. @@skipNegativeSlope:
  266.  
  267. ; └── here ch=sector; ds:si->Map; ax=across; di=slope;
  268. ;          cl=().hit; bx=().across; dx=().along
  269.  
  270.  
  271. ; ** RAY-TRACING LOOP **
  272. ; Upon entry:
  273. ;  ds:si -> MapContents[MapY,MapX]
  274. ;  ax    = FineY or FineX  ("across" coord)
  275. ;  di    = slope ("across" increment)
  276. ;  bx    = map increment for "across" step
  277. ;  dx    = map increment for "along" step
  278. ;  ch    = sector (bit-mapped)
  279. ;  cl bit 0  = "across" hit coord (0 or 1)
  280. ;  cl bit 1  = "along" hit coord  (0 or 1)
  281.  
  282.           PUSH CX      ; save bit-mapped sector byte
  283.           xor ch, ch   ; ch will be our counter now
  284.           inc ch
  285. @@RayLoop:
  286.           test ah,80    ; FY <0 or >32767 ?
  287.           jz @@skip
  288.  
  289.           and ah, 7f    ; ... if so, reset FY...
  290.           add si, dx    ; ... and update map ptr
  291.           mov cl, [si]
  292.           or  cl, cl    ; anything along our path ?
  293.           jnz @@HitX
  294.  
  295. @@skip:
  296.           add si, bx
  297.           mov cl, [si]
  298.           or  cl, cl    ; how about across out path ?
  299.           jnz @@HitY
  300.           add ax, di    ; update "across" coord
  301.           inc ch
  302.           jmp  @@RayLoop
  303.  
  304. @@HitY:   ; "across" (normal) hit
  305.           POP BX             ; retrieve bit-mapped sector info
  306.           xor dx, dx
  307.           shr bl, 2
  308.           rcr dx, 1          ; dx = "along" coord = 0 or 32768
  309.           mov [HitOfs], ax   ; ax = "across" coord
  310.           jmp @@leave
  311.  
  312. @@HitX:    ; "along" (overflow) hit
  313.  
  314.           mov bx, [Walls]
  315.           xchg bl,bh
  316.           mov [Walls], bx     ; signal which wall was hit
  317.  
  318.           ; ax = FY
  319.           POP BX
  320.           test bh, 10110100b  ; sectors 2,7,4,5 ?
  321.           jz @@noPreSub
  322.           neg di              ; (these sectors had negative slope)
  323.           SubFrom1 a          ; ...if so, "presubtract": ax = 1 - FY
  324. ;neg ax
  325. ;and ah,7f
  326. @@noPreSub:
  327.           mov dx, ax
  328.           xor ax, ax          ; dx:ax = 65536 * ax
  329.           shr dx,1
  330.           rcr ax, 1           ; dx:ax = 32768 * ax
  331.           div di              ; ax = (32768*ax)/slope
  332.  
  333.           test bh, 10000111b  ; sectors 0,1,2,7 ?
  334.           jz @@noPostSub
  335.           SubFrom1 a          ; ...if so, "postsubtract": ax = 1 - ax
  336. ;neg ax
  337. ;and ah,7f
  338.           dec ch
  339. @@noPostSub:
  340.           mov dx, ax          ; result is "along" coord value for hit
  341.           mov [HitOfs], dx    ;   save it!
  342.  
  343.           xor ax, ax
  344.           shr bl, 1
  345.           rcr ax, 1           ; ax = "across" coord = 0 or 32768
  346.  
  347. @@leave:
  348.           mov [Contents], cl  ; save cl = Map[MapY,MapX] of hit!
  349.           test bh, 01111000b  ; sectors 3,6,4,5 ?
  350.           jz @@grows
  351. @@shrinks:
  352.           mov di, [X0]
  353.           sub di, dx
  354.           test bl, 1
  355.           jz @@continue2
  356.           dec ch
  357.           jmp @@continue2
  358. @@grows:
  359.           mov di, dx
  360.           sub di, [X0]
  361. @@continue2:
  362.  
  363.           sar di, 7    ; di = (Xfinal-X0)/128  (32768/128=256)
  364.           xor cl, cl   ; cx = 256 * #steps
  365.           add cx, di   ; cx = EndX - StartX
  366.  
  367.           test bh, 01100110b  ; did we switch FX <-> FY ?
  368.           jz @@skipswitch2
  369.           xchg ax, dx
  370. @@skipswitch2:
  371.  
  372. ; here ds:si points to map coords of hit and ax=FY, dx=FX
  373.  
  374.           mov di, [outRay]
  375.           mov [di+SRay.FineX], dx    ; save coords
  376.           mov [di+SRay.FineY], ax
  377.  
  378.           mov ax, si
  379.           sub ax, offset Map
  380.  
  381. IF mps EQ 128d
  382.           shl ax, 1         ; AH = MapY = ofs div 128
  383.           shr al, 1         ; AL = MapX = ofs mod 128
  384. ENDIF
  385. IF mps EQ 64d
  386.           mov bl, al
  387.           shl ax, 2         ; AH = MapY = ofs div 64
  388.           mov al, bl        
  389.           and al, 3f        ; AL = MapX = ofs mod 64
  390. ENDIF
  391.  
  392.           mov [di+SRay.MapX], al
  393.           mov [di+SRay.MapY], ah
  394.  
  395.           mov ax, cx
  396.           mul [DistanceFactor]  ; dx:ax = 32768*distance
  397.           shl ax,1
  398.           rcl dx, 1             ; dx = distance (in 1/256 units)
  399.           add [di+SRay.Length], dx
  400.  
  401. @@Exit:
  402.  
  403. P286
  404.           popa
  405.           mov al, [Contents]         ; al = return map contents
  406.           mov ah, [byte ptr Walls]   ; ah = side of wall which was hit
  407.           mov dx, [HitOfs]           ; dx = hit offset along wall
  408.           test ah, 02
  409.           jz @@skipMirror            ; wall sides 2 & 3 run against
  410.           SubFrom1 d                 ; coord direction, dx = 32768-HitOfs
  411. @@skipMirror:
  412.  
  413.           ret
  414.         ENDP
  415.  
  416.  
  417.         END
  418.