diff options
Diffstat (limited to 'apps/plugins/sdl/progs/wolf3d/wl_draw.c')
-rw-r--r-- | apps/plugins/sdl/progs/wolf3d/wl_draw.c | 1647 |
1 files changed, 1647 insertions, 0 deletions
diff --git a/apps/plugins/sdl/progs/wolf3d/wl_draw.c b/apps/plugins/sdl/progs/wolf3d/wl_draw.c new file mode 100644 index 0000000000..625e93dc0a --- /dev/null +++ b/apps/plugins/sdl/progs/wolf3d/wl_draw.c | |||
@@ -0,0 +1,1647 @@ | |||
1 | // WL_DRAW.C | ||
2 | |||
3 | #include "wl_def.h" | ||
4 | #pragma hdrstop | ||
5 | |||
6 | #include "wl_cloudsky.h" | ||
7 | #include "wl_atmos.h" | ||
8 | #include "wl_shade.h" | ||
9 | |||
10 | /* | ||
11 | ============================================================================= | ||
12 | |||
13 | LOCAL CONSTANTS | ||
14 | |||
15 | ============================================================================= | ||
16 | */ | ||
17 | |||
18 | // the door is the last picture before the sprites | ||
19 | #define DOORWALL (PMSpriteStart-8) | ||
20 | |||
21 | #define ACTORSIZE 0x4000 | ||
22 | |||
23 | /* | ||
24 | ============================================================================= | ||
25 | |||
26 | GLOBAL VARIABLES | ||
27 | |||
28 | ============================================================================= | ||
29 | */ | ||
30 | |||
31 | static byte *vbuf = NULL; | ||
32 | unsigned vbufPitch = 0; | ||
33 | |||
34 | int32_t lasttimecount; | ||
35 | int32_t frameon; | ||
36 | boolean fpscounter; | ||
37 | |||
38 | int fps_frames=0, fps_time=0, fps=0; | ||
39 | |||
40 | int *wallheight; | ||
41 | int min_wallheight; | ||
42 | |||
43 | // | ||
44 | // math tables | ||
45 | // | ||
46 | short *pixelangle; | ||
47 | int32_t finetangent[FINEANGLES/4]; | ||
48 | fixed sintable[ANGLES+ANGLES/4]; | ||
49 | fixed *costable = sintable+(ANGLES/4); | ||
50 | |||
51 | // | ||
52 | // refresh variables | ||
53 | // | ||
54 | fixed viewx,viewy; // the focal point | ||
55 | short viewangle; | ||
56 | fixed viewsin,viewcos; | ||
57 | |||
58 | void TransformActor (objtype *ob); | ||
59 | void BuildTables (void); | ||
60 | void ClearScreen (void); | ||
61 | int CalcRotate (objtype *ob); | ||
62 | void DrawScaleds (void); | ||
63 | void CalcTics (void); | ||
64 | void ThreeDRefresh (void); | ||
65 | |||
66 | |||
67 | |||
68 | // | ||
69 | // wall optimization variables | ||
70 | // | ||
71 | int lastside; // true for vertical | ||
72 | int32_t lastintercept; | ||
73 | int lasttilehit; | ||
74 | int lasttexture; | ||
75 | |||
76 | // | ||
77 | // ray tracing variables | ||
78 | // | ||
79 | short focaltx,focalty,viewtx,viewty; | ||
80 | longword xpartialup,xpartialdown,ypartialup,ypartialdown; | ||
81 | |||
82 | short midangle,angle; | ||
83 | |||
84 | word tilehit; | ||
85 | int pixx; | ||
86 | |||
87 | short xtile,ytile; | ||
88 | short xtilestep,ytilestep; | ||
89 | int32_t xintercept,yintercept; | ||
90 | word xstep,ystep; | ||
91 | word xspot,yspot; | ||
92 | int texdelta; | ||
93 | |||
94 | word horizwall[MAXWALLTILES],vertwall[MAXWALLTILES]; | ||
95 | |||
96 | |||
97 | /* | ||
98 | ============================================================================ | ||
99 | |||
100 | 3 - D DEFINITIONS | ||
101 | |||
102 | ============================================================================ | ||
103 | */ | ||
104 | |||
105 | /* | ||
106 | ======================== | ||
107 | = | ||
108 | = TransformActor | ||
109 | = | ||
110 | = Takes paramaters: | ||
111 | = gx,gy : globalx/globaly of point | ||
112 | = | ||
113 | = globals: | ||
114 | = viewx,viewy : point of view | ||
115 | = viewcos,viewsin : sin/cos of viewangle | ||
116 | = scale : conversion from global value to screen value | ||
117 | = | ||
118 | = sets: | ||
119 | = screenx,transx,transy,screenheight: projected edge location and size | ||
120 | = | ||
121 | ======================== | ||
122 | */ | ||
123 | |||
124 | |||
125 | // | ||
126 | // transform actor | ||
127 | // | ||
128 | void TransformActor (objtype *ob) | ||
129 | { | ||
130 | fixed gx,gy,gxt,gyt,nx,ny; | ||
131 | |||
132 | // | ||
133 | // translate point to view centered coordinates | ||
134 | // | ||
135 | gx = ob->x-viewx; | ||
136 | gy = ob->y-viewy; | ||
137 | |||
138 | // | ||
139 | // calculate newx | ||
140 | // | ||
141 | gxt = FixedMul(gx,viewcos); | ||
142 | gyt = FixedMul(gy,viewsin); | ||
143 | nx = gxt-gyt-ACTORSIZE; // fudge the shape forward a bit, because | ||
144 | // the midpoint could put parts of the shape | ||
145 | // into an adjacent wall | ||
146 | |||
147 | // | ||
148 | // calculate newy | ||
149 | // | ||
150 | gxt = FixedMul(gx,viewsin); | ||
151 | gyt = FixedMul(gy,viewcos); | ||
152 | ny = gyt+gxt; | ||
153 | |||
154 | // | ||
155 | // calculate perspective ratio | ||
156 | // | ||
157 | ob->transx = nx; | ||
158 | ob->transy = ny; | ||
159 | |||
160 | if (nx<MINDIST) // too close, don't overflow the divide | ||
161 | { | ||
162 | ob->viewheight = 0; | ||
163 | return; | ||
164 | } | ||
165 | |||
166 | ob->viewx = (word)(centerx + ny*scale/nx); | ||
167 | |||
168 | // | ||
169 | // calculate height (heightnumerator/(nx>>8)) | ||
170 | // | ||
171 | ob->viewheight = (word)(heightnumerator/(nx>>8)); | ||
172 | } | ||
173 | |||
174 | //========================================================================== | ||
175 | |||
176 | /* | ||
177 | ======================== | ||
178 | = | ||
179 | = TransformTile | ||
180 | = | ||
181 | = Takes paramaters: | ||
182 | = tx,ty : tile the object is centered in | ||
183 | = | ||
184 | = globals: | ||
185 | = viewx,viewy : point of view | ||
186 | = viewcos,viewsin : sin/cos of viewangle | ||
187 | = scale : conversion from global value to screen value | ||
188 | = | ||
189 | = sets: | ||
190 | = screenx,transx,transy,screenheight: projected edge location and size | ||
191 | = | ||
192 | = Returns true if the tile is withing getting distance | ||
193 | = | ||
194 | ======================== | ||
195 | */ | ||
196 | |||
197 | boolean TransformTile (int tx, int ty, short *dispx, short *dispheight) | ||
198 | { | ||
199 | fixed gx,gy,gxt,gyt,nx,ny; | ||
200 | |||
201 | // | ||
202 | // translate point to view centered coordinates | ||
203 | // | ||
204 | gx = ((int32_t)tx<<TILESHIFT)+0x8000-viewx; | ||
205 | gy = ((int32_t)ty<<TILESHIFT)+0x8000-viewy; | ||
206 | |||
207 | // | ||
208 | // calculate newx | ||
209 | // | ||
210 | gxt = FixedMul(gx,viewcos); | ||
211 | gyt = FixedMul(gy,viewsin); | ||
212 | nx = gxt-gyt-0x2000; // 0x2000 is size of object | ||
213 | |||
214 | // | ||
215 | // calculate newy | ||
216 | // | ||
217 | gxt = FixedMul(gx,viewsin); | ||
218 | gyt = FixedMul(gy,viewcos); | ||
219 | ny = gyt+gxt; | ||
220 | |||
221 | |||
222 | // | ||
223 | // calculate height / perspective ratio | ||
224 | // | ||
225 | if (nx<MINDIST) // too close, don't overflow the divide | ||
226 | *dispheight = 0; | ||
227 | else | ||
228 | { | ||
229 | *dispx = (short)(centerx + ny*scale/nx); | ||
230 | *dispheight = (short)(heightnumerator/(nx>>8)); | ||
231 | } | ||
232 | |||
233 | // | ||
234 | // see if it should be grabbed | ||
235 | // | ||
236 | if (nx<TILEGLOBAL && ny>-TILEGLOBAL/2 && ny<TILEGLOBAL/2) | ||
237 | return true; | ||
238 | else | ||
239 | return false; | ||
240 | } | ||
241 | |||
242 | //========================================================================== | ||
243 | |||
244 | /* | ||
245 | ==================== | ||
246 | = | ||
247 | = CalcHeight | ||
248 | = | ||
249 | = Calculates the height of xintercept,yintercept from viewx,viewy | ||
250 | = | ||
251 | ==================== | ||
252 | */ | ||
253 | |||
254 | int CalcHeight() | ||
255 | { | ||
256 | fixed z = FixedMul(xintercept - viewx, viewcos) | ||
257 | - FixedMul(yintercept - viewy, viewsin); | ||
258 | if(z < MINDIST) z = MINDIST; | ||
259 | int height = heightnumerator / (z >> 8); | ||
260 | if(height < min_wallheight) min_wallheight = height; | ||
261 | return height; | ||
262 | } | ||
263 | |||
264 | //========================================================================== | ||
265 | |||
266 | /* | ||
267 | =================== | ||
268 | = | ||
269 | = ScalePost | ||
270 | = | ||
271 | =================== | ||
272 | */ | ||
273 | |||
274 | byte *postsource; | ||
275 | int postx; | ||
276 | int postwidth; | ||
277 | |||
278 | void ScalePost() | ||
279 | { | ||
280 | int ywcount, yoffs, yw, yd, yendoffs; | ||
281 | byte col; | ||
282 | |||
283 | #ifdef USE_SHADING | ||
284 | byte *curshades = shadetable[GetShade(wallheight[postx])]; | ||
285 | #endif | ||
286 | |||
287 | ywcount = yd = wallheight[postx] >> 3; | ||
288 | if(yd <= 0) yd = 100; | ||
289 | |||
290 | yoffs = (viewheight / 2 - ywcount) * vbufPitch; | ||
291 | if(yoffs < 0) yoffs = 0; | ||
292 | yoffs += postx; | ||
293 | |||
294 | yendoffs = viewheight / 2 + ywcount - 1; | ||
295 | yw=TEXTURESIZE-1; | ||
296 | |||
297 | while(yendoffs >= viewheight) | ||
298 | { | ||
299 | ywcount -= TEXTURESIZE/2; | ||
300 | while(ywcount <= 0) | ||
301 | { | ||
302 | ywcount += yd; | ||
303 | yw--; | ||
304 | } | ||
305 | yendoffs--; | ||
306 | } | ||
307 | if(yw < 0) return; | ||
308 | |||
309 | #ifdef USE_SHADING | ||
310 | col = curshades[postsource[yw]]; | ||
311 | #else | ||
312 | col = postsource[yw]; | ||
313 | #endif | ||
314 | yendoffs = yendoffs * vbufPitch + postx; | ||
315 | while(yoffs <= yendoffs) | ||
316 | { | ||
317 | vbuf[yendoffs] = col; | ||
318 | ywcount -= TEXTURESIZE/2; | ||
319 | if(ywcount <= 0) | ||
320 | { | ||
321 | do | ||
322 | { | ||
323 | ywcount += yd; | ||
324 | yw--; | ||
325 | } | ||
326 | while(ywcount <= 0); | ||
327 | if(yw < 0) break; | ||
328 | #ifdef USE_SHADING | ||
329 | col = curshades[postsource[yw]]; | ||
330 | #else | ||
331 | col = postsource[yw]; | ||
332 | #endif | ||
333 | } | ||
334 | yendoffs -= vbufPitch; | ||
335 | } | ||
336 | } | ||
337 | |||
338 | void GlobalScalePost(byte *vidbuf, unsigned pitch) | ||
339 | { | ||
340 | vbuf = vidbuf; | ||
341 | vbufPitch = pitch; | ||
342 | ScalePost(); | ||
343 | } | ||
344 | |||
345 | /* | ||
346 | ==================== | ||
347 | = | ||
348 | = HitVertWall | ||
349 | = | ||
350 | = tilehit bit 7 is 0, because it's not a door tile | ||
351 | = if bit 6 is 1 and the adjacent tile is a door tile, use door side pic | ||
352 | = | ||
353 | ==================== | ||
354 | */ | ||
355 | |||
356 | void HitVertWall (void) | ||
357 | { | ||
358 | int wallpic; | ||
359 | int texture; | ||
360 | |||
361 | texture = ((yintercept+texdelta)>>TEXTUREFROMFIXEDSHIFT)&TEXTUREMASK; | ||
362 | if (xtilestep == -1) | ||
363 | { | ||
364 | texture = TEXTUREMASK-texture; | ||
365 | xintercept += TILEGLOBAL; | ||
366 | } | ||
367 | |||
368 | if(lastside==1 && lastintercept==xtile && lasttilehit==tilehit && !(lasttilehit & 0x40)) | ||
369 | { | ||
370 | if((pixx&3) && texture == lasttexture) | ||
371 | { | ||
372 | ScalePost(); | ||
373 | postx = pixx; | ||
374 | wallheight[pixx] = wallheight[pixx-1]; | ||
375 | return; | ||
376 | } | ||
377 | ScalePost(); | ||
378 | wallheight[pixx] = CalcHeight(); | ||
379 | postsource+=texture-lasttexture; | ||
380 | postwidth=1; | ||
381 | postx=pixx; | ||
382 | lasttexture=texture; | ||
383 | return; | ||
384 | } | ||
385 | |||
386 | if(lastside!=-1) ScalePost(); | ||
387 | |||
388 | lastside=1; | ||
389 | lastintercept=xtile; | ||
390 | lasttilehit=tilehit; | ||
391 | lasttexture=texture; | ||
392 | wallheight[pixx] = CalcHeight(); | ||
393 | postx = pixx; | ||
394 | postwidth = 1; | ||
395 | |||
396 | if (tilehit & 0x40) | ||
397 | { // check for adjacent doors | ||
398 | ytile = (short)(yintercept>>TILESHIFT); | ||
399 | if ( tilemap[xtile-xtilestep][ytile]&0x80 ) | ||
400 | wallpic = DOORWALL+3; | ||
401 | else | ||
402 | wallpic = vertwall[tilehit & ~0x40]; | ||
403 | } | ||
404 | else | ||
405 | wallpic = vertwall[tilehit]; | ||
406 | |||
407 | postsource = PM_GetTexture(wallpic) + texture; | ||
408 | } | ||
409 | |||
410 | |||
411 | /* | ||
412 | ==================== | ||
413 | = | ||
414 | = HitHorizWall | ||
415 | = | ||
416 | = tilehit bit 7 is 0, because it's not a door tile | ||
417 | = if bit 6 is 1 and the adjacent tile is a door tile, use door side pic | ||
418 | = | ||
419 | ==================== | ||
420 | */ | ||
421 | |||
422 | void HitHorizWall (void) | ||
423 | { | ||
424 | int wallpic; | ||
425 | int texture; | ||
426 | |||
427 | texture = ((xintercept+texdelta)>>TEXTUREFROMFIXEDSHIFT)&TEXTUREMASK; | ||
428 | if (ytilestep == -1) | ||
429 | yintercept += TILEGLOBAL; | ||
430 | else | ||
431 | texture = TEXTUREMASK-texture; | ||
432 | |||
433 | if(lastside==0 && lastintercept==ytile && lasttilehit==tilehit && !(lasttilehit & 0x40)) | ||
434 | { | ||
435 | if((pixx&3) && texture == lasttexture) | ||
436 | { | ||
437 | ScalePost(); | ||
438 | postx=pixx; | ||
439 | wallheight[pixx] = wallheight[pixx-1]; | ||
440 | return; | ||
441 | } | ||
442 | ScalePost(); | ||
443 | wallheight[pixx] = CalcHeight(); | ||
444 | postsource+=texture-lasttexture; | ||
445 | postwidth=1; | ||
446 | postx=pixx; | ||
447 | lasttexture=texture; | ||
448 | return; | ||
449 | } | ||
450 | |||
451 | if(lastside!=-1) ScalePost(); | ||
452 | |||
453 | lastside=0; | ||
454 | lastintercept=ytile; | ||
455 | lasttilehit=tilehit; | ||
456 | lasttexture=texture; | ||
457 | wallheight[pixx] = CalcHeight(); | ||
458 | postx = pixx; | ||
459 | postwidth = 1; | ||
460 | |||
461 | if (tilehit & 0x40) | ||
462 | { // check for adjacent doors | ||
463 | xtile = (short)(xintercept>>TILESHIFT); | ||
464 | if ( tilemap[xtile][ytile-ytilestep]&0x80) | ||
465 | wallpic = DOORWALL+2; | ||
466 | else | ||
467 | wallpic = horizwall[tilehit & ~0x40]; | ||
468 | } | ||
469 | else | ||
470 | wallpic = horizwall[tilehit]; | ||
471 | |||
472 | postsource = PM_GetTexture(wallpic) + texture; | ||
473 | } | ||
474 | |||
475 | //========================================================================== | ||
476 | |||
477 | /* | ||
478 | ==================== | ||
479 | = | ||
480 | = HitHorizDoor | ||
481 | = | ||
482 | ==================== | ||
483 | */ | ||
484 | |||
485 | void HitHorizDoor (void) | ||
486 | { | ||
487 | int doorpage; | ||
488 | int doornum; | ||
489 | int texture; | ||
490 | |||
491 | doornum = tilehit&0x7f; | ||
492 | texture = ((xintercept-doorposition[doornum])>>TEXTUREFROMFIXEDSHIFT)&TEXTUREMASK; | ||
493 | |||
494 | if(lasttilehit==tilehit) | ||
495 | { | ||
496 | if((pixx&3) && texture == lasttexture) | ||
497 | { | ||
498 | ScalePost(); | ||
499 | postx=pixx; | ||
500 | wallheight[pixx] = wallheight[pixx-1]; | ||
501 | return; | ||
502 | } | ||
503 | ScalePost(); | ||
504 | wallheight[pixx] = CalcHeight(); | ||
505 | postsource+=texture-lasttexture; | ||
506 | postwidth=1; | ||
507 | postx=pixx; | ||
508 | lasttexture=texture; | ||
509 | return; | ||
510 | } | ||
511 | |||
512 | if(lastside!=-1) ScalePost(); | ||
513 | |||
514 | lastside=2; | ||
515 | lasttilehit=tilehit; | ||
516 | lasttexture=texture; | ||
517 | wallheight[pixx] = CalcHeight(); | ||
518 | postx = pixx; | ||
519 | postwidth = 1; | ||
520 | |||
521 | switch(doorobjlist[doornum].lock) | ||
522 | { | ||
523 | case dr_normal: | ||
524 | doorpage = DOORWALL; | ||
525 | break; | ||
526 | case dr_lock1: | ||
527 | case dr_lock2: | ||
528 | case dr_lock3: | ||
529 | case dr_lock4: | ||
530 | doorpage = DOORWALL+6; | ||
531 | break; | ||
532 | case dr_elevator: | ||
533 | doorpage = DOORWALL+4; | ||
534 | break; | ||
535 | } | ||
536 | |||
537 | postsource = PM_GetTexture(doorpage) + texture; | ||
538 | } | ||
539 | |||
540 | //========================================================================== | ||
541 | |||
542 | /* | ||
543 | ==================== | ||
544 | = | ||
545 | = HitVertDoor | ||
546 | = | ||
547 | ==================== | ||
548 | */ | ||
549 | |||
550 | void HitVertDoor (void) | ||
551 | { | ||
552 | int doorpage; | ||
553 | int doornum; | ||
554 | int texture; | ||
555 | |||
556 | doornum = tilehit&0x7f; | ||
557 | texture = ((yintercept-doorposition[doornum])>>TEXTUREFROMFIXEDSHIFT)&TEXTUREMASK; | ||
558 | |||
559 | if(lasttilehit==tilehit) | ||
560 | { | ||
561 | if((pixx&3) && texture == lasttexture) | ||
562 | { | ||
563 | ScalePost(); | ||
564 | postx=pixx; | ||
565 | wallheight[pixx] = wallheight[pixx-1]; | ||
566 | return; | ||
567 | } | ||
568 | ScalePost(); | ||
569 | wallheight[pixx] = CalcHeight(); | ||
570 | postsource+=texture-lasttexture; | ||
571 | postwidth=1; | ||
572 | postx=pixx; | ||
573 | lasttexture=texture; | ||
574 | return; | ||
575 | } | ||
576 | |||
577 | if(lastside!=-1) ScalePost(); | ||
578 | |||
579 | lastside=2; | ||
580 | lasttilehit=tilehit; | ||
581 | lasttexture=texture; | ||
582 | wallheight[pixx] = CalcHeight(); | ||
583 | postx = pixx; | ||
584 | postwidth = 1; | ||
585 | |||
586 | switch(doorobjlist[doornum].lock) | ||
587 | { | ||
588 | case dr_normal: | ||
589 | doorpage = DOORWALL+1; | ||
590 | break; | ||
591 | case dr_lock1: | ||
592 | case dr_lock2: | ||
593 | case dr_lock3: | ||
594 | case dr_lock4: | ||
595 | doorpage = DOORWALL+7; | ||
596 | break; | ||
597 | case dr_elevator: | ||
598 | doorpage = DOORWALL+5; | ||
599 | break; | ||
600 | } | ||
601 | |||
602 | postsource = PM_GetTexture(doorpage) + texture; | ||
603 | } | ||
604 | |||
605 | //========================================================================== | ||
606 | |||
607 | #define HitHorizBorder HitHorizWall | ||
608 | #define HitVertBorder HitVertWall | ||
609 | |||
610 | //========================================================================== | ||
611 | |||
612 | byte vgaCeiling[]= | ||
613 | { | ||
614 | #ifndef SPEAR | ||
615 | 0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0xbf, | ||
616 | 0x4e,0x4e,0x4e,0x1d,0x8d,0x4e,0x1d,0x2d,0x1d,0x8d, | ||
617 | 0x1d,0x1d,0x1d,0x1d,0x1d,0x2d,0xdd,0x1d,0x1d,0x98, | ||
618 | |||
619 | 0x1d,0x9d,0x2d,0xdd,0xdd,0x9d,0x2d,0x4d,0x1d,0xdd, | ||
620 | 0x7d,0x1d,0x2d,0x2d,0xdd,0xd7,0x1d,0x1d,0x1d,0x2d, | ||
621 | 0x1d,0x1d,0x1d,0x1d,0xdd,0xdd,0x7d,0xdd,0xdd,0xdd | ||
622 | #else | ||
623 | 0x6f,0x4f,0x1d,0xde,0xdf,0x2e,0x7f,0x9e,0xae,0x7f, | ||
624 | 0x1d,0xde,0xdf,0xde,0xdf,0xde,0xe1,0xdc,0x2e,0x1d,0xdc | ||
625 | #endif | ||
626 | }; | ||
627 | |||
628 | /* | ||
629 | ===================== | ||
630 | = | ||
631 | = VGAClearScreen | ||
632 | = | ||
633 | ===================== | ||
634 | */ | ||
635 | |||
636 | void VGAClearScreen (void) | ||
637 | { | ||
638 | byte ceiling=vgaCeiling[gamestate.episode*10+mapon]; | ||
639 | |||
640 | int y; | ||
641 | byte *ptr = vbuf; | ||
642 | #ifdef USE_SHADING | ||
643 | for(y = 0; y < viewheight / 2; y++, ptr += vbufPitch) | ||
644 | memset(ptr, shadetable[GetShade((viewheight / 2 - y) << 3)][ceiling], viewwidth); | ||
645 | for(; y < viewheight; y++, ptr += vbufPitch) | ||
646 | memset(ptr, shadetable[GetShade((y - viewheight / 2) << 3)][0x19], viewwidth); | ||
647 | #else | ||
648 | for(y = 0; y < viewheight / 2; y++, ptr += vbufPitch) | ||
649 | memset(ptr, ceiling, viewwidth); | ||
650 | for(; y < viewheight; y++, ptr += vbufPitch) | ||
651 | memset(ptr, 0x19, viewwidth); | ||
652 | #endif | ||
653 | } | ||
654 | |||
655 | //========================================================================== | ||
656 | |||
657 | /* | ||
658 | ===================== | ||
659 | = | ||
660 | = CalcRotate | ||
661 | = | ||
662 | ===================== | ||
663 | */ | ||
664 | |||
665 | int CalcRotate (objtype *ob) | ||
666 | { | ||
667 | int angle, viewangle; | ||
668 | |||
669 | // this isn't exactly correct, as it should vary by a trig value, | ||
670 | // but it is close enough with only eight rotations | ||
671 | |||
672 | viewangle = player->angle + (centerx - ob->viewx)/8; | ||
673 | |||
674 | if (ob->obclass == rocketobj || ob->obclass == hrocketobj) | ||
675 | angle = (viewangle-180) - ob->angle; | ||
676 | else | ||
677 | angle = (viewangle-180) - dirangle[ob->dir]; | ||
678 | |||
679 | angle+=ANGLES/16; | ||
680 | while (angle>=ANGLES) | ||
681 | angle-=ANGLES; | ||
682 | while (angle<0) | ||
683 | angle+=ANGLES; | ||
684 | |||
685 | if (ob->state->rotate == 2) // 2 rotation pain frame | ||
686 | return 0; // pain with shooting frame bugfix | ||
687 | |||
688 | return angle/(ANGLES/8); | ||
689 | } | ||
690 | |||
691 | void ScaleShape (int xcenter, int shapenum, unsigned height, uint32_t flags) | ||
692 | { | ||
693 | t_compshape *shape; | ||
694 | unsigned scale,pixheight; | ||
695 | unsigned starty,endy; | ||
696 | word *cmdptr; | ||
697 | byte *cline; | ||
698 | byte *line; | ||
699 | byte *vmem; | ||
700 | int actx,i,upperedge; | ||
701 | short newstart; | ||
702 | int scrstarty,screndy,lpix,rpix,pixcnt,ycnt; | ||
703 | unsigned j; | ||
704 | byte col; | ||
705 | |||
706 | #ifdef USE_SHADING | ||
707 | byte *curshades; | ||
708 | if(flags & FL_FULLBRIGHT) | ||
709 | curshades = shadetable[0]; | ||
710 | else | ||
711 | curshades = shadetable[GetShade(height)]; | ||
712 | #endif | ||
713 | |||
714 | shape = (t_compshape *) PM_GetSprite(shapenum); | ||
715 | |||
716 | scale=height>>3; // low three bits are fractional | ||
717 | if(!scale) return; // too close or far away | ||
718 | |||
719 | pixheight=scale*SPRITESCALEFACTOR; | ||
720 | actx=xcenter-scale; | ||
721 | upperedge=viewheight/2-scale; | ||
722 | |||
723 | cmdptr=(word *) shape->dataofs; | ||
724 | |||
725 | for(i=shape->leftpix,pixcnt=i*pixheight,rpix=(pixcnt>>6)+actx;i<=shape->rightpix;i++,cmdptr++) | ||
726 | { | ||
727 | lpix=rpix; | ||
728 | if(lpix>=viewwidth) break; | ||
729 | pixcnt+=pixheight; | ||
730 | rpix=(pixcnt>>6)+actx; | ||
731 | if(lpix!=rpix && rpix>0) | ||
732 | { | ||
733 | if(lpix<0) lpix=0; | ||
734 | if(rpix>viewwidth) rpix=viewwidth,i=shape->rightpix+1; | ||
735 | cline=(byte *)shape + *cmdptr; | ||
736 | while(lpix<rpix) | ||
737 | { | ||
738 | if(wallheight[lpix]<=(int)height) | ||
739 | { | ||
740 | line=cline; | ||
741 | while((endy = READWORD(&line)) != 0) | ||
742 | { | ||
743 | endy >>= 1; | ||
744 | newstart = READWORD(&line); | ||
745 | starty = READWORD(&line) >> 1; | ||
746 | j=starty; | ||
747 | ycnt=j*pixheight; | ||
748 | screndy=(ycnt>>6)+upperedge; | ||
749 | if(screndy<0) vmem=vbuf+lpix; | ||
750 | else vmem=vbuf+screndy*vbufPitch+lpix; | ||
751 | for(;j<endy;j++) | ||
752 | { | ||
753 | scrstarty=screndy; | ||
754 | ycnt+=pixheight; | ||
755 | screndy=(ycnt>>6)+upperedge; | ||
756 | if(scrstarty!=screndy && screndy>0) | ||
757 | { | ||
758 | #ifdef USE_SHADING | ||
759 | col=curshades[((byte *)shape)[newstart+j]]; | ||
760 | #else | ||
761 | col=((byte *)shape)[newstart+j]; | ||
762 | #endif | ||
763 | if(scrstarty<0) scrstarty=0; | ||
764 | if(screndy>viewheight) screndy=viewheight,j=endy; | ||
765 | |||
766 | while(scrstarty<screndy) | ||
767 | { | ||
768 | *vmem=col; | ||
769 | vmem+=vbufPitch; | ||
770 | scrstarty++; | ||
771 | } | ||
772 | } | ||
773 | } | ||
774 | } | ||
775 | } | ||
776 | lpix++; | ||
777 | } | ||
778 | } | ||
779 | } | ||
780 | } | ||
781 | |||
782 | void SimpleScaleShape (int xcenter, int shapenum, unsigned height) | ||
783 | { | ||
784 | t_compshape *shape; | ||
785 | unsigned scale,pixheight; | ||
786 | unsigned starty,endy; | ||
787 | word *cmdptr; | ||
788 | byte *cline; | ||
789 | byte *line; | ||
790 | int actx,i,upperedge; | ||
791 | short newstart; | ||
792 | int scrstarty,screndy,lpix,rpix,pixcnt,ycnt; | ||
793 | unsigned j; | ||
794 | byte col; | ||
795 | byte *vmem; | ||
796 | |||
797 | shape = (t_compshape *) PM_GetSprite(shapenum); | ||
798 | |||
799 | scale=height>>1; | ||
800 | pixheight=scale*SPRITESCALEFACTOR; | ||
801 | actx=xcenter-scale; | ||
802 | upperedge=viewheight/2-scale; | ||
803 | |||
804 | cmdptr=shape->dataofs; | ||
805 | |||
806 | for(i=shape->leftpix,pixcnt=i*pixheight,rpix=(pixcnt>>6)+actx;i<=shape->rightpix;i++,cmdptr++) | ||
807 | { | ||
808 | lpix=rpix; | ||
809 | if(lpix>=viewwidth) break; | ||
810 | pixcnt+=pixheight; | ||
811 | rpix=(pixcnt>>6)+actx; | ||
812 | if(lpix!=rpix && rpix>0) | ||
813 | { | ||
814 | if(lpix<0) lpix=0; | ||
815 | if(rpix>viewwidth) rpix=viewwidth,i=shape->rightpix+1; | ||
816 | cline = (byte *)shape + *cmdptr; | ||
817 | while(lpix<rpix) | ||
818 | { | ||
819 | line=cline; | ||
820 | while((endy = READWORD(&line)) != 0) | ||
821 | { | ||
822 | endy >>= 1; | ||
823 | newstart = READWORD(&line); | ||
824 | starty = READWORD(&line) >> 1; | ||
825 | j=starty; | ||
826 | ycnt=j*pixheight; | ||
827 | screndy=(ycnt>>6)+upperedge; | ||
828 | if(screndy<0) vmem=vbuf+lpix; | ||
829 | else vmem=vbuf+screndy*vbufPitch+lpix; | ||
830 | for(;j<endy;j++) | ||
831 | { | ||
832 | scrstarty=screndy; | ||
833 | ycnt+=pixheight; | ||
834 | screndy=(ycnt>>6)+upperedge; | ||
835 | if(scrstarty!=screndy && screndy>0) | ||
836 | { | ||
837 | col=((byte *)shape)[newstart+j]; | ||
838 | if(scrstarty<0) scrstarty=0; | ||
839 | if(screndy>viewheight) screndy=viewheight,j=endy; | ||
840 | |||
841 | while(scrstarty<screndy) | ||
842 | { | ||
843 | *vmem=col; | ||
844 | vmem+=vbufPitch; | ||
845 | scrstarty++; | ||
846 | } | ||
847 | } | ||
848 | } | ||
849 | } | ||
850 | lpix++; | ||
851 | } | ||
852 | } | ||
853 | } | ||
854 | } | ||
855 | |||
856 | /* | ||
857 | ===================== | ||
858 | = | ||
859 | = DrawScaleds | ||
860 | = | ||
861 | = Draws all objects that are visable | ||
862 | = | ||
863 | ===================== | ||
864 | */ | ||
865 | |||
866 | #define MAXVISABLE 250 | ||
867 | |||
868 | typedef struct | ||
869 | { | ||
870 | short viewx, | ||
871 | viewheight, | ||
872 | shapenum; | ||
873 | short flags; // this must be changed to uint32_t, when you | ||
874 | // you need more than 16-flags for drawing | ||
875 | #ifdef USE_DIR3DSPR | ||
876 | statobj_t *transsprite; | ||
877 | #endif | ||
878 | } visobj_t; | ||
879 | |||
880 | visobj_t vislist[MAXVISABLE]; | ||
881 | visobj_t *visptr,*visstep,*farthest; | ||
882 | |||
883 | void DrawScaleds (void) | ||
884 | { | ||
885 | int i,least,numvisable,height; | ||
886 | byte *tilespot,*visspot; | ||
887 | unsigned spotloc; | ||
888 | |||
889 | statobj_t *statptr; | ||
890 | objtype *obj; | ||
891 | |||
892 | visptr = &vislist[0]; | ||
893 | |||
894 | // | ||
895 | // place static objects | ||
896 | // | ||
897 | for (statptr = &statobjlist[0] ; statptr !=laststatobj ; statptr++) | ||
898 | { | ||
899 | if ((visptr->shapenum = statptr->shapenum) == -1) | ||
900 | continue; // object has been deleted | ||
901 | |||
902 | if (!*statptr->visspot) | ||
903 | continue; // not visable | ||
904 | |||
905 | if (TransformTile (statptr->tilex,statptr->tiley, | ||
906 | &visptr->viewx,&visptr->viewheight) && statptr->flags & FL_BONUS) | ||
907 | { | ||
908 | GetBonus (statptr); | ||
909 | if(statptr->shapenum == -1) | ||
910 | continue; // object has been taken | ||
911 | } | ||
912 | |||
913 | if (!visptr->viewheight) | ||
914 | continue; // to close to the object | ||
915 | |||
916 | #ifdef USE_DIR3DSPR | ||
917 | if(statptr->flags & FL_DIR_MASK) | ||
918 | visptr->transsprite=statptr; | ||
919 | else | ||
920 | visptr->transsprite=NULL; | ||
921 | #endif | ||
922 | |||
923 | if (visptr < &vislist[MAXVISABLE-1]) // don't let it overflow | ||
924 | { | ||
925 | visptr->flags = (short) statptr->flags; | ||
926 | visptr++; | ||
927 | } | ||
928 | } | ||
929 | |||
930 | // | ||
931 | // place active objects | ||
932 | // | ||
933 | for (obj = player->next;obj;obj=obj->next) | ||
934 | { | ||
935 | if ((visptr->shapenum = obj->state->shapenum)==0) | ||
936 | continue; // no shape | ||
937 | |||
938 | spotloc = (obj->tilex<<mapshift)+obj->tiley; // optimize: keep in struct? | ||
939 | visspot = &spotvis[0][0]+spotloc; | ||
940 | tilespot = &tilemap[0][0]+spotloc; | ||
941 | |||
942 | // | ||
943 | // could be in any of the nine surrounding tiles | ||
944 | // | ||
945 | if (*visspot | ||
946 | || ( *(visspot-1) && !*(tilespot-1) ) | ||
947 | || ( *(visspot+1) && !*(tilespot+1) ) | ||
948 | || ( *(visspot-65) && !*(tilespot-65) ) | ||
949 | || ( *(visspot-64) && !*(tilespot-64) ) | ||
950 | || ( *(visspot-63) && !*(tilespot-63) ) | ||
951 | || ( *(visspot+65) && !*(tilespot+65) ) | ||
952 | || ( *(visspot+64) && !*(tilespot+64) ) | ||
953 | || ( *(visspot+63) && !*(tilespot+63) ) ) | ||
954 | { | ||
955 | obj->active = ac_yes; | ||
956 | TransformActor (obj); | ||
957 | if (!obj->viewheight) | ||
958 | continue; // too close or far away | ||
959 | |||
960 | visptr->viewx = obj->viewx; | ||
961 | visptr->viewheight = obj->viewheight; | ||
962 | if (visptr->shapenum == -1) | ||
963 | visptr->shapenum = obj->temp1; // special shape | ||
964 | |||
965 | if (obj->state->rotate) | ||
966 | visptr->shapenum += CalcRotate (obj); | ||
967 | |||
968 | if (visptr < &vislist[MAXVISABLE-1]) // don't let it overflow | ||
969 | { | ||
970 | visptr->flags = (short) obj->flags; | ||
971 | #ifdef USE_DIR3DSPR | ||
972 | visptr->transsprite = NULL; | ||
973 | #endif | ||
974 | visptr++; | ||
975 | } | ||
976 | obj->flags |= FL_VISABLE; | ||
977 | } | ||
978 | else | ||
979 | obj->flags &= ~FL_VISABLE; | ||
980 | } | ||
981 | |||
982 | // | ||
983 | // draw from back to front | ||
984 | // | ||
985 | numvisable = (int) (visptr-&vislist[0]); | ||
986 | |||
987 | if (!numvisable) | ||
988 | return; // no visable objects | ||
989 | |||
990 | for (i = 0; i<numvisable; i++) | ||
991 | { | ||
992 | least = 32000; | ||
993 | for (visstep=&vislist[0] ; visstep<visptr ; visstep++) | ||
994 | { | ||
995 | height = visstep->viewheight; | ||
996 | if (height < least) | ||
997 | { | ||
998 | least = height; | ||
999 | farthest = visstep; | ||
1000 | } | ||
1001 | } | ||
1002 | // | ||
1003 | // draw farthest | ||
1004 | // | ||
1005 | #ifdef USE_DIR3DSPR | ||
1006 | if(farthest->transsprite) | ||
1007 | Scale3DShape(vbuf, vbufPitch, farthest->transsprite); | ||
1008 | else | ||
1009 | #endif | ||
1010 | ScaleShape(farthest->viewx, farthest->shapenum, farthest->viewheight, farthest->flags); | ||
1011 | |||
1012 | farthest->viewheight = 32000; | ||
1013 | } | ||
1014 | } | ||
1015 | |||
1016 | //========================================================================== | ||
1017 | |||
1018 | /* | ||
1019 | ============== | ||
1020 | = | ||
1021 | = DrawPlayerWeapon | ||
1022 | = | ||
1023 | = Draw the player's hands | ||
1024 | = | ||
1025 | ============== | ||
1026 | */ | ||
1027 | |||
1028 | int weaponscale[NUMWEAPONS] = {SPR_KNIFEREADY, SPR_PISTOLREADY, | ||
1029 | SPR_MACHINEGUNREADY, SPR_CHAINREADY}; | ||
1030 | |||
1031 | void DrawPlayerWeapon (void) | ||
1032 | { | ||
1033 | int shapenum; | ||
1034 | |||
1035 | #ifndef SPEAR | ||
1036 | if (gamestate.victoryflag) | ||
1037 | { | ||
1038 | #ifndef APOGEE_1_0 | ||
1039 | if (player->state == &s_deathcam && (GetTimeCount()&32) ) | ||
1040 | SimpleScaleShape(viewwidth/2,SPR_DEATHCAM,viewheight+1); | ||
1041 | #endif | ||
1042 | return; | ||
1043 | } | ||
1044 | #endif | ||
1045 | |||
1046 | if (gamestate.weapon != -1) | ||
1047 | { | ||
1048 | shapenum = weaponscale[gamestate.weapon]+gamestate.weaponframe; | ||
1049 | SimpleScaleShape(viewwidth/2,shapenum,viewheight+1); | ||
1050 | } | ||
1051 | |||
1052 | if (demorecord || demoplayback) | ||
1053 | SimpleScaleShape(viewwidth/2,SPR_DEMO,viewheight+1); | ||
1054 | } | ||
1055 | |||
1056 | |||
1057 | //========================================================================== | ||
1058 | |||
1059 | |||
1060 | /* | ||
1061 | ===================== | ||
1062 | = | ||
1063 | = CalcTics | ||
1064 | = | ||
1065 | ===================== | ||
1066 | */ | ||
1067 | |||
1068 | void CalcTics (void) | ||
1069 | { | ||
1070 | // | ||
1071 | // calculate tics since last refresh for adaptive timing | ||
1072 | // | ||
1073 | if (lasttimecount > (int32_t) GetTimeCount()) | ||
1074 | lasttimecount = GetTimeCount(); // if the game was paused a LONG time | ||
1075 | |||
1076 | uint32_t curtime = SDL_GetTicks(); | ||
1077 | tics = (curtime * 7) / 100 - lasttimecount; | ||
1078 | if(!tics) | ||
1079 | { | ||
1080 | // wait until end of current tic | ||
1081 | SDL_Delay(((lasttimecount + 1) * 100) / 7 - curtime); | ||
1082 | tics = 1; | ||
1083 | } | ||
1084 | |||
1085 | lasttimecount += tics; | ||
1086 | |||
1087 | if (tics>MAXTICS) | ||
1088 | tics = MAXTICS; | ||
1089 | } | ||
1090 | |||
1091 | |||
1092 | //========================================================================== | ||
1093 | |||
1094 | void AsmRefresh() | ||
1095 | { | ||
1096 | int32_t xstep,ystep; | ||
1097 | longword xpartial,ypartial; | ||
1098 | boolean playerInPushwallBackTile = tilemap[focaltx][focalty] == 64; | ||
1099 | |||
1100 | for(pixx=0;pixx<viewwidth;pixx++) | ||
1101 | { | ||
1102 | short angl=midangle+pixelangle[pixx]; | ||
1103 | if(angl<0) angl+=FINEANGLES; | ||
1104 | if(angl>=3600) angl-=FINEANGLES; | ||
1105 | if(angl<900) | ||
1106 | { | ||
1107 | xtilestep=1; | ||
1108 | ytilestep=-1; | ||
1109 | xstep=finetangent[900-1-angl]; | ||
1110 | ystep=-finetangent[angl]; | ||
1111 | xpartial=xpartialup; | ||
1112 | ypartial=ypartialdown; | ||
1113 | } | ||
1114 | else if(angl<1800) | ||
1115 | { | ||
1116 | xtilestep=-1; | ||
1117 | ytilestep=-1; | ||
1118 | xstep=-finetangent[angl-900]; | ||
1119 | ystep=-finetangent[1800-1-angl]; | ||
1120 | xpartial=xpartialdown; | ||
1121 | ypartial=ypartialdown; | ||
1122 | } | ||
1123 | else if(angl<2700) | ||
1124 | { | ||
1125 | xtilestep=-1; | ||
1126 | ytilestep=1; | ||
1127 | xstep=-finetangent[2700-1-angl]; | ||
1128 | ystep=finetangent[angl-1800]; | ||
1129 | xpartial=xpartialdown; | ||
1130 | ypartial=ypartialup; | ||
1131 | } | ||
1132 | else if(angl<3600) | ||
1133 | { | ||
1134 | xtilestep=1; | ||
1135 | ytilestep=1; | ||
1136 | xstep=finetangent[angl-2700]; | ||
1137 | ystep=finetangent[3600-1-angl]; | ||
1138 | xpartial=xpartialup; | ||
1139 | ypartial=ypartialup; | ||
1140 | } | ||
1141 | yintercept=FixedMul(ystep,xpartial)+viewy; | ||
1142 | xtile=focaltx+xtilestep; | ||
1143 | xspot=(word)((xtile<<mapshift)+((uint32_t)yintercept>>16)); | ||
1144 | xintercept=FixedMul(xstep,ypartial)+viewx; | ||
1145 | ytile=focalty+ytilestep; | ||
1146 | yspot=(word)((((uint32_t)xintercept>>16)<<mapshift)+ytile); | ||
1147 | texdelta=0; | ||
1148 | |||
1149 | // Special treatment when player is in back tile of pushwall | ||
1150 | if(playerInPushwallBackTile) | ||
1151 | { | ||
1152 | if( pwalldir == di_east && xtilestep == 1 | ||
1153 | || pwalldir == di_west && xtilestep == -1) | ||
1154 | { | ||
1155 | int32_t yintbuf = yintercept - ((ystep * (64 - pwallpos)) >> 6); | ||
1156 | if((yintbuf >> 16) == focalty) // ray hits pushwall back? | ||
1157 | { | ||
1158 | if(pwalldir == di_east) | ||
1159 | xintercept = (focaltx << TILESHIFT) + (pwallpos << 10); | ||
1160 | else | ||
1161 | xintercept = (focaltx << TILESHIFT) - TILEGLOBAL + ((64 - pwallpos) << 10); | ||
1162 | yintercept = yintbuf; | ||
1163 | ytile = (short) (yintercept >> TILESHIFT); | ||
1164 | tilehit = pwalltile; | ||
1165 | HitVertWall(); | ||
1166 | continue; | ||
1167 | } | ||
1168 | } | ||
1169 | else if(pwalldir == di_south && ytilestep == 1 | ||
1170 | || pwalldir == di_north && ytilestep == -1) | ||
1171 | { | ||
1172 | int32_t xintbuf = xintercept - ((xstep * (64 - pwallpos)) >> 6); | ||
1173 | if((xintbuf >> 16) == focaltx) // ray hits pushwall back? | ||
1174 | { | ||
1175 | xintercept = xintbuf; | ||
1176 | if(pwalldir == di_south) | ||
1177 | yintercept = (focalty << TILESHIFT) + (pwallpos << 10); | ||
1178 | else | ||
1179 | yintercept = (focalty << TILESHIFT) - TILEGLOBAL + ((64 - pwallpos) << 10); | ||
1180 | xtile = (short) (xintercept >> TILESHIFT); | ||
1181 | tilehit = pwalltile; | ||
1182 | HitHorizWall(); | ||
1183 | continue; | ||
1184 | } | ||
1185 | } | ||
1186 | } | ||
1187 | |||
1188 | do | ||
1189 | { | ||
1190 | if(ytilestep==-1 && (yintercept>>16)<=ytile) goto horizentry; | ||
1191 | if(ytilestep==1 && (yintercept>>16)>=ytile) goto horizentry; | ||
1192 | vertentry: | ||
1193 | if((uint32_t)yintercept>mapheight*65536-1 || (word)xtile>=mapwidth) | ||
1194 | { | ||
1195 | if(xtile<0) xintercept=0, xtile=0; | ||
1196 | else if(xtile>=mapwidth) xintercept=mapwidth<<TILESHIFT, xtile=mapwidth-1; | ||
1197 | else xtile=(short) (xintercept >> TILESHIFT); | ||
1198 | if(yintercept<0) yintercept=0, ytile=0; | ||
1199 | else if(yintercept>=(mapheight<<TILESHIFT)) yintercept=mapheight<<TILESHIFT, ytile=mapheight-1; | ||
1200 | yspot=0xffff; | ||
1201 | tilehit=0; | ||
1202 | HitHorizBorder(); | ||
1203 | break; | ||
1204 | } | ||
1205 | if(xspot>=maparea) break; | ||
1206 | tilehit=((byte *)tilemap)[xspot]; | ||
1207 | if(tilehit) | ||
1208 | { | ||
1209 | if(tilehit&0x80) | ||
1210 | { | ||
1211 | int32_t yintbuf=yintercept+(ystep>>1); | ||
1212 | if((yintbuf>>16)!=(yintercept>>16)) | ||
1213 | goto passvert; | ||
1214 | if((word)yintbuf<doorposition[tilehit&0x7f]) | ||
1215 | goto passvert; | ||
1216 | yintercept=yintbuf; | ||
1217 | xintercept=(xtile<<TILESHIFT)|0x8000; | ||
1218 | ytile = (short) (yintercept >> TILESHIFT); | ||
1219 | HitVertDoor(); | ||
1220 | } | ||
1221 | else | ||
1222 | { | ||
1223 | if(tilehit==64) | ||
1224 | { | ||
1225 | if(pwalldir==di_west || pwalldir==di_east) | ||
1226 | { | ||
1227 | int32_t yintbuf; | ||
1228 | int pwallposnorm; | ||
1229 | int pwallposinv; | ||
1230 | if(pwalldir==di_west) | ||
1231 | { | ||
1232 | pwallposnorm = 64-pwallpos; | ||
1233 | pwallposinv = pwallpos; | ||
1234 | } | ||
1235 | else | ||
1236 | { | ||
1237 | pwallposnorm = pwallpos; | ||
1238 | pwallposinv = 64-pwallpos; | ||
1239 | } | ||
1240 | if(pwalldir == di_east && xtile==pwallx && ((uint32_t)yintercept>>16)==pwally | ||
1241 | || pwalldir == di_west && !(xtile==pwallx && ((uint32_t)yintercept>>16)==pwally)) | ||
1242 | { | ||
1243 | yintbuf=yintercept+((ystep*pwallposnorm)>>6); | ||
1244 | if((yintbuf>>16)!=(yintercept>>16)) | ||
1245 | goto passvert; | ||
1246 | |||
1247 | xintercept=(xtile<<TILESHIFT)+TILEGLOBAL-(pwallposinv<<10); | ||
1248 | yintercept=yintbuf; | ||
1249 | ytile = (short) (yintercept >> TILESHIFT); | ||
1250 | tilehit=pwalltile; | ||
1251 | HitVertWall(); | ||
1252 | } | ||
1253 | else | ||
1254 | { | ||
1255 | yintbuf=yintercept+((ystep*pwallposinv)>>6); | ||
1256 | if((yintbuf>>16)!=(yintercept>>16)) | ||
1257 | goto passvert; | ||
1258 | |||
1259 | xintercept=(xtile<<TILESHIFT)-(pwallposinv<<10); | ||
1260 | yintercept=yintbuf; | ||
1261 | ytile = (short) (yintercept >> TILESHIFT); | ||
1262 | tilehit=pwalltile; | ||
1263 | HitVertWall(); | ||
1264 | } | ||
1265 | } | ||
1266 | else | ||
1267 | { | ||
1268 | int pwallposi = pwallpos; | ||
1269 | if(pwalldir==di_north) pwallposi = 64-pwallpos; | ||
1270 | if(pwalldir==di_south && (word)yintercept<(pwallposi<<10) | ||
1271 | || pwalldir==di_north && (word)yintercept>(pwallposi<<10)) | ||
1272 | { | ||
1273 | if(((uint32_t)yintercept>>16)==pwally && xtile==pwallx) | ||
1274 | { | ||
1275 | if(pwalldir==di_south && (int32_t)((word)yintercept)+ystep<(pwallposi<<10) | ||
1276 | || pwalldir==di_north && (int32_t)((word)yintercept)+ystep>(pwallposi<<10)) | ||
1277 | goto passvert; | ||
1278 | |||
1279 | if(pwalldir==di_south) | ||
1280 | yintercept=(yintercept&0xffff0000)+(pwallposi<<10); | ||
1281 | else | ||
1282 | yintercept=(yintercept&0xffff0000)-TILEGLOBAL+(pwallposi<<10); | ||
1283 | xintercept=xintercept-((xstep*(64-pwallpos))>>6); | ||
1284 | xtile = (short) (xintercept >> TILESHIFT); | ||
1285 | tilehit=pwalltile; | ||
1286 | HitHorizWall(); | ||
1287 | } | ||
1288 | else | ||
1289 | { | ||
1290 | texdelta = -(pwallposi<<10); | ||
1291 | xintercept=xtile<<TILESHIFT; | ||
1292 | ytile = (short) (yintercept >> TILESHIFT); | ||
1293 | tilehit=pwalltile; | ||
1294 | HitVertWall(); | ||
1295 | } | ||
1296 | } | ||
1297 | else | ||
1298 | { | ||
1299 | if(((uint32_t)yintercept>>16)==pwally && xtile==pwallx) | ||
1300 | { | ||
1301 | texdelta = -(pwallposi<<10); | ||
1302 | xintercept=xtile<<TILESHIFT; | ||
1303 | ytile = (short) (yintercept >> TILESHIFT); | ||
1304 | tilehit=pwalltile; | ||
1305 | HitVertWall(); | ||
1306 | } | ||
1307 | else | ||
1308 | { | ||
1309 | if(pwalldir==di_south && (int32_t)((word)yintercept)+ystep>(pwallposi<<10) | ||
1310 | || pwalldir==di_north && (int32_t)((word)yintercept)+ystep<(pwallposi<<10)) | ||
1311 | goto passvert; | ||
1312 | |||
1313 | if(pwalldir==di_south) | ||
1314 | yintercept=(yintercept&0xffff0000)-((64-pwallpos)<<10); | ||
1315 | else | ||
1316 | yintercept=(yintercept&0xffff0000)+((64-pwallpos)<<10); | ||
1317 | xintercept=xintercept-((xstep*pwallpos)>>6); | ||
1318 | xtile = (short) (xintercept >> TILESHIFT); | ||
1319 | tilehit=pwalltile; | ||
1320 | HitHorizWall(); | ||
1321 | } | ||
1322 | } | ||
1323 | } | ||
1324 | } | ||
1325 | else | ||
1326 | { | ||
1327 | xintercept=xtile<<TILESHIFT; | ||
1328 | ytile = (short) (yintercept >> TILESHIFT); | ||
1329 | HitVertWall(); | ||
1330 | } | ||
1331 | } | ||
1332 | break; | ||
1333 | } | ||
1334 | passvert: | ||
1335 | *((byte *)spotvis+xspot)=1; | ||
1336 | xtile+=xtilestep; | ||
1337 | yintercept+=ystep; | ||
1338 | xspot=(word)((xtile<<mapshift)+((uint32_t)yintercept>>16)); | ||
1339 | } | ||
1340 | while(1); | ||
1341 | continue; | ||
1342 | |||
1343 | do | ||
1344 | { | ||
1345 | if(xtilestep==-1 && (xintercept>>16)<=xtile) goto vertentry; | ||
1346 | if(xtilestep==1 && (xintercept>>16)>=xtile) goto vertentry; | ||
1347 | horizentry: | ||
1348 | if((uint32_t)xintercept>mapwidth*65536-1 || (word)ytile>=mapheight) | ||
1349 | { | ||
1350 | if(ytile<0) yintercept=0, ytile=0; | ||
1351 | else if(ytile>=mapheight) yintercept=mapheight<<TILESHIFT, ytile=mapheight-1; | ||
1352 | else ytile=(short) (yintercept >> TILESHIFT); | ||
1353 | if(xintercept<0) xintercept=0, xtile=0; | ||
1354 | else if(xintercept>=(mapwidth<<TILESHIFT)) xintercept=mapwidth<<TILESHIFT, xtile=mapwidth-1; | ||
1355 | xspot=0xffff; | ||
1356 | tilehit=0; | ||
1357 | HitVertBorder(); | ||
1358 | break; | ||
1359 | } | ||
1360 | if(yspot>=maparea) break; | ||
1361 | tilehit=((byte *)tilemap)[yspot]; | ||
1362 | if(tilehit) | ||
1363 | { | ||
1364 | if(tilehit&0x80) | ||
1365 | { | ||
1366 | int32_t xintbuf=xintercept+(xstep>>1); | ||
1367 | if((xintbuf>>16)!=(xintercept>>16)) | ||
1368 | goto passhoriz; | ||
1369 | if((word)xintbuf<doorposition[tilehit&0x7f]) | ||
1370 | goto passhoriz; | ||
1371 | xintercept=xintbuf; | ||
1372 | yintercept=(ytile<<TILESHIFT)+0x8000; | ||
1373 | xtile = (short) (xintercept >> TILESHIFT); | ||
1374 | HitHorizDoor(); | ||
1375 | } | ||
1376 | else | ||
1377 | { | ||
1378 | if(tilehit==64) | ||
1379 | { | ||
1380 | if(pwalldir==di_north || pwalldir==di_south) | ||
1381 | { | ||
1382 | int32_t xintbuf; | ||
1383 | int pwallposnorm; | ||
1384 | int pwallposinv; | ||
1385 | if(pwalldir==di_north) | ||
1386 | { | ||
1387 | pwallposnorm = 64-pwallpos; | ||
1388 | pwallposinv = pwallpos; | ||
1389 | } | ||
1390 | else | ||
1391 | { | ||
1392 | pwallposnorm = pwallpos; | ||
1393 | pwallposinv = 64-pwallpos; | ||
1394 | } | ||
1395 | if(pwalldir == di_south && ytile==pwally && ((uint32_t)xintercept>>16)==pwallx | ||
1396 | || pwalldir == di_north && !(ytile==pwally && ((uint32_t)xintercept>>16)==pwallx)) | ||
1397 | { | ||
1398 | xintbuf=xintercept+((xstep*pwallposnorm)>>6); | ||
1399 | if((xintbuf>>16)!=(xintercept>>16)) | ||
1400 | goto passhoriz; | ||
1401 | |||
1402 | yintercept=(ytile<<TILESHIFT)+TILEGLOBAL-(pwallposinv<<10); | ||
1403 | xintercept=xintbuf; | ||
1404 | xtile = (short) (xintercept >> TILESHIFT); | ||
1405 | tilehit=pwalltile; | ||
1406 | HitHorizWall(); | ||
1407 | } | ||
1408 | else | ||
1409 | { | ||
1410 | xintbuf=xintercept+((xstep*pwallposinv)>>6); | ||
1411 | if((xintbuf>>16)!=(xintercept>>16)) | ||
1412 | goto passhoriz; | ||
1413 | |||
1414 | yintercept=(ytile<<TILESHIFT)-(pwallposinv<<10); | ||
1415 | xintercept=xintbuf; | ||
1416 | xtile = (short) (xintercept >> TILESHIFT); | ||
1417 | tilehit=pwalltile; | ||
1418 | HitHorizWall(); | ||
1419 | } | ||
1420 | } | ||
1421 | else | ||
1422 | { | ||
1423 | int pwallposi = pwallpos; | ||
1424 | if(pwalldir==di_west) pwallposi = 64-pwallpos; | ||
1425 | if(pwalldir==di_east && (word)xintercept<(pwallposi<<10) | ||
1426 | || pwalldir==di_west && (word)xintercept>(pwallposi<<10)) | ||
1427 | { | ||
1428 | if(((uint32_t)xintercept>>16)==pwallx && ytile==pwally) | ||
1429 | { | ||
1430 | if(pwalldir==di_east && (int32_t)((word)xintercept)+xstep<(pwallposi<<10) | ||
1431 | || pwalldir==di_west && (int32_t)((word)xintercept)+xstep>(pwallposi<<10)) | ||
1432 | goto passhoriz; | ||
1433 | |||
1434 | if(pwalldir==di_east) | ||
1435 | xintercept=(xintercept&0xffff0000)+(pwallposi<<10); | ||
1436 | else | ||
1437 | xintercept=(xintercept&0xffff0000)-TILEGLOBAL+(pwallposi<<10); | ||
1438 | yintercept=yintercept-((ystep*(64-pwallpos))>>6); | ||
1439 | ytile = (short) (yintercept >> TILESHIFT); | ||
1440 | tilehit=pwalltile; | ||
1441 | HitVertWall(); | ||
1442 | } | ||
1443 | else | ||
1444 | { | ||
1445 | texdelta = -(pwallposi<<10); | ||
1446 | yintercept=ytile<<TILESHIFT; | ||
1447 | xtile = (short) (xintercept >> TILESHIFT); | ||
1448 | tilehit=pwalltile; | ||
1449 | HitHorizWall(); | ||
1450 | } | ||
1451 | } | ||
1452 | else | ||
1453 | { | ||
1454 | if(((uint32_t)xintercept>>16)==pwallx && ytile==pwally) | ||
1455 | { | ||
1456 | texdelta = -(pwallposi<<10); | ||
1457 | yintercept=ytile<<TILESHIFT; | ||
1458 | xtile = (short) (xintercept >> TILESHIFT); | ||
1459 | tilehit=pwalltile; | ||
1460 | HitHorizWall(); | ||
1461 | } | ||
1462 | else | ||
1463 | { | ||
1464 | if(pwalldir==di_east && (int32_t)((word)xintercept)+xstep>(pwallposi<<10) | ||
1465 | || pwalldir==di_west && (int32_t)((word)xintercept)+xstep<(pwallposi<<10)) | ||
1466 | goto passhoriz; | ||
1467 | |||
1468 | if(pwalldir==di_east) | ||
1469 | xintercept=(xintercept&0xffff0000)-((64-pwallpos)<<10); | ||
1470 | else | ||
1471 | xintercept=(xintercept&0xffff0000)+((64-pwallpos)<<10); | ||
1472 | yintercept=yintercept-((ystep*pwallpos)>>6); | ||
1473 | ytile = (short) (yintercept >> TILESHIFT); | ||
1474 | tilehit=pwalltile; | ||
1475 | HitVertWall(); | ||
1476 | } | ||
1477 | } | ||
1478 | } | ||
1479 | } | ||
1480 | else | ||
1481 | { | ||
1482 | yintercept=ytile<<TILESHIFT; | ||
1483 | xtile = (short) (xintercept >> TILESHIFT); | ||
1484 | HitHorizWall(); | ||
1485 | } | ||
1486 | } | ||
1487 | break; | ||
1488 | } | ||
1489 | passhoriz: | ||
1490 | *((byte *)spotvis+yspot)=1; | ||
1491 | ytile+=ytilestep; | ||
1492 | xintercept+=xstep; | ||
1493 | yspot=(word)((((uint32_t)xintercept>>16)<<mapshift)+ytile); | ||
1494 | } | ||
1495 | while(1); | ||
1496 | } | ||
1497 | } | ||
1498 | |||
1499 | /* | ||
1500 | ==================== | ||
1501 | = | ||
1502 | = WallRefresh | ||
1503 | = | ||
1504 | ==================== | ||
1505 | */ | ||
1506 | |||
1507 | void WallRefresh (void) | ||
1508 | { | ||
1509 | xpartialdown = viewx&(TILEGLOBAL-1); | ||
1510 | xpartialup = TILEGLOBAL-xpartialdown; | ||
1511 | ypartialdown = viewy&(TILEGLOBAL-1); | ||
1512 | ypartialup = TILEGLOBAL-ypartialdown; | ||
1513 | |||
1514 | min_wallheight = viewheight; | ||
1515 | lastside = -1; // the first pixel is on a new wall | ||
1516 | AsmRefresh (); | ||
1517 | ScalePost (); // no more optimization on last post | ||
1518 | } | ||
1519 | |||
1520 | void CalcViewVariables() | ||
1521 | { | ||
1522 | viewangle = player->angle; | ||
1523 | midangle = viewangle*(FINEANGLES/ANGLES); | ||
1524 | viewsin = sintable[viewangle]; | ||
1525 | viewcos = costable[viewangle]; | ||
1526 | viewx = player->x - FixedMul(focallength,viewcos); | ||
1527 | viewy = player->y + FixedMul(focallength,viewsin); | ||
1528 | |||
1529 | focaltx = (short)(viewx>>TILESHIFT); | ||
1530 | focalty = (short)(viewy>>TILESHIFT); | ||
1531 | |||
1532 | viewtx = (short)(player->x >> TILESHIFT); | ||
1533 | viewty = (short)(player->y >> TILESHIFT); | ||
1534 | } | ||
1535 | |||
1536 | //========================================================================== | ||
1537 | |||
1538 | /* | ||
1539 | ======================== | ||
1540 | = | ||
1541 | = ThreeDRefresh | ||
1542 | = | ||
1543 | ======================== | ||
1544 | */ | ||
1545 | |||
1546 | void ThreeDRefresh (void) | ||
1547 | { | ||
1548 | // | ||
1549 | // clear out the traced array | ||
1550 | // | ||
1551 | memset(spotvis,0,maparea); | ||
1552 | spotvis[player->tilex][player->tiley] = 1; // Detect all sprites over player fix | ||
1553 | |||
1554 | vbuf = VL_LockSurface(screenBuffer); | ||
1555 | vbuf+=screenofs; | ||
1556 | vbufPitch = bufferPitch; | ||
1557 | |||
1558 | CalcViewVariables(); | ||
1559 | |||
1560 | // | ||
1561 | // follow the walls from there to the right, drawing as we go | ||
1562 | // | ||
1563 | VGAClearScreen (); | ||
1564 | #if defined(USE_FEATUREFLAGS) && defined(USE_STARSKY) | ||
1565 | if(GetFeatureFlags() & FF_STARSKY) | ||
1566 | DrawStarSky(vbuf, vbufPitch); | ||
1567 | #endif | ||
1568 | |||
1569 | WallRefresh (); | ||
1570 | |||
1571 | #if defined(USE_FEATUREFLAGS) && defined(USE_PARALLAX) | ||
1572 | if(GetFeatureFlags() & FF_PARALLAXSKY) | ||
1573 | DrawParallax(vbuf, vbufPitch); | ||
1574 | #endif | ||
1575 | #if defined(USE_FEATUREFLAGS) && defined(USE_CLOUDSKY) | ||
1576 | if(GetFeatureFlags() & FF_CLOUDSKY) | ||
1577 | DrawClouds(vbuf, vbufPitch, min_wallheight); | ||
1578 | #endif | ||
1579 | #ifdef USE_FLOORCEILINGTEX | ||
1580 | DrawFloorAndCeiling(vbuf, vbufPitch, min_wallheight); | ||
1581 | #endif | ||
1582 | |||
1583 | // | ||
1584 | // draw all the scaled images | ||
1585 | // | ||
1586 | DrawScaleds(); // draw scaled stuff | ||
1587 | |||
1588 | #if defined(USE_FEATUREFLAGS) && defined(USE_RAIN) | ||
1589 | if(GetFeatureFlags() & FF_RAIN) | ||
1590 | DrawRain(vbuf, vbufPitch); | ||
1591 | #endif | ||
1592 | #if defined(USE_FEATUREFLAGS) && defined(USE_SNOW) | ||
1593 | if(GetFeatureFlags() & FF_SNOW) | ||
1594 | DrawSnow(vbuf, vbufPitch); | ||
1595 | #endif | ||
1596 | |||
1597 | DrawPlayerWeapon (); // draw player's hands | ||
1598 | |||
1599 | if(Keyboard[sc_Tab] && viewsize == 21 && gamestate.weapon != -1) | ||
1600 | ShowActStatus(); | ||
1601 | |||
1602 | VL_UnlockSurface(screenBuffer); | ||
1603 | vbuf = NULL; | ||
1604 | |||
1605 | // | ||
1606 | // show screen and time last cycle | ||
1607 | // | ||
1608 | |||
1609 | if (fizzlein) | ||
1610 | { | ||
1611 | FizzleFade(screenBuffer, 0, 0, screenWidth, screenHeight, 20, false); | ||
1612 | fizzlein = false; | ||
1613 | |||
1614 | lasttimecount = GetTimeCount(); // don't make a big tic count | ||
1615 | } | ||
1616 | else | ||
1617 | { | ||
1618 | #ifndef REMDEBUG | ||
1619 | if (fpscounter) | ||
1620 | { | ||
1621 | fontnumber = 0; | ||
1622 | SETFONTCOLOR(7,127); | ||
1623 | PrintX=4; PrintY=1; | ||
1624 | VWB_Bar(0,0,50,10,bordercol); | ||
1625 | US_PrintSigned(fps); | ||
1626 | US_Print(" fps"); | ||
1627 | } | ||
1628 | #endif | ||
1629 | SDL_BlitSurface(screenBuffer, NULL, screen, NULL); | ||
1630 | SDL_Flip(screen); | ||
1631 | } | ||
1632 | |||
1633 | #ifndef REMDEBUG | ||
1634 | if (fpscounter) | ||
1635 | { | ||
1636 | fps_frames++; | ||
1637 | fps_time+=tics; | ||
1638 | |||
1639 | if(fps_time>35) | ||
1640 | { | ||
1641 | fps_time-=35; | ||
1642 | fps=fps_frames<<1; | ||
1643 | fps_frames=0; | ||
1644 | } | ||
1645 | } | ||
1646 | #endif | ||
1647 | } | ||