1 //-------------------------------------------------------------------------
2 /*
3 Copyright (C) 2016 EDuke32 developers and contributors
4 
5 This file is part of EDuke32.
6 
7 EDuke32 is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License version 2
9 as published by the Free Software Foundation.
10 
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 
15 See the GNU General Public License for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
20 */
21 //-------------------------------------------------------------------------
22 
23 #include "duke3d.h"
24 #include "compat.h"
25 #include "screens.h"
26 #include "colmatch.h"
27 #include "input.h"
28 #include "anim.h"
29 #include "sbar.h"
30 #include "menus.h"
31 #include "osdfuncs.h"
32 #include "demo.h"
33 #include "mdsprite.h"
34 
35 #ifdef __ANDROID__
36 #include "android.h"
37 #endif
38 
39 #define COLOR_RED redcol
40 #define COLOR_WHITE whitecol
41 
42 #define quotepulseshade (sintable[((uint32_t)totalclock<<5)&2047]>>11)
43 
44 palette_t CrosshairColors = { 255, 255, 255, 0 };
45 palette_t DefaultCrosshairColors = { 0, 0, 0, 0 };
46 int32_t g_crosshairSum = -1;
47 // yxaspect and viewingrange just before the 'main' drawrooms call
48 int32_t dr_yxaspect, dr_viewingrange;
49 double g_moveActorsTime, g_moveWorldTime;  // in ms, smoothed
50 int32_t g_noLogoAnim = 0;
51 int32_t g_noLogo = 0;
52 
53 ////////// OFTEN-USED FEW-LINERS //////////
G_HandleEventsWhileNoInput(void)54 static void G_HandleEventsWhileNoInput(void)
55 {
56     I_ClearAllInput();
57 
58     while (!I_CheckAllInput())
59         G_HandleAsync();
60 
61     I_ClearAllInput();
62 }
63 
G_PlaySoundWhileNoInput(int32_t soundnum)64 static int32_t G_PlaySoundWhileNoInput(int32_t soundnum)
65 {
66     S_PlaySound(soundnum);
67     I_ClearAllInput();
68     while (S_CheckSoundPlaying(-1, soundnum))
69     {
70         G_HandleAsync();
71         if (I_CheckAllInput())
72         {
73             I_ClearAllInput();
74             return 1;
75         }
76     }
77 
78     return 0;
79 }
80 //////////
81 
P_SetGamePalette(DukePlayer_t * player,uint32_t palid,int32_t set)82 void P_SetGamePalette(DukePlayer_t *player, uint32_t palid, int32_t set)
83 {
84     if (palid >= MAXBASEPALS)
85         palid = 0;
86 
87     player->palette = palid;
88 
89     if (player != g_player[screenpeek].ps)
90         return;
91 
92     videoSetPalette(ud.brightness>>2, palid, set);
93 }
94 
G_GetCrosshairColor(void)95 void G_GetCrosshairColor(void)
96 {
97     if (DefaultCrosshairColors.f)
98         return;
99 
100     tileLoad(CROSSHAIR);
101 
102     if (!waloff[CROSSHAIR])
103         return;
104 
105     char const *ptr = (char const *) waloff[CROSSHAIR];
106 
107     // find the brightest color in the original 8-bit tile
108     int32_t ii = tilesiz[CROSSHAIR].x * tilesiz[CROSSHAIR].y;
109     int32_t bri = 0, j = 0, i;
110 
111     Bassert(ii > 0);
112 
113     do
114     {
115         if (*ptr != 255)
116         {
117             i = curpalette[(int32_t) *ptr].r+curpalette[(int32_t) *ptr].g+curpalette[(int32_t) *ptr].b;
118             if (i > j) { j = i; bri = *ptr; }
119         }
120         ptr++;
121     } while (--ii);
122 
123     Bmemcpy(&CrosshairColors, &curpalette[bri], sizeof(palette_t));
124     Bmemcpy(&DefaultCrosshairColors, &curpalette[bri], sizeof(palette_t));
125     DefaultCrosshairColors.f = 1; // this flag signifies that the color has been detected
126 }
127 
G_SetCrosshairColor(int32_t r,int32_t g,int32_t b)128 void G_SetCrosshairColor(int32_t r, int32_t g, int32_t b)
129 {
130     if (g_crosshairSum == r+(g<<8)+(b<<16))
131         return;
132 
133     tileLoad(CROSSHAIR);
134 
135     if (!waloff[CROSSHAIR])
136         return;
137 
138     if (!DefaultCrosshairColors.f)
139         G_GetCrosshairColor();
140 
141     g_crosshairSum = r+(g<<8)+(b<<16);
142     CrosshairColors.r = r;
143     CrosshairColors.g = g;
144     CrosshairColors.b = b;
145 
146     char *ptr = (char *) waloff[CROSSHAIR];
147 
148     int32_t ii = tilesiz[CROSSHAIR].x * tilesiz[CROSSHAIR].y;
149 
150     Bassert(ii > 0);
151 
152     int32_t i = (videoGetRenderMode() == REND_CLASSIC)
153                 ? paletteGetClosestColor(CrosshairColors.r, CrosshairColors.g, CrosshairColors.b)
154                 : paletteGetClosestColor(255, 255, 255);  // use white in GL so we can tint it to the right color
155 
156     do
157     {
158         if (*ptr != 255)
159             *ptr = i;
160         ptr++;
161     } while (--ii);
162 
163     paletteMakeLookupTable(CROSSHAIR_PAL, NULL, CrosshairColors.r, CrosshairColors.g, CrosshairColors.b, 1);
164 
165 #ifdef USE_OPENGL
166     // XXX: this makes us also load all hightile textures tinted with the crosshair color!
167     polytint_t & crosshairtint = hictinting[CROSSHAIR_PAL];
168     crosshairtint.r = CrosshairColors.r;
169     crosshairtint.g = CrosshairColors.g;
170     crosshairtint.b = CrosshairColors.b;
171     crosshairtint.f = HICTINT_USEONART | HICTINT_GRAYSCALE;
172 #endif
173     tileInvalidate(CROSSHAIR, -1, -1);
174 }
175 
176 #define SCORESHEETOFFSET -20
G_ShowScores(void)177 static void G_ShowScores(void)
178 {
179     int32_t t, i;
180 
181     if (g_mostConcurrentPlayers > 1 && (g_gametypeFlags[ud.coop]&GAMETYPE_SCORESHEET))
182     {
183         gametext_center(SCORESHEETOFFSET+58+2, "Multiplayer Totals");
184         gametext_center(SCORESHEETOFFSET+58+10, g_mapInfo[G_LastMapInfoIndex()].name);
185 
186         t = 0;
187         minitext(70, SCORESHEETOFFSET+80, "Name", 8, 2+8+16+ROTATESPRITE_MAX);
188         minitext(170, SCORESHEETOFFSET+80, "Frags", 8, 2+8+16+ROTATESPRITE_MAX);
189         minitext(200, SCORESHEETOFFSET+80, "Deaths", 8, 2+8+16+ROTATESPRITE_MAX);
190         minitext(235, SCORESHEETOFFSET+80, "Ping", 8, 2+8+16+ROTATESPRITE_MAX);
191 
192         for (i=g_mostConcurrentPlayers-1; i>=0; i--)
193         {
194             if (!g_player[i].playerquitflag)
195                 continue;
196 
197             minitext(70, SCORESHEETOFFSET+90+t, g_player[i].user_name, g_player[i].ps->palookup, 2+8+16+ROTATESPRITE_MAX);
198 
199             Bsprintf(tempbuf, "%-4d", g_player[i].ps->frag);
200             minitext(170, SCORESHEETOFFSET+90+t, tempbuf, 2, 2+8+16+ROTATESPRITE_MAX);
201 
202             Bsprintf(tempbuf, "%-4d", g_player[i].frags[i] + g_player[i].ps->fraggedself);
203             minitext(200, SCORESHEETOFFSET+90+t, tempbuf, 2, 2+8+16+ROTATESPRITE_MAX);
204 
205             //Bsprintf(tempbuf, "%-4d", g_player[i].ping);
206             //minitext(235, SCORESHEETOFFSET+90+t, tempbuf, 2, 2+8+16+ROTATESPRITE_MAX);
207 
208             t += 7;
209         }
210     }
211 }
212 #undef SCORESHEETOFFSET
213 
214 ////////// TINT ACCUMULATOR //////////
215 
216 typedef struct {
217     int32_t r, g, b;
218     // f: 0-63 scale
219     int32_t maxf, sumf;
220 } palaccum_t;
221 
222 #define PALACCUM_INITIALIZER { 0, 0, 0, 0, 0 }
223 
224 /* For a picture frame F and n tints C_1, C_2, ... C_n weighted a_1, a_2,
225 * ... a_n (on a 0-1 scale), the faded frame is calculated as
226 *
227 *    F_new := (1-max_i(a_i))*F + d*sum_i(a_i), where
228 *
229 *    d := max_i(a_i)/sum_i(a_i).
230 *
231 * This means that
232 *  1) tint application is independent of their order.
233 *  2) going from n+1 to n tints is continuous when the leaving one has faded.
234 *
235 * But note that for more than one tint, the composite tint will in general
236 * change its hue as the ratio of the weights of the individual ones changes.
237 */
palaccum_add(palaccum_t * pa,const palette_t * pal,int32_t f)238 static void palaccum_add(palaccum_t *pa, const palette_t *pal, int32_t f)
239 {
240     f = clamp(f, 0, 63);
241     if (f == 0)
242         return;
243 
244     pa->maxf = max(pa->maxf, f);
245     pa->sumf += f;
246 
247     pa->r += f*clamp(pal->r, 0, 63);
248     pa->g += f*clamp(pal->g, 0, 63);
249     pa->b += f*clamp(pal->b, 0, 63);
250 }
251 
G_FadePalaccum(const palaccum_t * pa)252 static void G_FadePalaccum(const palaccum_t *pa)
253 {
254     videoFadePalette(tabledivide32_noinline(pa->r, pa->sumf)<<2,
255         tabledivide32_noinline(pa->g, pa->sumf)<<2,
256         tabledivide32_noinline(pa->b, pa->sumf)<<2, pa->maxf<<2);
257 }
258 
259 
gtextsc(int32_t sc)260 static int32_t gtextsc(int32_t sc)
261 {
262     return scale(sc, ud.textscale, 400);
263 }
264 
265 ////////// DISPLAYREST //////////
266 
G_DrawCameraText(int16_t i)267 static void G_DrawCameraText(int16_t i)
268 {
269     if (!T1(i))
270     {
271         rotatesprite_win(24<<16, 33<<16, 65536L, 0, CAMCORNER, 0, 0, 2);
272         rotatesprite_win((320-26)<<16, 34<<16, 65536L, 0, CAMCORNER+1, 0, 0, 2);
273         rotatesprite_win(22<<16, 163<<16, 65536L, 512, CAMCORNER+1, 0, 0, 2+4);
274         rotatesprite_win((310-10)<<16, 163<<16, 65536L, 512, CAMCORNER+1, 0, 0, 2);
275 
276         if ((int32_t) totalclock&16)
277             rotatesprite_win(46<<16, 32<<16, 65536L, 0, CAMLIGHT, 0, 0, 2);
278     }
279     else
280     {
281         int32_t flipbits = ((int32_t) totalclock<<1)&48;
282 
283         for (bssize_t x=-64; x<394; x+=64)
284             for (bssize_t y=0; y<200; y+=64)
285                 rotatesprite_win(x<<16, y<<16, 65536L, 0, STATIC, 0, 0, 2+flipbits);
286     }
287 }
288 
G_MoveClouds(void)289 static inline void G_MoveClouds(void)
290 {
291     int32_t i;
292 
293     if (totalclock <= g_cloudClock && totalclock >= (g_cloudClock-7))
294         return;
295 
296     g_cloudClock = totalclock+6;
297 
298     g_cloudX += sintable[(fix16_to_int(g_player[screenpeek].ps->q16ang)+512)&2047]>>9;
299     g_cloudY += sintable[fix16_to_int(g_player[screenpeek].ps->q16ang)&2047]>>9;
300 
301     for (i=g_cloudCnt-1; i>=0; i--)
302     {
303         sector[g_cloudSect[i]].ceilingxpanning = g_cloudX>>6;
304         sector[g_cloudSect[i]].ceilingypanning = g_cloudY>>6;
305     }
306 }
307 
G_DrawOverheadMap(int32_t cposx,int32_t cposy,int32_t czoom,int16_t cang)308 static void G_DrawOverheadMap(int32_t cposx, int32_t cposy, int32_t czoom, int16_t cang)
309 {
310     int32_t i, j, k, l, x1, y1, x2=0, y2=0, x3, y3, x4, y4, ox, oy, xoff, yoff;
311     int32_t dax, day, cosang, sinang, xspan, yspan, sprx, spry;
312     int32_t xrepeat, yrepeat, z1, z2, startwall, endwall, tilenum, daang;
313     int32_t xvect, yvect, xvect2, yvect2;
314     int16_t p;
315     char col;
316     uwalltype *wal, *wal2;
317     spritetype *spr;
318 
319     int32_t tmpydim = (xdim*5)/8;
320 
321     renderSetAspect(65536, divscale16(tmpydim*320, xdim*200));
322 
323     xvect = sintable[(-cang)&2047] * czoom;
324     yvect = sintable[(1536-cang)&2047] * czoom;
325     xvect2 = mulscale16(xvect, yxaspect);
326     yvect2 = mulscale16(yvect, yxaspect);
327 
328     renderDisableFog();
329 
330     //Draw red lines
331     for (i=numsectors-1; i>=0; i--)
332     {
333         if (!(show2dsector[i>>3]&(1<<(i&7)))) continue;
334 
335         startwall = sector[i].wallptr;
336         endwall = sector[i].wallptr + sector[i].wallnum;
337 
338         z1 = sector[i].ceilingz;
339         z2 = sector[i].floorz;
340 
341         for (j=startwall, wal=(uwalltype *)&wall[startwall]; j<endwall; j++, wal++)
342         {
343             k = wal->nextwall;
344             if (k < 0) continue;
345 
346             if (sector[wal->nextsector].ceilingz == z1)
347                 if (sector[wal->nextsector].floorz == z2)
348                     if (((wal->cstat|wall[wal->nextwall].cstat)&(16+32)) == 0) continue;
349 
350             col = editorcolors[1]; //red
351             if ((wal->cstat|wall[wal->nextwall].cstat)&1) col = editorcolors[5]; //magenta
352 
353             if (!(show2dsector[wal->nextsector>>3]&(1<<(wal->nextsector&7))))
354                 col = editorcolors[7];
355             else continue;
356 
357             ox = wal->x-cposx;
358             oy = wal->y-cposy;
359             x1 = dmulscale16(ox, xvect, -oy, yvect)+(xdim<<11);
360             y1 = dmulscale16(oy, xvect2, ox, yvect2)+(ydim<<11);
361 
362             wal2 = (uwalltype *)&wall[wal->point2];
363             ox = wal2->x-cposx;
364             oy = wal2->y-cposy;
365             x2 = dmulscale16(ox, xvect, -oy, yvect)+(xdim<<11);
366             y2 = dmulscale16(oy, xvect2, ox, yvect2)+(ydim<<11);
367 
368             renderDrawLine(x1, y1, x2, y2, col);
369         }
370     }
371 
372     renderEnableFog();
373 
374     //Draw sprites
375     k = g_player[screenpeek].ps->i;
376     for (i=numsectors-1; i>=0; i--)
377     {
378         if (!(show2dsector[i>>3]&(1<<(i&7)))) continue;
379         for (j=headspritesect[i]; j>=0; j=nextspritesect[j])
380         {
381             spr = &sprite[j];
382 
383             if (j == k || (spr->cstat&0x8000) || spr->cstat == 257 || spr->xrepeat == 0) continue;
384 
385             col = editorcolors[6]; //cyan
386             if (spr->cstat&1) col = editorcolors[5]; //magenta
387 
388             sprx = spr->x;
389             spry = spr->y;
390 
391             if ((spr->cstat&257) != 0) switch (spr->cstat&48)
392             {
393             case 0:
394                 //                    break;
395 
396                 ox = sprx-cposx;
397                 oy = spry-cposy;
398                 x1 = dmulscale16(ox, xvect, -oy, yvect);
399                 y1 = dmulscale16(oy, xvect2, ox, yvect2);
400 
401                 ox = (sintable[(spr->ang+512)&2047]>>7);
402                 oy = (sintable[(spr->ang)&2047]>>7);
403                 x2 = dmulscale16(ox, xvect, -oy, yvect);
404                 y2 = dmulscale16(oy, xvect, ox, yvect);
405 
406                 x3 = mulscale16(x2, yxaspect);
407                 y3 = mulscale16(y2, yxaspect);
408 
409                 renderDrawLine(x1-x2+(xdim<<11), y1-y3+(ydim<<11),
410                     x1+x2+(xdim<<11), y1+y3+(ydim<<11), col);
411                 renderDrawLine(x1-y2+(xdim<<11), y1+x3+(ydim<<11),
412                     x1+x2+(xdim<<11), y1+y3+(ydim<<11), col);
413                 renderDrawLine(x1+y2+(xdim<<11), y1-x3+(ydim<<11),
414                     x1+x2+(xdim<<11), y1+y3+(ydim<<11), col);
415                 break;
416 
417             case 16:
418                 if (spr->picnum == LASERLINE)
419                 {
420                     x1 = sprx;
421                     y1 = spry;
422                     tilenum = spr->picnum;
423                     xoff = picanm[tilenum].xofs + spr->xoffset;
424                     if ((spr->cstat&4) > 0) xoff = -xoff;
425                     k = spr->ang;
426                     l = spr->xrepeat;
427                     dax = sintable[k&2047]*l;
428                     day = sintable[(k+1536)&2047]*l;
429                     l = tilesiz[tilenum].x;
430                     k = (l>>1)+xoff;
431                     x1 -= mulscale16(dax, k);
432                     x2 = x1+mulscale16(dax, l);
433                     y1 -= mulscale16(day, k);
434                     y2 = y1+mulscale16(day, l);
435 
436                     ox = x1-cposx;
437                     oy = y1-cposy;
438                     x1 = dmulscale16(ox, xvect, -oy, yvect);
439                     y1 = dmulscale16(oy, xvect2, ox, yvect2);
440 
441                     ox = x2-cposx;
442                     oy = y2-cposy;
443                     x2 = dmulscale16(ox, xvect, -oy, yvect);
444                     y2 = dmulscale16(oy, xvect2, ox, yvect2);
445 
446                     renderDrawLine(x1+(xdim<<11), y1+(ydim<<11),
447                         x2+(xdim<<11), y2+(ydim<<11), col);
448                 }
449 
450                 break;
451 
452             case 32:
453                 tilenum = spr->picnum;
454                 xoff = picanm[tilenum].xofs + spr->xoffset;
455                 yoff = picanm[tilenum].yofs + spr->yoffset;
456                 if ((spr->cstat&4) > 0) xoff = -xoff;
457                 if ((spr->cstat&8) > 0) yoff = -yoff;
458 
459                 k = spr->ang;
460                 cosang = sintable[(k+512)&2047];
461                 sinang = sintable[k&2047];
462                 xspan = tilesiz[tilenum].x;
463                 xrepeat = spr->xrepeat;
464                 yspan = tilesiz[tilenum].y;
465                 yrepeat = spr->yrepeat;
466 
467                 dax = ((xspan>>1)+xoff)*xrepeat;
468                 day = ((yspan>>1)+yoff)*yrepeat;
469                 x1 = sprx + dmulscale16(sinang, dax, cosang, day);
470                 y1 = spry + dmulscale16(sinang, day, -cosang, dax);
471                 l = xspan*xrepeat;
472                 x2 = x1 - mulscale16(sinang, l);
473                 y2 = y1 + mulscale16(cosang, l);
474                 l = yspan*yrepeat;
475                 k = -mulscale16(cosang, l);
476                 x3 = x2+k;
477                 x4 = x1+k;
478                 k = -mulscale16(sinang, l);
479                 y3 = y2+k;
480                 y4 = y1+k;
481 
482                 ox = x1-cposx;
483                 oy = y1-cposy;
484                 x1 = dmulscale16(ox, xvect, -oy, yvect);
485                 y1 = dmulscale16(oy, xvect2, ox, yvect2);
486 
487                 ox = x2-cposx;
488                 oy = y2-cposy;
489                 x2 = dmulscale16(ox, xvect, -oy, yvect);
490                 y2 = dmulscale16(oy, xvect2, ox, yvect2);
491 
492                 ox = x3-cposx;
493                 oy = y3-cposy;
494                 x3 = dmulscale16(ox, xvect, -oy, yvect);
495                 y3 = dmulscale16(oy, xvect2, ox, yvect2);
496 
497                 ox = x4-cposx;
498                 oy = y4-cposy;
499                 x4 = dmulscale16(ox, xvect, -oy, yvect);
500                 y4 = dmulscale16(oy, xvect2, ox, yvect2);
501 
502                 renderDrawLine(x1+(xdim<<11), y1+(ydim<<11),
503                     x2+(xdim<<11), y2+(ydim<<11), col);
504 
505                 renderDrawLine(x2+(xdim<<11), y2+(ydim<<11),
506                     x3+(xdim<<11), y3+(ydim<<11), col);
507 
508                 renderDrawLine(x3+(xdim<<11), y3+(ydim<<11),
509                     x4+(xdim<<11), y4+(ydim<<11), col);
510 
511                 renderDrawLine(x4+(xdim<<11), y4+(ydim<<11),
512                     x1+(xdim<<11), y1+(ydim<<11), col);
513 
514                 break;
515             }
516         }
517     }
518 
519     renderDisableFog();
520 
521     //Draw white lines
522     for (i=numsectors-1; i>=0; i--)
523     {
524         if (!(show2dsector[i>>3]&(1<<(i&7)))) continue;
525 
526         startwall = sector[i].wallptr;
527         endwall = sector[i].wallptr + sector[i].wallnum;
528 
529         k = -1;
530         for (j=startwall, wal=(uwalltype *)&wall[startwall]; j<endwall; j++, wal++)
531         {
532             if (wal->nextwall >= 0) continue;
533 
534             if (tilesiz[wal->picnum].x == 0) continue;
535             if (tilesiz[wal->picnum].y == 0) continue;
536 
537             if (j == k)
538             {
539                 x1 = x2;
540                 y1 = y2;
541             }
542             else
543             {
544                 ox = wal->x-cposx;
545                 oy = wal->y-cposy;
546                 x1 = dmulscale16(ox, xvect, -oy, yvect)+(xdim<<11);
547                 y1 = dmulscale16(oy, xvect2, ox, yvect2)+(ydim<<11);
548             }
549 
550             k = wal->point2;
551             wal2 = (uwalltype *)&wall[k];
552             ox = wal2->x-cposx;
553             oy = wal2->y-cposy;
554             x2 = dmulscale16(ox, xvect, -oy, yvect)+(xdim<<11);
555             y2 = dmulscale16(oy, xvect2, ox, yvect2)+(ydim<<11);
556 
557             renderDrawLine(x1, y1, x2, y2, editorcolors[7]);
558         }
559     }
560 
561     renderEnableFog();
562 
563     videoSetCorrectedAspect();
564 
565     for (TRAVERSE_CONNECT(p))
566     {
567         if (ud.scrollmode && p == screenpeek) continue;
568 
569         DukePlayer_t const * const pPlayer = g_player[p].ps;
570         uspritetype const * const pSprite = (uspritetype const *)&sprite[pPlayer->i];
571 
572         ox = pSprite->x - cposx;
573         oy = pSprite->y - cposy;
574         daang = (pSprite->ang - cang) & 2047;
575         if (p == screenpeek)
576         {
577             ox = 0;
578             oy = 0;
579             daang = 0;
580         }
581         x1 = mulscale16(ox, xvect) - mulscale16(oy, yvect);
582         y1 = mulscale16(oy, xvect2) + mulscale16(ox, yvect2);
583 
584         if (p == screenpeek || GTFLAGS(GAMETYPE_OTHERPLAYERSINMAP))
585         {
586             if (REALITY)
587             {
588                 if (pSprite->xvel > 16 && pPlayer->on_ground)
589                     i = 1440-((((4-((int32_t) totalclock>>4)))&3)*5);
590                 else
591                     i = APLAYER;
592             }
593             else
594             {
595                 if (pSprite->xvel > 16 && pPlayer->on_ground)
596                     i = APLAYERTOP+(((int32_t) totalclock>>4)&3);
597                 else
598                     i = APLAYERTOP;
599             }
600 
601             if (i < 0)
602                 continue;
603 
604             j = klabs(pPlayer->truefz - pPlayer->pos.z) >> 8;
605             j = mulscale16(czoom * (pSprite->yrepeat + j), yxaspect);
606 
607             if (j < 22000) j = 22000;
608             else if (j > (65536<<1)) j = (65536<<1);
609 
610             if (REALITY)
611                 j >>= 1;
612 
613             rotatesprite_win((x1<<4)+(xdim<<15), (y1<<4)+(ydim<<15), j, daang, i, pSprite->shade,
614                 P_GetOverheadPal(pPlayer), 0);
615         }
616     }
617 }
618 
619 #define printcoordsline(fmt, ...) do { \
620     Bsprintf(tempbuf, fmt, ## __VA_ARGS__); \
621     printext256(20, y+=9, COLOR_WHITE, -1, tempbuf, 0); \
622 } while (0)
623 
624 #ifdef DEBUGGINGAIDS
625 sprstat_t g_spriteStat;
626 #endif
627 
G_PrintCoords(int32_t snum)628 static void G_PrintCoords(int32_t snum)
629 {
630     const int32_t x = 250;
631     int32_t y = 16;
632 
633     const DukePlayer_t *ps = g_player[snum].ps;
634     const int32_t sectnum = ps->cursectnum;
635 
636     if ((g_gametypeFlags[ud.coop] & GAMETYPE_FRAGBAR))
637     {
638         if (ud.multimode > 4)
639             y = 32;
640         else if (g_netServer || ud.multimode > 1)
641             y = 24;
642     }
643     Bsprintf(tempbuf, "XYZ= (%d, %d, %d)", ps->pos.x, ps->pos.y, ps->pos.z);
644     printext256(x, y, COLOR_WHITE, -1, tempbuf, 0);
645     char ang[16], horiz[16], horizoff[16];
646     fix16_to_str(ps->q16ang, ang, 2);
647     fix16_to_str(ps->q16horiz, horiz, 2);
648     fix16_to_str(ps->q16horizoff, horizoff, 2);
649     Bsprintf(tempbuf, "A/H/HO= %s, %s, %s", ang, horiz, horizoff);
650     printext256(x, y+9, COLOR_WHITE, -1, tempbuf, 0);
651     Bsprintf(tempbuf, "VEL= (%d, %d, %d) + (%d, %d, 0)",
652         ps->vel.x>>14, ps->vel.y>>14, ps->vel.z, ps->fric.x>>5, ps->fric.y>>5);
653     printext256(x, y+18, COLOR_WHITE, -1, tempbuf, 0);
654     Bsprintf(tempbuf, "OG= %d  SBRIDGE=%d SBS=%d", ps->on_ground, ps->spritebridge, ps->sbs);
655     printext256(x, y+27, COLOR_WHITE, -1, tempbuf, 0);
656     if (sectnum >= 0)
657         Bsprintf(tempbuf, "SECT= %d (LO=%d EX=%d)", sectnum,
658             TrackerCast(sector[sectnum].lotag), TrackerCast(sector[sectnum].extra));
659     else
660         Bsprintf(tempbuf, "SECT= %d", sectnum);
661     printext256(x, y+36, COLOR_WHITE, -1, tempbuf, 0);
662     //    Bsprintf(tempbuf,"SEED= %d",randomseed);
663     //    printext256(x,y+45,COLOR_WHITE,-1,tempbuf,0);
664     y -= 9;
665 
666     y += 7;
667     Bsprintf(tempbuf, "THOLD= %d", ps->transporter_hold);
668     printext256(x, y+54, COLOR_WHITE, -1, tempbuf, 0);
669     Bsprintf(tempbuf, "GAMETIC= %u, TOTALCLOCK=%d", g_moveThingsCount, totalclock);
670     printext256(x, y+63, COLOR_WHITE, -1, tempbuf, 0);
671 #ifdef DEBUGGINGAIDS
672     Bsprintf(tempbuf, "NUMSPRITES= %d", Numsprites);
673     printext256(x, y+72, COLOR_WHITE, -1, tempbuf, 0);
674     if (g_moveThingsCount > g_spriteStat.lastgtic + REALGAMETICSPERSEC)
675     {
676         g_spriteStat.lastgtic = g_moveThingsCount;
677         g_spriteStat.lastnumins = g_spriteStat.numins;
678         g_spriteStat.numins = 0;
679     }
680     Bsprintf(tempbuf, "INSERTIONS/s= %u", g_spriteStat.lastnumins);
681     printext256(x, y+81, COLOR_WHITE, -1, tempbuf, 0);
682     Bsprintf(tempbuf, "ONSCREEN= %d", g_spriteStat.numonscreen);
683     printext256(x, y+90, COLOR_WHITE, -1, tempbuf, 0);
684     y += 3*9;
685 #endif
686     y += 7;
687     Bsprintf(tempbuf, "VR=%.03f  YX=%.03f", (double) dr_viewingrange/65536.0, (double) dr_yxaspect/65536.0);
688     printext256(x, y+72, COLOR_WHITE, -1, tempbuf, 0);
689     Bsprintf(tempbuf, "MOVEACTORS [ms]= %.3e", g_moveActorsTime);
690     printext256(x, y+81, COLOR_WHITE, -1, tempbuf, 0);
691     Bsprintf(tempbuf, "MOVEWORLD [ms]= %.3e", g_moveWorldTime);
692     printext256(x, y+90, COLOR_WHITE, -1, tempbuf, 0);
693 
694 #ifdef USE_OPENGL
695     if (ud.coords == 2)
696     {
697         y=16;
698 
699         printcoordsline("rendmode = %d", videoGetRenderMode());
700         printcoordsline("r_ambientlight = %.03f", r_ambientlight);
701 
702         if (rendmode >= 3)
703         {
704             if (rendmode==3)
705                 printcoordsline("r_usenewshading = %d", r_usenewshading);
706 # ifdef POLYMER
707             else
708                 printcoordsline("r_pr_artmapping = %d", pr_artmapping);
709 #endif
710         }
711     }
712 #endif
713 }
714 
G_ShowCacheLocks(void)715 static void G_ShowCacheLocks(void)
716 {
717     if (offscreenrendering)
718         return;
719 
720     int k = 0;
721 
722 #if !defined DEBUG_ALLOCACHE_AS_MALLOC
723     auto indexes = g_cache.getIndex();
724 
725     for (int i=g_cache.numBlocks()-1; i>=0; i--)
726     {
727         if ((*indexes[i].lock) != CACHE1D_LOCKED && (*indexes[i].lock) != 1)
728         {
729             if (k >= ydim-12)
730                 break;
731 
732             Bsprintf(tempbuf, "Locked- %d: Leng:%d, Lock:%d", i, indexes[i].leng, *indexes[i].lock);
733             printext256(0L, k, COLOR_WHITE, -1, tempbuf, 1);
734             k += 6;
735         }
736     }
737 #endif
738 
739     if (k < ydim-12)
740         k += 6;
741 
742     for (int i=10; i>=0; i--)
743     {
744         if (rts_lumplockbyte[i] >= CACHE1D_LOCKED)
745         {
746             if (k >= ydim-12)
747                 break;
748 
749             Bsprintf(tempbuf, "RTS Locked %d:", i);
750             printext256(0, k, COLOR_WHITE, -1, tempbuf, 1);
751             k += 6;
752         }
753     }
754 
755     if (k >= ydim-12 && k<ydim-6)
756         printext256(0, k, COLOR_WHITE, -1, "(MORE . . .)", 1);
757 
758     // sounds
759     if (xdim < 640)
760         return;
761 
762     k = 0;
763 
764     for (int i=0; i<=g_highestSoundIdx; i++)
765     {
766         if (g_sounds[i].num > 0)
767         {
768             for (int j = 0, n = g_sounds[i].num; j < n; j++)
769             {
770                 if (k >= ydim-12)
771                     return;
772 
773                 Bsprintf(tempbuf, "snd %d_%d: voice %d, ow %d", i, j, g_sounds[i].voices[j].id, g_sounds[i].voices[j].owner);
774                 printext256(160, k, COLOR_WHITE, -1, tempbuf, 1);
775 
776                 k += 6;
777             }
778         }
779     }
780 }
781 
782 #define LOW_FPS 30
783 #define SLOW_FRAME_TIME 33
784 
785 #if defined GEKKO
786 # define FPS_YOFFSET 16
787 #else
788 # define FPS_YOFFSET 0
789 #endif
790 
791 #define FPS_COLOR(x) ((x) ? COLOR_RED : COLOR_WHITE)
792 
G_PrintFPS(void)793 static void G_PrintFPS(void)
794 {
795     static int32_t frameCount;
796     static double cumulativeFrameDelay;
797     static double lastFrameTime;
798     static float lastFPS, minFPS = FLT_MAX, maxFPS;
799     static double minGameUpdate = DBL_MAX, maxGameUpdate;
800 
801     double frameTime = timerGetHiTicks();
802     double frameDelay = frameTime - lastFrameTime;
803     cumulativeFrameDelay += frameDelay;
804 
805     if (frameDelay >= 0)
806     {
807         int32_t x = (xdim <= 640);
808 
809         if (ud.showfps)
810         {
811             int32_t chars = Bsprintf(tempbuf, "%.1f ms, %5.1f fps", frameDelay, lastFPS);
812 
813             printext256(windowxy2.x-(chars<<(3-x))+1, windowxy1.y+2+FPS_YOFFSET, 0, -1, tempbuf, x);
814             printext256(windowxy2.x-(chars<<(3-x)), windowxy1.y+1+FPS_YOFFSET,
815                 FPS_COLOR(lastFPS < LOW_FPS), -1, tempbuf, x);
816 
817             if (ud.showfps > 1)
818             {
819                 chars = Bsprintf(tempbuf, "max: %5.1f fps", maxFPS);
820 
821                 printext256(windowxy2.x-(chars<<(3-x))+1, windowxy1.y+10+2+FPS_YOFFSET, 0, -1, tempbuf, x);
822                 printext256(windowxy2.x-(chars<<(3-x)), windowxy1.y+10+FPS_YOFFSET,
823                     FPS_COLOR(maxFPS < LOW_FPS), -1, tempbuf, x);
824 
825                 chars = Bsprintf(tempbuf, "min: %5.1f fps", minFPS);
826 
827                 printext256(windowxy2.x-(chars<<(3-x))+1, windowxy1.y+20+2+FPS_YOFFSET, 0, -1, tempbuf, x);
828                 printext256(windowxy2.x-(chars<<(3-x)), windowxy1.y+20+FPS_YOFFSET,
829                     FPS_COLOR(minFPS < LOW_FPS), -1, tempbuf, x);
830             }
831             if (ud.showfps > 2)
832             {
833                 if (g_gameUpdateTime > maxGameUpdate) maxGameUpdate = g_gameUpdateTime;
834                 if (g_gameUpdateTime < minGameUpdate) minGameUpdate = g_gameUpdateTime;
835 
836                 chars = Bsprintf(tempbuf, "Game Update: %2.2f ms + draw: %2.2f ms", g_gameUpdateTime, g_gameUpdateAndDrawTime);
837 
838                 printext256(windowxy2.x-(chars<<(3-x))+1, windowxy1.y+30+2+FPS_YOFFSET, 0, -1, tempbuf, x);
839                 printext256(windowxy2.x-(chars<<(3-x)), windowxy1.y+30+FPS_YOFFSET,
840                     FPS_COLOR(g_gameUpdateAndDrawTime >= SLOW_FRAME_TIME), -1, tempbuf, x);
841 
842                 chars = Bsprintf(tempbuf, "GU min/max/avg: %5.2f/%5.2f/%5.2f ms", minGameUpdate, maxGameUpdate, g_gameUpdateAvgTime);
843 
844                 printext256(windowxy2.x-(chars<<(3-x))+1, windowxy1.y+40+2+FPS_YOFFSET, 0, -1, tempbuf, x);
845                 printext256(windowxy2.x-(chars<<(3-x)), windowxy1.y+40+FPS_YOFFSET,
846                     FPS_COLOR(maxGameUpdate >= SLOW_FRAME_TIME), -1, tempbuf, x);
847 
848                 chars = Bsprintf(tempbuf, "G_MoveActors(): %.3e ms", g_moveActorsTime);
849 
850                 printext256(windowxy2.x-(chars<<(3-x))+1, windowxy1.y+50+2+FPS_YOFFSET, 0, -1, tempbuf, x);
851                 printext256(windowxy2.x-(chars<<(3-x)), windowxy1.y+50+FPS_YOFFSET,
852                     COLOR_WHITE, -1, tempbuf, x);
853 
854                 chars = Bsprintf(tempbuf, "G_MoveWorld(): %.3e ms", g_moveWorldTime);
855 
856                 printext256(windowxy2.x-(chars<<(3-x))+1, windowxy1.y+60+2+FPS_YOFFSET, 0, -1, tempbuf, x);
857                 printext256(windowxy2.x-(chars<<(3-x)), windowxy1.y+60+FPS_YOFFSET,
858                     COLOR_WHITE, -1, tempbuf, x);
859             }
860 
861             // lag meter
862             if (g_netClientPeer)
863             {
864                 chars = Bsprintf(tempbuf, "%d +- %d ms", (g_netClientPeer->lastRoundTripTime + g_netClientPeer->roundTripTime)/2,
865                     (g_netClientPeer->lastRoundTripTimeVariance + g_netClientPeer->roundTripTimeVariance)/2);
866 
867                 printext256(windowxy2.x-(chars<<(3-x))+1, windowxy1.y+30+2+FPS_YOFFSET, 0, -1, tempbuf, x);
868                 printext256(windowxy2.x-(chars<<(3-x)), windowxy1.y+30+1+FPS_YOFFSET, FPS_COLOR(g_netClientPeer->lastRoundTripTime > 200), -1, tempbuf, x);
869             }
870         }
871 
872         if (cumulativeFrameDelay >= 1000.0)
873         {
874             lastFPS = 1000.f * frameCount / cumulativeFrameDelay;
875             g_frameRate = Blrintf(lastFPS);
876             frameCount = 0;
877             cumulativeFrameDelay = 0.0;
878 
879             if (ud.showfps > 1)
880             {
881                 if (lastFPS > maxFPS) maxFPS = lastFPS;
882                 if (lastFPS < minFPS) minFPS = lastFPS;
883 
884                 static int secondCounter;
885 
886                 if (++secondCounter >= ud.frameperiod)
887                 {
888                     maxFPS = (lastFPS + maxFPS) * .5f;
889                     minFPS = (lastFPS + minFPS) * .5f;
890                     maxGameUpdate = (g_gameUpdateTime + maxGameUpdate) * 0.5;
891                     minGameUpdate = (g_gameUpdateTime + minGameUpdate) * 0.5;
892                     secondCounter = 0;
893                 }
894             }
895         }
896         frameCount++;
897     }
898     lastFrameTime = frameTime;
899 }
900 
901 #undef FPS_COLOR
902 
G_DisplayRest(int32_t smoothratio)903 void G_DisplayRest(int32_t smoothratio)
904 {
905     int32_t i, j;
906     palaccum_t tint = PALACCUM_INITIALIZER;
907 
908     DukePlayer_t *const pp = g_player[screenpeek].ps;
909 #ifdef SPLITSCREEN_MOD_HACKS
910     DukePlayer_t *const pp2 = g_fakeMultiMode==2 ? g_player[1].ps : NULL;
911 #endif
912     int32_t cposx, cposy, cang;
913 
914 #ifdef USE_OPENGL
915     // this takes care of fullscreen tint for OpenGL
916     if (videoGetRenderMode() >= REND_POLYMOST)
917     {
918         polytint_t & fstint = hictinting[MAXPALOOKUPS-1];
919 
920         if (pp->palette == WATERPAL)
921         {
922             fstint.r = 224;
923             fstint.g = 192;
924             fstint.b = 255;
925             fstint.f = 0;
926         }
927         else if (pp->palette == SLIMEPAL)
928         {
929             fstint.r = 208;
930             fstint.g = 255;
931             fstint.b = 192;
932             fstint.f = 0;
933         }
934         else
935         {
936             fstint.r = 255;
937             fstint.g = 255;
938             fstint.b = 255;
939             fstint.f = 0;
940         }
941     }
942 #endif  // USE_OPENGL
943 
944     if (!REALITY)
945         palaccum_add(&tint, &pp->pals, pp->pals.f);
946 #ifdef SPLITSCREEN_MOD_HACKS
947     if (pp2)
948         palaccum_add(&tint, &pp2->pals, pp2->pals.f);
949 #endif
950     if (!RR)
951     {
952         static const palette_t loogiepal = { 0, 63, 0, 0 };
953 
954         palaccum_add(&tint, &loogiepal, pp->loogcnt>>1);
955 #ifdef SPLITSCREEN_MOD_HACKS
956         if (pp2)
957             palaccum_add(&tint, &loogiepal, pp2->loogcnt>>1);
958 #endif
959     }
960 
961     if (g_restorePalette)
962     {
963         // reset a normal palette
964         static uint32_t omovethingscnt;
965 
966         if (g_restorePalette < 2 || omovethingscnt+1 == g_moveThingsCount)
967         {
968             int32_t pal = pp->palette;
969 #ifdef SPLITSCREEN_MOD_HACKS
970             const int32_t opal = pal;
971 
972             if (pp2)  // splitscreen HACK: BASEPAL trumps all, then it's arbitrary.
973                 pal = min(pal, pp2->palette);
974 #endif
975 
976             // g_restorePalette < 0: reset tinting, too (e.g. when loading new game)
977             P_SetGamePalette(pp, pal, 2 + (g_restorePalette>0)*16);
978 
979 #ifdef SPLITSCREEN_MOD_HACKS
980             if (pp2)  // keep first player's pal as its member!
981                 pp->palette = opal;
982 #endif
983 
984             g_restorePalette = 0;
985         }
986         else
987         {
988             // delay setting the palette by one game tic
989             omovethingscnt = g_moveThingsCount;
990         }
991     }
992 
993     if (ud.show_help)
994     {
995         switch (ud.show_help)
996         {
997         case 1:
998             rotatesprite_fs(160<<16, 100<<16, 65536L, 0, TEXTSTORY, 0, 0, 10+64);
999             break;
1000         case 2:
1001             rotatesprite_fs(160<<16, 100<<16, 65536L, 0, F1HELP, 0, 0, 10+64);
1002             break;
1003         case 3:
1004             if (RRRA)
1005                 rotatesprite_fs(160<<16, 100<<16, 65536L, 0, RRTILE1636, 0, 0, 10+64);
1006             break;
1007         }
1008 
1009         if (I_ReturnTrigger())
1010         {
1011             I_ReturnTriggerClear();
1012             ud.show_help = 0;
1013             if ((!g_netServer && ud.multimode < 2) && ud.recstat != 2)
1014             {
1015                 ready2send = 1;
1016                 totalclock = ototalclock;
1017             }
1018             G_UpdateScreenArea();
1019         }
1020 
1021         return;
1022     }
1023 
1024     i = pp->cursectnum;
1025     if (i > -1)
1026     {
1027         const walltype *wal = &wall[sector[i].wallptr];
1028 
1029         show2dsector[i>>3] |= (1<<(i&7));
1030         for (j=sector[i].wallnum; j>0; j--, wal++)
1031         {
1032             i = wal->nextsector;
1033             if (i < 0) continue;
1034             if (wal->cstat&0x0071) continue;
1035             if (wall[wal->nextwall].cstat&0x0071) continue;
1036             if (sector[i].lotag == 32767) continue;
1037             if (sector[i].ceilingz >= sector[i].floorz) continue;
1038             show2dsector[i>>3] |= (1<<(i&7));
1039         }
1040     }
1041 
1042     if (ud.camerasprite == -1)
1043     {
1044         if (ud.overhead_on != 2)
1045         {
1046             if (!RR && pp->newowner >= 0)
1047                 G_DrawCameraText(pp->newowner);
1048             else
1049             {
1050                 P_DisplayWeapon();
1051 #ifdef SPLITSCREEN_MOD_HACKS
1052                 if (pp2)  // HACK
1053                 {
1054                     const int32_t oscreenpeek = screenpeek;
1055                     screenpeek = 1;
1056                     P_DisplayWeapon();
1057                     screenpeek = oscreenpeek;
1058                 }
1059 #endif
1060 
1061                 if (pp->over_shoulder_on == 0)
1062                 {
1063                     if (REALITY)
1064                         RT_P_DisplayScuba();
1065                     else
1066                         P_DisplayScuba();
1067                 }
1068 #ifdef SPLITSCREEN_MOD_HACKS
1069                 if (pp2 && pp2->over_shoulder_on == 0)  // HACK
1070                 {
1071                     const int32_t oscreenpeek = screenpeek;
1072                     screenpeek = 1;
1073                     P_DisplayScuba();
1074                     screenpeek = oscreenpeek;
1075                 }
1076 #endif
1077             }
1078             if (!RR)
1079                 G_MoveClouds();
1080         }
1081 
1082         if (DEER)
1083             sub_57B38(pp->opos.x, pp->opos.y, 20, 1536);
1084 
1085         if (ud.overhead_on > 0)
1086         {
1087             // smoothratio = min(max(smoothratio,0),65536);
1088             smoothratio = calc_smoothratio(totalclock, ototalclock);
1089             G_DoInterpolations(smoothratio);
1090 
1091             if (ud.scrollmode == 0)
1092             {
1093                 if (pp->newowner == -1 && !ud.pause_on)
1094                 {
1095                     if (screenpeek == myconnectindex && numplayers > 1)
1096                     {
1097                         cposx = omypos.x + mulscale16(mypos.x-omypos.x, smoothratio);
1098                         cposy = omypos.y + mulscale16(mypos.y-omypos.y, smoothratio);
1099                         cang = fix16_to_int(omyang) + mulscale16((fix16_to_int(myang+F16(1024)-omyang)&2047)-1024, smoothratio);
1100                     }
1101                     else
1102                     {
1103                         cposx = pp->opos.x + mulscale16(pp->pos.x-pp->opos.x, smoothratio);
1104                         cposy = pp->opos.y + mulscale16(pp->pos.y-pp->opos.y, smoothratio);
1105                         cang = fix16_to_int(pp->oq16ang) + mulscale16((fix16_to_int(pp->q16ang+F16(1024)-pp->oq16ang)&2047)-1024, smoothratio);
1106                     }
1107                 }
1108                 else
1109                 {
1110                     cposx = pp->opos.x;
1111                     cposy = pp->opos.y;
1112                     cang = fix16_to_int(pp->oq16ang);
1113                 }
1114             }
1115             else
1116             {
1117 #ifdef __ANDROID__
1118                 CONTROL_Android_ScrollMap(&ud.fola, &ud.folx, &ud.foly, &pp->zoom);
1119 #else
1120                 if (!ud.pause_on)
1121                 {
1122                     ud.fola += ud.folavel>>3;
1123                     ud.folx += (ud.folfvel*sintable[(512+2048-ud.fola)&2047])>>14;
1124                     ud.foly += (ud.folfvel*sintable[(512+1024-512-ud.fola)&2047])>>14;
1125                 }
1126 #endif
1127                 cposx = ud.folx;
1128                 cposy = ud.foly;
1129                 cang = ud.fola;
1130             }
1131 
1132             if (ud.overhead_on == 2)
1133             {
1134                 videoClearViewableArea(0L);
1135                 renderDrawMapView(cposx, cposy, pp->zoom, cang);
1136             }
1137             G_DrawOverheadMap(cposx, cposy, pp->zoom, cang);
1138 
1139             G_RestoreInterpolations();
1140 
1141             if (ud.overhead_on == 2)
1142             {
1143                 const int32_t a = RR ? 0 : ((ud.screen_size > 0) ? 147 : 179);
1144                 if (RR && g_lastLevel)
1145                     minitext(5, a+6, "CLOSE ENCOUNTERS", 0, 2+8+16+256);
1146                 else
1147                 {
1148                     if (!REALITY && !G_HaveUserMap())
1149                         minitext(5, a+6, g_volumeNames[ud.volume_number], 0, 2+8+16+256);
1150                     minitext(5, a+6+6, g_mapInfo[ud.volume_number*MAXLEVELS + ud.level_number].name, 0, 2+8+16+256);
1151                 }
1152             }
1153         }
1154     }
1155 
1156     if (!REALITY && pp->invdisptime > 0) G_DrawInventory(pp);
1157 
1158     G_DrawStatusBar(screenpeek);
1159 
1160 #ifdef SPLITSCREEN_MOD_HACKS
1161     // HACK
1162     if (g_fakeMultiMode==2)
1163     {
1164         G_DrawStatusBar(1);
1165         G_PrintGameQuotes(1);
1166     }
1167 #endif
1168 
1169     G_PrintGameQuotes(screenpeek);
1170 
1171     if (ud.show_level_text && hud_showmapname && g_levelTextTime > 1)
1172     {
1173         int32_t o = 10|16;
1174 
1175         if (g_levelTextTime < 3)
1176             o |= 1|32;
1177         else if (g_levelTextTime < 5)
1178             o |= 1;
1179 
1180         if (g_mapInfo[(ud.volume_number*MAXLEVELS) + ud.level_number].name != NULL)
1181         {
1182             char const * const fn = currentboardfilename[0] != 0 &&
1183                 ud.volume_number == 0 && ud.level_number == 7
1184                     ? currentboardfilename
1185                     : g_mapInfo[(ud.volume_number*MAXLEVELS) + ud.level_number].name;
1186 
1187             if (REALITY)
1188             {
1189                 RT_DisablePolymost(0);
1190                 RT_RotateSpriteSetColor(255, 128, 128, clamp(g_levelTextTime * 8, 0, 256));
1191                 menutext_(160<<16, (90+16+8)<<16, 0, fn, 0, TEXT_XCENTER|TEXT_N64NOPAL);
1192                 RT_EnablePolymost();
1193             }
1194             else
1195                 menutext_(160<<16, (90+16+8)<<16, -g_levelTextTime+22/*quotepulseshade*/, fn, o, TEXT_XCENTER);
1196         }
1197     }
1198 
1199     if (I_EscapeTrigger() && ud.overhead_on == 0
1200         && ud.show_help == 0
1201         && g_player[myconnectindex].ps->newowner == -1)
1202     {
1203         if ((g_player[myconnectindex].ps->gm&MODE_MENU) == MODE_MENU && g_currentMenu <= MENU_MAIN_INGAME)
1204         {
1205             I_EscapeTriggerClear();
1206             S_PlaySound(REALITY ? 0xaa : EXITMENUSOUND);
1207             Menu_Change(MENU_CLOSE);
1208             if (!ud.pause_on)
1209                 S_PauseSounds(false);
1210         }
1211         else if ((g_player[myconnectindex].ps->gm&MODE_MENU) != MODE_MENU &&
1212             g_player[myconnectindex].ps->newowner == -1 &&
1213             (g_player[myconnectindex].ps->gm&MODE_TYPE) != MODE_TYPE)
1214         {
1215             I_EscapeTriggerClear();
1216             S_PauseSounds(true);
1217 
1218             Menu_Open(myconnectindex);
1219 
1220             if ((!g_netServer && ud.multimode < 2) && ud.recstat != 2) ready2send = 0;
1221 
1222             if (g_player[myconnectindex].ps->gm&MODE_GAME) Menu_Change(MENU_MAIN_INGAME);
1223             else Menu_Change(MENU_MAIN);
1224             screenpeek = myconnectindex;
1225 
1226             S_MenuSound();
1227         }
1228     }
1229 
1230     if (!DEER && g_player[myconnectindex].ps->newowner == -1 && ud.overhead_on == 0 && ud.crosshair && ud.camerasprite == -1)
1231     {
1232         int32_t a = CROSSHAIR;
1233         if ((unsigned) a < MAXTILES)
1234         {
1235             vec2_t crosshairpos = { (160<<16) - (g_player[myconnectindex].ps->look_ang<<15), 100<<16 };
1236             uint8_t crosshair_pal = CROSSHAIR_PAL;
1237             uint32_t crosshair_o = 1|2;
1238             uint32_t crosshair_scale = divscale16(ud.crosshairscale, 100);
1239             if (RR)
1240                 crosshair_scale >>= 1;
1241 
1242             rotatesprite_win(crosshairpos.x, crosshairpos.y, crosshair_scale, 0, a, 0, crosshair_pal, crosshair_o);
1243         }
1244     }
1245 
1246 #ifdef GEKKO
1247     // like the mouse cursor, the pointer doesn't use the crosshair enabled / scale options
1248     if (g_player[myconnectindex].ps->newowner == -1 && ud.overhead_on == 0 && ud.camerasprite == -1 &&
1249         (g_player[myconnectindex].ps->gm&MODE_MENU) == 0 && mouseReadAbs((vec2_t *)&ud.returnvar[0], &g_mouseAbs))
1250     {
1251         int32_t a = VM_OnEventWithReturn(EVENT_DISPLAYPOINTER, g_player[screenpeek].ps->i, screenpeek, CROSSHAIR);
1252         if ((unsigned) a < MAXTILES)
1253         {
1254             vec2_t pointerpos = { tabledivide32(ud.returnvar[0], upscalefactor), tabledivide32(ud.returnvar[1], upscalefactor) };
1255             uint8_t pointer_pal = CROSSHAIR_PAL;
1256             uint32_t pointer_o = 1|2;
1257             uint32_t pointer_scale = 65536;
1258 
1259             auto const oyxaspect = yxaspect;
1260 
1261             rotatesprite_win(pointerpos.x, pointerpos.y, pointer_scale, 0, a, 0, pointer_pal, pointer_o);
1262         }
1263     }
1264 #endif
1265 #if 0
1266     if (g_gametypeFlags[ud.coop] & GAMETYPE_TDM)
1267     {
1268         for (i=0; i<ud.multimode; i++)
1269         {
1270             if (g_player[i].ps->team == g_player[myconnectindex].ps->team)
1271             {
1272                 j = min(max((G_GetAngleDelta(getangle(g_player[i].ps->pos.x-g_player[myconnectindex].ps->pos.x,
1273                     g_player[i].ps->pos.y-g_player[myconnectindex].ps->pos.y), g_player[myconnectindex].ps->ang))>>1, -160), 160);
1274                 rotatesprite_win((160-j)<<16, 100L<<16, 65536L, 0, DUKEICON, 0, 0, 2+1);
1275             }
1276         }
1277     }
1278 #endif
1279 
1280     if (ud.pause_on==1 && (g_player[myconnectindex].ps->gm&MODE_MENU) == 0)
1281         menutext_center(100, "Game Paused");
1282 
1283     if (ud.coords)
1284         G_PrintCoords(screenpeek);
1285 
1286 #ifdef YAX_DEBUG
1287     M32_drawdebug();
1288 #endif
1289 
1290 #ifdef USE_OPENGL
1291     mdpause = (ud.pause_on || (ud.recstat==2 && (g_demo_paused && g_demo_goalCnt==0)) || (g_player[myconnectindex].ps->gm&MODE_MENU && numplayers < 2));
1292 #endif
1293 
1294     G_PrintFPS();
1295 
1296     // JBF 20040124: display level stats in screen corner
1297     if (ud.overhead_on != 2 && ud.levelstats)
1298     {
1299         DukePlayer_t const * const myps = g_player[myconnectindex].ps;
1300         int const sbarshift = RR ? 15 : 16;
1301         int const ystep = RR ? (10<<16) : (7<<16);
1302 
1303         i = 198<<16;
1304 
1305         if (ud.screen_size == 4)
1306         {
1307             if (ud.althud == 0 || ud.hudontop == 0)
1308                 i -= sbarsc(ud.althud ? ((tilesiz[BIGALPHANUM].y<<sbarshift)+(8<<16)) : (REALITY ? 30 : tilesiz[INVENTORYBOX].y)<<sbarshift);
1309         }
1310         else if (RR && ud.screen_size == 12)
1311         {
1312             i -= sbarsc((tilesiz[BOTTOMSTATUSBAR].y+tilesiz[WEAPONBAR].y)<<sbarshift);
1313         }
1314         else if (ud.screen_size > 2)
1315             i -= sbarsc(tilesiz[BOTTOMSTATUSBAR].y<<sbarshift);
1316 
1317         int32_t const xbetween = (tilesiz[MF_Bluefont.tilenum + 'A' - '!'].x<<16) + MF_Bluefont.between.x;
1318 
1319         int32_t textflags = TEXT_XOFFSETZERO | TEXT_GAMETEXTNUMHACK;
1320 
1321         if (REALITY)
1322         {
1323             RT_DisablePolymost(0);
1324             RT_RotateSpriteSetColor(255, 80, 0, 256);
1325             textflags |= TEXT_N64NOPAL;
1326         }
1327 
1328         Bsprintf(tempbuf, "T:^15%d:%02d.%02d",
1329             (myps->player_par/(REALGAMETICSPERSEC*60)),
1330             (myps->player_par/REALGAMETICSPERSEC)%60,
1331             ((myps->player_par%REALGAMETICSPERSEC)*33)/10
1332             );
1333         G_ScreenText(MF_Bluefont.tilenum, 2<<16, i-gtextsc(ystep*(REALITY ? 4 : 3)), gtextsc(MF_Bluefont.zoom), 0, 0, tempbuf, 0, 10, 2|8|16|256|ROTATESPRITE_FULL16, 0, MF_Bluefont.emptychar.x, MF_Bluefont.emptychar.y, xbetween, MF_Bluefont.between.y, MF_Bluefont.textflags|textflags, 0, 0, xdim-1, ydim-1);
1334 
1335         if ((!RR && ud.player_skill > 3) || ((g_netServer || ud.multimode > 1) && !GTFLAGS(GAMETYPE_PLAYERSFRIENDLY)))
1336             Bsprintf(tempbuf, "K:^15%d", (ud.multimode>1 &&!GTFLAGS(GAMETYPE_PLAYERSFRIENDLY)) ?
1337                 myps->frag-myps->fraggedself : myps->actors_killed);
1338         else
1339         {
1340             if (myps->actors_killed >= myps->max_actors_killed)
1341                 Bsprintf(tempbuf, "K:%d/%d", myps->actors_killed, myps->actors_killed);
1342             else
1343                 Bsprintf(tempbuf, "K:^15%d/%d", myps->actors_killed, myps->max_actors_killed);
1344         }
1345         G_ScreenText(MF_Bluefont.tilenum, 2<<16, i-gtextsc(ystep*(REALITY ? 3 : 2)), gtextsc(MF_Bluefont.zoom), 0, 0, tempbuf, 0, 10, 2|8|16|256|ROTATESPRITE_FULL16, 0, MF_Bluefont.emptychar.x, MF_Bluefont.emptychar.y, xbetween, MF_Bluefont.between.y, MF_Bluefont.textflags|textflags, 0, 0, xdim-1, ydim-1);
1346 
1347         if (myps->secret_rooms == myps->max_secret_rooms)
1348             Bsprintf(tempbuf, "S:%d/%d", myps->secret_rooms, myps->max_secret_rooms);
1349         else Bsprintf(tempbuf, "S:^15%d/%d", myps->secret_rooms, myps->max_secret_rooms);
1350         G_ScreenText(MF_Bluefont.tilenum, 2<<16, i-gtextsc(ystep), gtextsc(MF_Bluefont.zoom), 0, 0, tempbuf, 0, 10, 2|8|16|256|ROTATESPRITE_FULL16, 0, MF_Bluefont.emptychar.x, MF_Bluefont.emptychar.y, xbetween, MF_Bluefont.between.y, MF_Bluefont.textflags|textflags, 0, 0, xdim-1, ydim-1);
1351 
1352 
1353         if (REALITY)
1354         {
1355             Bsprintf(tempbuf, "B:%d/%d",
1356                 myps->dn64_36e, myps->dn64_36d
1357                 );
1358             G_ScreenText(MF_Bluefont.tilenum, 2<<16, i-gtextsc(ystep*2), gtextsc(MF_Bluefont.zoom), 0, 0, tempbuf, 0, 10, 2|8|16|256|ROTATESPRITE_FULL16, 0, MF_Bluefont.emptychar.x, MF_Bluefont.emptychar.y, xbetween, MF_Bluefont.between.y, MF_Bluefont.textflags|textflags, 0, 0, xdim-1, ydim-1);
1359 
1360             RT_EnablePolymost();
1361         }
1362     }
1363 
1364     if (g_player[myconnectindex].gotvote == 0 && voting != -1 && voting != myconnectindex)
1365     {
1366         Bsprintf(tempbuf, "%s^00 has called a vote for map", g_player[voting].user_name);
1367         gametext_center(40, tempbuf);
1368         Bsprintf(tempbuf, "%s (E%dL%d)", g_mapInfo[vote_episode*MAXLEVELS + vote_map].name, vote_episode+1, vote_map+1);
1369         gametext_center(48, tempbuf);
1370         gametext_center(70, "Press F1 to Accept, F2 to Decline");
1371     }
1372 
1373     if (BUTTON(gamefunc_Show_DukeMatch_Scores))
1374         G_ShowScores();
1375 
1376     if (g_Debug)
1377         G_ShowCacheLocks();
1378 
1379     Net_DisplaySyncMsg();
1380 
1381 #ifndef EDUKE32_TOUCH_DEVICES
1382     if (VOLUMEONE)
1383     {
1384         if (ud.show_help == 0 && g_showShareware > 0 && (g_player[myconnectindex].ps->gm&MODE_MENU) == 0)
1385             rotatesprite_fs((320-50)<<16, 9<<16, 65536L, 0, BETAVERSION, 0, 0, 2+8+16+128);
1386     }
1387 #endif
1388 
1389     if (!Demo_IsProfiling())
1390     {
1391         if (g_player[myconnectindex].ps->gm&MODE_TYPE)
1392             Net_SendMessage();
1393         else
1394             M_DisplayMenus();
1395     }
1396 
1397     {
1398         static int32_t applied = 0;
1399 
1400         if (tint.maxf)
1401         {
1402             G_FadePalaccum(&tint);
1403             applied = 1;
1404         }
1405         else if (applied)
1406         {
1407             // be sure to always un-apply a tint.
1408             videoFadePalette(0, 0, 0, 0);
1409             applied = 0;
1410         }
1411     }
1412 }
1413 
G_FadePalette(int32_t r,int32_t g,int32_t b,int32_t e)1414 void G_FadePalette(int32_t r, int32_t g, int32_t b, int32_t e)
1415 {
1416     if (ud.screenfade == 0)
1417       return;
1418     videoFadePalette(r, g, b, e);
1419     videoNextPage();
1420 
1421     int32_t tc = (int32_t) totalclock;
1422     while (totalclock < tc + 4)
1423         G_HandleAsync();
1424 }
1425 
1426 // START and END limits are always inclusive!
1427 // STEP must evenly divide END-START, i.e. abs(end-start)%step == 0
fadepal(int32_t r,int32_t g,int32_t b,int32_t start,int32_t end,int32_t step)1428 void fadepal(int32_t r, int32_t g, int32_t b, int32_t start, int32_t end, int32_t step)
1429 {
1430     if (ud.screenfade == 0)
1431       return;
1432     if (videoGetRenderMode() >= REND_POLYMOST)
1433     {
1434         G_FadePalette(r, g, b, end);
1435         return;
1436     }
1437 
1438     // (end-start)/step + 1 iterations
1439     do
1440     {
1441         if (KB_KeyPressed(sc_Space))
1442         {
1443             KB_ClearKeyDown(sc_Space);
1444             videoFadePalette(r, g, b, end);  // have to set to end fade value if we break!
1445             return;
1446         }
1447 
1448         G_FadePalette(r, g, b, start);
1449 
1450         start += step;
1451     } while (start != end+step);
1452 }
1453 
1454 // START and END limits are always inclusive!
fadepaltile(int32_t r,int32_t g,int32_t b,int32_t start,int32_t end,int32_t step,int32_t tile)1455 static void fadepaltile(int32_t r, int32_t g, int32_t b, int32_t start, int32_t end, int32_t step, int32_t tile)
1456 {
1457     if (ud.screenfade == 0)
1458       return;
1459     // STEP must evenly divide END-START
1460     Bassert(klabs(end-start)%step == 0);
1461 
1462     videoClearScreen(0);
1463 
1464     // (end-start)/step + 1 iterations
1465     do
1466     {
1467 #ifdef __ANDROID__ //Needed for N7 2013 to stop corruption while fading video
1468         videoClearViewableArea(0);
1469 #endif
1470         if (KB_KeyPressed(sc_Space))
1471         {
1472             KB_ClearKeyDown(sc_Space);
1473             videoFadePalette(r, g, b, end);  // have to set to end fade value if we break!
1474             return;
1475         }
1476         rotatesprite_fs(160<<16, 100<<16, 65536L, 0, tile, 0, 0, 2+8+64+BGSTRETCH);
1477         G_FadePalette(r, g, b, start);
1478 
1479         start += step;
1480     } while (start != end+step);
1481 }
1482 
1483 #ifdef __ANDROID__
1484 int inExtraScreens = 0;
1485 #endif
1486 
G_DisplayExtraScreens(void)1487 void G_DisplayExtraScreens(void)
1488 {
1489     S_StopMusic();
1490     FX_StopAllSounds();
1491     if (RR)
1492         return;
1493 
1494     if (!VOLUMEALL)
1495     {
1496 #ifdef __ANDROID__
1497         inExtraScreens = 1;
1498 #endif
1499         videoSetViewableArea(0, 0, xdim-1, ydim-1);
1500         renderFlushPerms();
1501         //g_player[myconnectindex].ps->palette = palette;
1502         P_SetGamePalette(g_player[myconnectindex].ps, BASEPAL, 1);    // JBF 20040308
1503         fadepal(0, 0, 0, 0, 252, 28);
1504         I_ClearAllInput();
1505         rotatesprite_fs(160<<16, 100<<16, 65536L, 0, 3291, 0, 0, 2+8+64+BGSTRETCH);
1506         fadepaltile(0, 0, 0, 252, 0, -28, 3291);
1507         while (!I_CheckAllInput())
1508             G_HandleAsync();
1509 
1510         fadepaltile(0, 0, 0, 0, 252, 28, 3291);
1511         I_ClearAllInput();
1512         rotatesprite_fs(160<<16, 100<<16, 65536L, 0, 3290, 0, 0, 2+8+64+BGSTRETCH);
1513         fadepaltile(0, 0, 0, 252, 0, -28, 3290);
1514         while (!I_CheckAllInput())
1515             G_HandleAsync();
1516 
1517 #ifdef __ANDROID__
1518         inExtraScreens = 0;
1519 #endif
1520     }
1521 
1522     if (0)
1523     {
1524 #ifdef __ANDROID__
1525         inExtraScreens = 1;
1526 #endif
1527         videoSetViewableArea(0, 0, xdim-1, ydim-1);
1528         renderFlushPerms();
1529         //g_player[myconnectindex].ps->palette = palette;
1530         P_SetGamePalette(g_player[myconnectindex].ps, BASEPAL, 1);    // JBF 20040308
1531         fadepal(0, 0, 0, 0, 252, 28);
1532         I_ClearAllInput();
1533         totalclock = 0;
1534         rotatesprite_fs(160<<16, 100<<16, 65536L, 0, TENSCREEN, 0, 0, 2+8+64+BGSTRETCH);
1535         fadepaltile(0, 0, 0, 252, 0, -28, TENSCREEN);
1536         while (!I_CheckAllInput() && totalclock < 2400)
1537             G_HandleAsync();
1538 
1539         fadepaltile(0, 0, 0, 0, 252, 28, TENSCREEN);
1540         I_ClearAllInput();
1541 #ifdef __ANDROID__
1542         inExtraScreens = 0;
1543 #endif
1544     }
1545 }
1546 
G_DisplayLogo(void)1547 void G_DisplayLogo(void)
1548 {
1549     int32_t soundanm = 0;
1550     //int32_t logoflags = G_GetLogoFlags();
1551 
1552     ready2send = 0;
1553 
1554     I_ClearAllInput();
1555 
1556     videoSetViewableArea(0, 0, xdim-1, ydim-1);
1557     videoClearScreen(0L);
1558     G_FadePalette(0, 0, 0, 252);
1559 
1560     renderFlushPerms();
1561     videoNextPage();
1562 
1563     G_UpdateAppTitle();
1564 
1565     S_StopMusic();
1566     FX_StopAllSounds(); // JBF 20031228
1567     S_ClearSoundLocks();  // JBF 20031228
1568     if (DEER)
1569     {
1570         if (!g_noLogo /* && (!g_netServer && ud.multimode < 2) */)
1571         {
1572             if (!I_CheckAllInput() && g_noLogoAnim == 0)
1573             {
1574                 videoClearScreen(0);
1575 
1576                 P_SetGamePalette(g_player[myconnectindex].ps, BASEPAL, 8 + 2 + 1);    // JBF 20040308
1577                 fadepal(0, 0, 0, 0, 252, 28);
1578                 renderFlushPerms();
1579                 rotatesprite_fs(160 << 16, 100 << 16, 65536L, 0, 7106, 0, 0, 2 + 8 + 64 + BGSTRETCH);
1580                 videoNextPage();
1581                 fadepaltile(0, 0, 0, 252, 0, -4, 7106);
1582                 totalclock = 0;
1583 
1584                 while (totalclock < (120 * 3) && !I_CheckAllInput())
1585                 {
1586                     if (engineFPSLimit())
1587                     {
1588                         videoClearScreen(0);
1589                         rotatesprite_fs(160 << 16, 100 << 16, 65536L, 0, 7106, 0, 0, 2 + 8 + 64 + BGSTRETCH);
1590                         G_HandleAsync();
1591 
1592                         if (g_restorePalette)
1593                         {
1594                             P_SetGamePalette(g_player[myconnectindex].ps, g_player[myconnectindex].ps->palette, 0);
1595                             g_restorePalette = 0;
1596                         }
1597                         videoNextPage();
1598                     }
1599                 }
1600 
1601                 fadepaltile(0, 0, 0, 0, 252, 4, 7106);
1602             }
1603 
1604             videoClearScreen(0L);
1605             videoNextPage();
1606 
1607             I_ClearAllInput();
1608 
1609             videoClearScreen(0L);
1610             videoNextPage();
1611 
1612             videoClearScreen(0);
1613 
1614             //g_player[myconnectindex].ps->palette = drealms;
1615             //G_FadePalette(0,0,0,252);
1616 
1617             if (!I_CheckAllInput() && g_noLogoAnim == 0)
1618             {
1619                 videoClearScreen(0);
1620 
1621                 P_SetGamePalette(g_player[myconnectindex].ps, BASEPAL, 8 + 2 + 1);    // JBF 20040308
1622                 fadepal(0, 0, 0, 0, 252, 28);
1623                 renderFlushPerms();
1624                 rotatesprite_fs(160 << 16, 100 << 16, 65536L, 0, 7107, 0, 0, 2 + 8 + 64 + BGSTRETCH);
1625                 videoNextPage();
1626                 fadepaltile(0, 0, 0, 252, 0, -4, 7107);
1627                 totalclock = 0;
1628 
1629                 while (totalclock < (120 * 3) && !I_CheckAllInput())
1630                 {
1631                     if (engineFPSLimit())
1632                     {
1633                         videoClearScreen(0);
1634                         rotatesprite_fs(160 << 16, 100 << 16, 65536L, 0, 7107, 0, 0, 2 + 8 + 64 + BGSTRETCH);
1635                         G_HandleAsync();
1636 
1637                         if (g_restorePalette)
1638                         {
1639                             P_SetGamePalette(g_player[myconnectindex].ps, g_player[myconnectindex].ps->palette, 0);
1640                             g_restorePalette = 0;
1641                         }
1642                         videoNextPage();
1643                     }
1644                 }
1645 
1646                 fadepaltile(0, 0, 0, 0, 252, 4, 7107);
1647             }
1648 
1649             I_ClearAllInput();
1650         }
1651 
1652         renderFlushPerms();
1653         videoClearScreen(0L);
1654         videoNextPage();
1655 
1656         //g_player[myconnectindex].ps->palette = palette;
1657         P_SetGamePalette(g_player[myconnectindex].ps, BASEPAL, 0);    // JBF 20040308
1658 
1659         //G_FadePalette(0,0,0,0);
1660         videoClearScreen(0L);
1661 
1662         g_noLogo = 1; // Play intro only once
1663         return;
1664     }
1665     if (RRRA)
1666         return;
1667     if (RR)
1668     {
1669         if (!I_CheckAllInput() && g_noLogoAnim == 0)
1670         {
1671             Net_GetPackets();
1672             Anim_Play("rr_intro.anm");
1673             G_FadePalette(0, 0, 0, 252);
1674             I_ClearAllInput();
1675         }
1676 
1677         videoClearScreen(0L);
1678         videoNextPage();
1679         FX_StopAllSounds();
1680         S_ClearSoundLocks();
1681 
1682         if (!I_CheckAllInput() && g_noLogoAnim == 0)
1683         {
1684             Net_GetPackets();
1685             Anim_Play("redneck.anm");
1686             G_FadePalette(0, 0, 0, 252);
1687             I_ClearAllInput();
1688         }
1689 
1690         videoClearScreen(0L);
1691         videoNextPage();
1692         FX_StopAllSounds();
1693         S_ClearSoundLocks();
1694 
1695         if (!I_CheckAllInput() && g_noLogoAnim == 0)
1696         {
1697             Net_GetPackets();
1698             Anim_Play("xatlogo.anm");
1699             G_FadePalette(0, 0, 0, 252);
1700             I_ClearAllInput();
1701         }
1702 
1703         videoClearScreen(0L);
1704         videoNextPage();
1705         FX_StopAllSounds();
1706         S_ClearSoundLocks();
1707 
1708         //g_player[myconnectindex].ps->palette = palette;
1709         P_SetGamePalette(g_player[myconnectindex].ps, BASEPAL, 0);    // JBF 20040308
1710         S_PlaySound(NITEVISION_ONOFF);
1711 
1712         //G_FadePalette(0,0,0,0);
1713         videoClearScreen(0L);
1714         return;
1715     }
1716     if (REALITY)
1717     {
1718         G_FadePalette(0, 0, 0, 0);
1719         totalclock = 0;
1720 
1721         while ((int)totalclock < (4 * (16 + 120 + 16)) && !I_CheckAllInput())
1722         {
1723             if (engineFPSLimit())
1724             {
1725                 int alpha = 0;
1726                 if (totalclock < (4 * 16))
1727                     alpha = clamp((int)totalclock * 4, 0, 256);
1728                 else if (totalclock < (4 * (16 + 120)))
1729                     alpha = 256;
1730                 else
1731                     alpha = clamp(256 - ((int)totalclock - (4 * (16 + 120))) * 4, 0, 256);
1732 
1733 
1734                 videoClearScreen(0);
1735 
1736                 RT_DisablePolymost(0);
1737                 RT_RotateSpriteSetColor(255, 255, 255, alpha);
1738 
1739                 RT_RotateSprite(160, 60, 100, 100, 0xe09, 0);
1740                 RT_RotateSprite(100, 160, 100, 100, 0xe5d, 0);
1741                 RT_RotateSprite(220, 160, 100, 100, 0xe5e, 0);
1742                 RT_EnablePolymost();
1743 
1744                 G_HandleAsync();
1745                 videoNextPage();
1746             }
1747         }
1748 
1749         I_ClearAllInput();
1750 
1751         S_PlaySpecialMusicOrNothing(MUS_INTRO);
1752 
1753         renderFlushPerms();
1754         videoClearScreen(0L);
1755         videoNextPage();
1756 
1757         //g_player[myconnectindex].ps->palette = palette;
1758         P_SetGamePalette(g_player[myconnectindex].ps, BASEPAL, 0);    // JBF 20040308
1759 
1760         //G_FadePalette(0,0,0,0);
1761         videoClearScreen(0L);
1762         return;
1763     }
1764     if (!g_noLogo /* && (!g_netServer && ud.multimode < 2) */)
1765     {
1766 #ifndef EDUKE32_TOUCH_DEVICES
1767         if (VOLUMEALL)
1768 #endif
1769         {
1770             if (!I_CheckAllInput() && g_noLogoAnim == 0)
1771             {
1772                 Net_GetPackets();
1773                 Anim_Play("logo.anm");
1774                 G_FadePalette(0, 0, 0, 252);
1775                 I_ClearAllInput();
1776             }
1777 
1778             videoClearScreen(0L);
1779             videoNextPage();
1780             FX_StopAllSounds();
1781             S_ClearSoundLocks();
1782         }
1783 
1784         S_PlaySpecialMusicOrNothing(MUS_INTRO);
1785 
1786         //g_player[myconnectindex].ps->palette = drealms;
1787         //G_FadePalette(0,0,0,252);
1788 
1789         if (!I_CheckAllInput() && g_noLogoAnim == 0)
1790         {
1791             int32_t i;
1792             Net_GetPackets();
1793 
1794             i = kopen4loadfrommod("3dr.ivf", 0);
1795 
1796             if (i == -1)
1797                 i = kopen4loadfrommod("3dr.anm", 0);
1798 
1799             if (i != -1)
1800             {
1801                 kclose(i);
1802                 Anim_Play("3dr.anm");
1803                 G_FadePalette(0, 0, 0, 252);
1804                 I_ClearAllInput();
1805             }
1806             else
1807             {
1808                 videoClearScreen(0);
1809 
1810                 P_SetGamePalette(g_player[myconnectindex].ps, DREALMSPAL, 8 + 2 + 1);    // JBF 20040308
1811                 fadepal(0, 0, 0, 0, 252, 28);
1812                 renderFlushPerms();
1813                 rotatesprite_fs(160 << 16, 100 << 16, 65536L, 0, DREALMS, 0, 0, 2 + 8 + 64 + BGSTRETCH);
1814                 videoNextPage();
1815                 fadepaltile(0, 0, 0, 252, 0, -28, DREALMS);
1816                 totalclock = 0;
1817 
1818                 while (totalclock < (120 * 7) && !I_CheckAllInput())
1819                 {
1820                     if (engineFPSLimit())
1821                     {
1822                         videoClearScreen(0);
1823                         rotatesprite_fs(160 << 16, 100 << 16, 65536L, 0, DREALMS, 0, 0, 2 + 8 + 64 + BGSTRETCH);
1824                         G_HandleAsync();
1825 
1826                         if (g_restorePalette)
1827                         {
1828                             P_SetGamePalette(g_player[myconnectindex].ps, g_player[myconnectindex].ps->palette, 0);
1829                             g_restorePalette = 0;
1830                         }
1831                         videoNextPage();
1832                     }
1833                 }
1834 
1835                 fadepaltile(0, 0, 0, 0, 252, 28, DREALMS);
1836             }
1837         }
1838 
1839         videoClearScreen(0L);
1840         videoNextPage();
1841 
1842         I_ClearAllInput();
1843 
1844         videoClearScreen(0L);
1845         videoNextPage();
1846 
1847         videoClearScreen(0);
1848 
1849         //g_player[myconnectindex].ps->palette = titlepal;
1850         P_SetGamePalette(g_player[myconnectindex].ps, TITLEPAL, 8+2+1);   // JBF 20040308
1851         renderFlushPerms();
1852         rotatesprite_fs(160<<16, 100<<16, 65536L, 0, BETASCREEN, 0, 0, 2+8+64+BGSTRETCH);
1853         KB_FlushKeyboardQueue();
1854         fadepaltile(0, 0, 0, 252, 0, -28, BETASCREEN);
1855         totalclock = 0;
1856 
1857         while (
1858 #ifndef EDUKE32_SIMPLE_MENU
1859             totalclock < (860+120) &&
1860 #endif
1861             !I_CheckAllInput())
1862         {
1863             if (engineFPSLimit())
1864             {
1865                 videoClearScreen(0);
1866                 rotatesprite_fs(160<<16, 100<<16, 65536L, 0, BETASCREEN, 0, 0, 2+8+64+BGSTRETCH);
1867 
1868                 if (totalclock > 120 && totalclock < (120+60))
1869                 {
1870                     if (soundanm == 0)
1871                     {
1872                         soundanm++;
1873                         S_PlaySound(PIPEBOMB_EXPLODE);
1874                     }
1875                     rotatesprite_fs(160<<16, 104<<16, ((int32_t) totalclock-120)<<10, 0, DUKENUKEM, 0, 0, 2+8);
1876                 }
1877                 else if (totalclock >= (120+60))
1878                     rotatesprite_fs(160<<16, (104)<<16, 60<<10, 0, DUKENUKEM, 0, 0, 2+8);
1879 
1880                 if (totalclock > 220 && totalclock < (220+30))
1881                 {
1882                     if (soundanm == 1)
1883                     {
1884                         soundanm++;
1885                         S_PlaySound(PIPEBOMB_EXPLODE);
1886                     }
1887 
1888                     rotatesprite_fs(160<<16, (104)<<16, 60<<10, 0, DUKENUKEM, 0, 0, 2+8);
1889                     rotatesprite_fs(160<<16, (129)<<16, ((int32_t) totalclock - 220)<<11, 0, THREEDEE, 0, 0, 2+8);
1890                 }
1891                 else if (totalclock >= (220+30))
1892                     rotatesprite_fs(160<<16, (129)<<16, 30<<11, 0, THREEDEE, 0, 0, 2+8);
1893 
1894                 if (PLUTOPAK)
1895                 {
1896                     // JBF 20030804
1897                     if (totalclock >= 280 && totalclock < 395)
1898                     {
1899                         rotatesprite_fs(160<<16, (151)<<16, (410-(int32_t) totalclock)<<12, 0, PLUTOPAKSPRITE+1, (sintable[((int32_t) totalclock<<4)&2047]>>11), 0, 2+8);
1900                         if (soundanm == 2)
1901                         {
1902                             soundanm++;
1903                             S_PlaySound(FLY_BY);
1904                         }
1905                     }
1906                     else if (totalclock >= 395)
1907                     {
1908                         if (soundanm == 3)
1909                         {
1910                             soundanm++;
1911                             S_PlaySound(PIPEBOMB_EXPLODE);
1912                         }
1913                         rotatesprite_fs(160<<16, (151)<<16, 30<<11, 0, PLUTOPAKSPRITE+1, (sintable[((int32_t) totalclock<<4)&2047]>>11), 0, 2+8);
1914                     }
1915                 }
1916 
1917                 if (g_restorePalette)
1918                 {
1919                     P_SetGamePalette(g_player[myconnectindex].ps, g_player[myconnectindex].ps->palette, 0);
1920                     g_restorePalette = 0;
1921                 }
1922 
1923                 videoNextPage();
1924             }
1925 
1926             G_HandleAsync();
1927         }
1928 
1929         I_ClearAllInput();
1930     }
1931 
1932     renderFlushPerms();
1933     videoClearScreen(0L);
1934     videoNextPage();
1935 
1936     //g_player[myconnectindex].ps->palette = palette;
1937     P_SetGamePalette(g_player[myconnectindex].ps, BASEPAL, 0);    // JBF 20040308
1938     S_PlaySound(NITEVISION_ONOFF);
1939 
1940     //G_FadePalette(0,0,0,0);
1941     videoClearScreen(0L);
1942 }
1943 
G_DoOrderScreen(void)1944 void G_DoOrderScreen(void)
1945 {
1946     int32_t i;
1947 
1948     videoSetViewableArea(0, 0, xdim-1, ydim-1);
1949 
1950     P_SetGamePalette(g_player[myconnectindex].ps, BASEPAL, 1);    // JBF 20040308
1951 
1952     for (i=0; i<4; i++)
1953     {
1954         fadepal(0, 0, 0, 0, 252, 28);
1955         I_ClearAllInput();
1956         rotatesprite_fs(160<<16, 100<<16, 65536L, 0, ORDERING+i, 0, 0, 2+8+64+BGSTRETCH);
1957         fadepal(0, 0, 0, 252, 0, -28);
1958         while (!I_CheckAllInput())
1959             G_HandleAsync();
1960     }
1961 
1962     I_ClearAllInput();
1963 }
1964 
1965 
G_BonusCutscenes(void)1966 static void G_BonusCutscenes(void)
1967 {
1968     if (RRRA)
1969         return;
1970     if (!(numplayers < 2 && ud.eog && ud.from_bonus == 0))
1971         return;
1972 
1973     if (RR)
1974     {
1975         switch (ud.volume_number)
1976         {
1977         case 0:
1978             videoClearScreen(0L);
1979             videoNextPage();
1980             if (ud.lockout == 0)
1981             {
1982                 Anim_Play("turdmov.anm");
1983                 I_ClearAllInput();
1984                 videoClearScreen(0L);
1985                 videoNextPage();
1986             }
1987             ud.level_number = 0;
1988             ud.volume_number = 1;
1989             ud.eog = 0;
1990             fadepal(0, 0, 0, 0, 252, 4);
1991             I_ClearAllInput();
1992             P_SetGamePalette(g_player[myconnectindex].ps, BASEPAL, 8+2+1);
1993             rotatesprite_fs(0, 0, 65536L, 0, TENSCREEN, 0, 0, 2+8+16+64+128+BGSTRETCH);
1994             videoNextPage();
1995             fadepal(0, 0, 0, 252, 0, -4);
1996             I_ClearAllInput();
1997             G_HandleEventsWhileNoInput();
1998             fadepal(0, 0, 0, 0, 252, 4);
1999             FX_StopAllSounds();
2000             S_ClearSoundLocks();
2001             break;
2002         case 1:
2003             videoClearScreen(0L);
2004             videoNextPage();
2005             if (ud.lockout == 0)
2006             {
2007                 Anim_Play("rr_outro.anm");
2008                 I_ClearAllInput();
2009                 videoClearScreen(0L);
2010                 videoNextPage();
2011             }
2012             g_lastLevel = 0;
2013             g_vixenLevel = 1;
2014             ud.level_number = 0;
2015             ud.volume_number = 0;
2016             fadepal(0, 0, 0, 0, 252, 4);
2017             videoSetViewableArea(0, 0, xdim-1, ydim-1);
2018             I_ClearAllInput();
2019             P_SetGamePalette(g_player[myconnectindex].ps, BASEPAL, 8 + 2 + 1);
2020             rotatesprite_fs(0, 0, 65536L, 0, TENSCREEN, 0, 0, 2 + 8 + 16 + 64 + 128 + BGSTRETCH);
2021             videoNextPage();
2022             fadepal(0, 0, 0, 252, 0, -4);
2023             I_ClearAllInput();
2024             G_HandleEventsWhileNoInput();
2025             fadepal(0, 0, 0, 0, 252, 4);
2026             FX_StopAllSounds();
2027             S_ClearSoundLocks();
2028             break;
2029         }
2030         return;
2031     }
2032 
2033     switch (ud.volume_number)
2034     {
2035     case 0:
2036         if (ud.lockout == 0)
2037         {
2038             int32_t bonuscnt=0;
2039             int32_t const bossmove [] =
2040             {
2041                 0, 120, VICTORY1+3, 86, 59,
2042                 220, 260, VICTORY1+4, 86, 59,
2043                 260, 290, VICTORY1+5, 86, 59,
2044                 290, 320, VICTORY1+6, 86, 59,
2045                 320, 350, VICTORY1+7, 86, 59,
2046                 350, 380, VICTORY1+8, 86, 59,
2047                 350, 380, VICTORY1+8, 86, 59 // duplicate row to alleviate overflow in the for loop below "boss"
2048             };
2049 
2050             P_SetGamePalette(g_player[myconnectindex].ps, ENDINGPAL, 8+2+1); // JBF 20040308
2051             videoClearScreen(0L);
2052             rotatesprite_fs(0, 50<<16, 65536L, 0, VICTORY1, 0, 0, 2+8+16+64+128+BGSTRETCH);
2053             videoNextPage();
2054             fadepal(0, 0, 0, 252, 0, -4);
2055 
2056             I_ClearAllInput();
2057             totalclock = 0;
2058 
2059             while (1)
2060             {
2061                 if (engineFPSLimit())
2062                 {
2063                     videoClearScreen(0L);
2064                     rotatesprite_fs(0, 50<<16, 65536L, 0, VICTORY1, 0, 0, 2+8+16+64+128+BGSTRETCH);
2065 
2066                     // boss
2067                     if (totalclock > 390 && totalclock < 780)
2068                         for (bssize_t t=0; t<35; t+=5) if (bossmove[t+2] && (totalclock%390) > bossmove[t] && (totalclock%390) <= bossmove[t+1])
2069                         {
2070                             if (t==10 && bonuscnt == 1)
2071                             {
2072                                 S_PlaySound(SHOTGUN_FIRE);
2073                                 S_PlaySound(SQUISHED);
2074                                 bonuscnt++;
2075                             }
2076                             rotatesprite_fs(bossmove[t+3]<<16, bossmove[t+4]<<16, 65536L, 0, bossmove[t+2], 0, 0, 2+8+16+64+128+BGSTRETCH);
2077                         }
2078 
2079                     // Breathe
2080                     if (totalclock < 450 || totalclock >= 750)
2081                     {
2082                         int32_t const breathe [] =
2083                         {
2084                             0,  30, VICTORY1+1, 176, 59,
2085                             30,  60, VICTORY1+2, 176, 59,
2086                             60,  90, VICTORY1+1, 176, 59,
2087                             90, 120,          0, 176, 59
2088                         };
2089 
2090                         if (totalclock >= 750)
2091                         {
2092                             rotatesprite_fs(86<<16, 59<<16, 65536L, 0, VICTORY1+8, 0, 0, 2+8+16+64+128+BGSTRETCH);
2093                             if (totalclock >= 750 && bonuscnt == 2)
2094                             {
2095                                 S_PlaySound(DUKETALKTOBOSS);
2096                                 bonuscnt++;
2097                             }
2098 
2099                         }
2100                         for (bssize_t t=0; t<20; t+=5)
2101                             if (breathe[t+2] && (totalclock%120) > breathe[t] && (totalclock%120) <= breathe[t+1])
2102                             {
2103                                 if (t==5 && bonuscnt == 0)
2104                                 {
2105                                     S_PlaySound(BOSSTALKTODUKE);
2106                                     bonuscnt++;
2107                                 }
2108                                 rotatesprite_fs(breathe[t+3]<<16, breathe[t+4]<<16, 65536L, 0, breathe[t+2], 0, 0, 2+8+16+64+128+BGSTRETCH);
2109                             }
2110                     }
2111 
2112                     videoNextPage();
2113                 }
2114 
2115                 G_HandleAsync();
2116 
2117                 if (I_CheckAllInput()) break;
2118             }
2119 
2120             fadepal(0, 0, 0, 0, 252, 4);
2121         }
2122 
2123         I_ClearAllInput();
2124         P_SetGamePalette(g_player[myconnectindex].ps, BASEPAL, 8+2+1);   // JBF 20040308
2125 
2126         rotatesprite_fs(160<<16, 100<<16, 65536L, 0, 3292, 0, 0, 2+8+64+BGSTRETCH);
2127         fadepal(0, 0, 0, 252, 0, -4);
2128         G_HandleEventsWhileNoInput();
2129         fadepal(0, 0, 0, 0, 252, 4);
2130 
2131         S_StopMusic();
2132         FX_StopAllSounds();
2133         S_ClearSoundLocks();
2134         break;
2135 
2136     case 1:
2137         videoSetViewableArea(0, 0, xdim-1, ydim-1);
2138 
2139         S_StopMusic();
2140         videoClearScreen(0L);
2141         videoNextPage();
2142 
2143         if (ud.lockout == 0)
2144         {
2145             fadepal(0, 0, 0, 252, 0, -4);
2146             Anim_Play("cineov2.anm");
2147             I_ClearAllInput();
2148             videoClearScreen(0L);
2149             videoNextPage();
2150 
2151             S_PlaySound(PIPEBOMB_EXPLODE);
2152             fadepal(0, 0, 0, 0, 252, 4);
2153         }
2154 
2155         I_ClearAllInput();
2156         P_SetGamePalette(g_player[myconnectindex].ps, BASEPAL, 8+2+1);   // JBF 20040308
2157         rotatesprite_fs(160<<16, 100<<16, 65536L, 0, 3293, 0, 0, 2+8+64+BGSTRETCH);
2158         fadepal(0, 0, 0, 252, 0, -4);
2159         G_HandleEventsWhileNoInput();
2160         fadepal(0, 0, 0, 0, 252, 4);
2161 
2162         break;
2163 
2164     case 3:
2165         videoSetViewableArea(0, 0, xdim-1, ydim-1);
2166 
2167         S_StopMusic();
2168         videoClearScreen(0L);
2169         videoNextPage();
2170 
2171         if (ud.lockout == 0)
2172         {
2173             fadepal(0, 0, 0, 252, 0, -4);
2174 
2175             I_ClearAllInput();
2176             int t = Anim_Play("vol4e1.anm");
2177             videoClearScreen(0L);
2178             videoNextPage();
2179             if (t)
2180                 goto end_vol4e;
2181 
2182             t = Anim_Play("vol4e2.anm");
2183             videoClearScreen(0L);
2184             videoNextPage();
2185             if (t)
2186                 goto end_vol4e;
2187 
2188             Anim_Play("vol4e3.anm");
2189             videoClearScreen(0L);
2190             videoNextPage();
2191         }
2192 
2193     end_vol4e:
2194         FX_StopAllSounds();
2195         S_ClearSoundLocks();
2196         S_PlaySound(ENDSEQVOL3SND4);
2197         I_ClearAllInput();
2198 
2199         G_FadePalette(0, 0, 0, 0);
2200         P_SetGamePalette(g_player[myconnectindex].ps, BASEPAL, 8+2+1);   // JBF 20040308
2201                                                                          //        G_FadePalette(0,0,0,252);
2202         videoClearScreen(0L);
2203         menutext_center(60, "Thanks to all our");
2204         menutext_center(60+16, "fans for giving");
2205         menutext_center(60+16+16, "us big heads.");
2206         menutext_center(70+16+16+16, "Look for a Duke Nukem 3D");
2207         menutext_center(70+16+16+16+16, "sequel soon.");
2208         videoNextPage();
2209 
2210         fadepal(0, 0, 0, 252, 0, -12);
2211         videoNextPage();
2212         I_ClearAllInput();
2213         G_HandleEventsWhileNoInput();
2214         fadepal(0, 0, 0, 0, 252, 12);
2215 
2216         videoClearScreen(0L);
2217         videoNextPage();
2218 
2219         Anim_Play("DUKETEAM.ANM");
2220 
2221         I_ClearAllInput();
2222         G_HandleEventsWhileNoInput();
2223 
2224         videoClearScreen(0L);
2225         videoNextPage();
2226         G_FadePalette(0, 0, 0, 252);
2227 
2228         FX_StopAllSounds();
2229         S_ClearSoundLocks();
2230         I_ClearAllInput();
2231 
2232         break;
2233 
2234     case 2:
2235         S_StopMusic();
2236         videoClearScreen(0L);
2237         videoNextPage();
2238         if (ud.lockout == 0)
2239         {
2240             fadepal(0, 0, 0, 252, 0, -4);
2241             Anim_Play("cineov3.anm");
2242             I_ClearAllInput();
2243             ototalclock = totalclock+200;
2244             while (totalclock < ototalclock)
2245                 G_HandleAsync();
2246             videoClearScreen(0L);
2247             videoNextPage();
2248 
2249             FX_StopAllSounds();
2250             S_ClearSoundLocks();
2251         }
2252 
2253         Anim_Play("RADLOGO.ANM");
2254 
2255         if (ud.lockout == 0 && !I_CheckAllInput())
2256         {
2257             if (G_PlaySoundWhileNoInput(ENDSEQVOL3SND5)) goto ENDANM;
2258             if (G_PlaySoundWhileNoInput(ENDSEQVOL3SND6)) goto ENDANM;
2259             if (G_PlaySoundWhileNoInput(ENDSEQVOL3SND7)) goto ENDANM;
2260             if (G_PlaySoundWhileNoInput(ENDSEQVOL3SND8)) goto ENDANM;
2261             if (G_PlaySoundWhileNoInput(ENDSEQVOL3SND9)) goto ENDANM;
2262         }
2263 
2264         I_ClearAllInput();
2265 
2266         totalclock = 0;
2267         if (PLUTOPAK)
2268         {
2269             while (totalclock < 120 && !I_CheckAllInput())
2270                 G_HandleAsync();
2271 
2272             I_ClearAllInput();
2273         }
2274         else
2275         {
2276             G_HandleEventsWhileNoInput();
2277         }
2278 
2279     ENDANM:
2280         if (!PLUTOPAK)
2281         {
2282             FX_StopAllSounds();
2283             S_ClearSoundLocks();
2284             S_PlaySound(ENDSEQVOL3SND4);
2285 
2286             videoClearScreen(0L);
2287             videoNextPage();
2288 
2289             Anim_Play("DUKETEAM.ANM");
2290 
2291             I_ClearAllInput();
2292             G_HandleEventsWhileNoInput();
2293 
2294             videoClearScreen(0L);
2295             videoNextPage();
2296             G_FadePalette(0, 0, 0, 252);
2297         }
2298 
2299         I_ClearAllInput();
2300         FX_StopAllSounds();
2301         S_ClearSoundLocks();
2302 
2303         videoClearScreen(0L);
2304 
2305         break;
2306     }
2307 }
2308 
G_DisplayMPResultsScreen(void)2309 static void G_DisplayMPResultsScreen(void)
2310 {
2311     int32_t i, y, t = 0;
2312 
2313     rotatesprite_fs(160<<16, 100<<16, 65536L, 0, MENUSCREEN, 16, 0, 2+8+64+BGSTRETCH);
2314     rotatesprite_fs(160<<16, 34<<16, RR ? 23592L : 65536L, 0, INGAMEDUKETHREEDEE, 0, 0, 10);
2315     if (!RR && PLUTOPAK)   // JBF 20030804
2316         rotatesprite_fs((260)<<16, 36<<16, 65536L, 0, PLUTOPAKSPRITE+2, 0, 0, 2+8);
2317     gametext_center(58+(RR ? 0 : 2), "Multiplayer Totals");
2318     gametext_center(58+10, g_mapInfo[G_LastMapInfoIndex()].name);
2319 
2320     gametext_center_shade(RR ? 175 : 165, "Press any key or button to continue", quotepulseshade);
2321 
2322     minitext(38, 80, "Name", 8, 2+8+16+128);
2323     minitext(269, 80, "Kills", 8, 2+8+16+128);
2324     for (i=0; i<g_mostConcurrentPlayers; i++)
2325     {
2326         Bsprintf(tempbuf, "%-4d", i+1);
2327         minitext(92+(i*23), 80, tempbuf, RR ? 0 : 3, 2+8+16+128);
2328     }
2329 
2330     for (i=0; i<g_mostConcurrentPlayers; i++)
2331     {
2332         int32_t xfragtotal = 0;
2333         Bsprintf(tempbuf, "%d", i+1);
2334 
2335         minitext(30, 90+t, tempbuf, 0, 2+8+16+128);
2336         minitext(38, 90+t, g_player[i].user_name, g_player[i].ps->palookup, 2+8+16+128);
2337 
2338         for (y=0; y<g_mostConcurrentPlayers; y++)
2339         {
2340             if (i == y)
2341             {
2342                 Bsprintf(tempbuf, "%-4d", g_player[y].ps->fraggedself);
2343                 minitext(92+(y*23), 90+t, tempbuf, RR ? 0 : 2, 2+8+16+128);
2344                 xfragtotal -= g_player[y].ps->fraggedself;
2345             }
2346             else
2347             {
2348                 Bsprintf(tempbuf, "%-4d", g_player[i].frags[y]);
2349                 minitext(92+(y*23), 90+t, tempbuf, 0, 2+8+16+128);
2350                 xfragtotal += g_player[i].frags[y];
2351             }
2352         }
2353 
2354         Bsprintf(tempbuf, "%-4d", xfragtotal);
2355         minitext(101+(8*23), 90+t, tempbuf, RR ? 0 : 2, 2+8+16+128);
2356 
2357         t += 7;
2358     }
2359 
2360     for (y=0; y<g_mostConcurrentPlayers; y++)
2361     {
2362         int32_t yfragtotal = 0;
2363         for (i=0; i<g_mostConcurrentPlayers; i++)
2364         {
2365             if (i == y)
2366                 yfragtotal += g_player[i].ps->fraggedself;
2367             else
2368                 yfragtotal += g_player[i].frags[y];
2369         }
2370         Bsprintf(tempbuf, "%-4d", yfragtotal);
2371         minitext(92+(y*23), 96+(8*7), tempbuf, RR ? 0 : 2, 2+8+16+128);
2372     }
2373 
2374     minitext(45, 96+(8*7), "Deaths", RR ? 0 : 8, 2+8+16+128);
2375 }
2376 
G_PrintTime_ClockPad(void)2377 static int32_t G_PrintTime_ClockPad(void)
2378 {
2379     int32_t clockpad = 2;
2380     int32_t ii, ij;
2381 
2382     for (ii=g_player[myconnectindex].ps->player_par/(REALGAMETICSPERSEC*60), ij=1; ii>9; ii/=10, ij++) { }
2383     clockpad = max(clockpad, ij);
2384     if (!(ud.volume_number == 0 && ud.last_level-1 == 7 && boardfilename[0]))
2385     {
2386         for (ii=g_mapInfo[G_LastMapInfoIndex()].partime/(REALGAMETICSPERSEC*60), ij=1; ii>9; ii/=10, ij++) { }
2387         clockpad = max(clockpad, ij);
2388         if (g_mapInfo[G_LastMapInfoIndex()].designertime)
2389         {
2390             for (ii=g_mapInfo[G_LastMapInfoIndex()].designertime/(REALGAMETICSPERSEC*60), ij=1; ii>9; ii/=10, ij++) { }
2391             clockpad = max(clockpad, ij);
2392         }
2393     }
2394     if (ud.playerbest > 0) for (ii=ud.playerbest/(REALGAMETICSPERSEC*60), ij=1; ii>9; ii/=10, ij++) { }
2395     clockpad = max(clockpad, ij);
2396 
2397     return clockpad;
2398 }
2399 
G_PrintTime2(int32_t time)2400 static const char* G_PrintTime2(int32_t time)
2401 {
2402     Bsprintf(tempbuf, RR ? "%0*d : %02d" : "%0*d:%02d", G_PrintTime_ClockPad(), time/(REALGAMETICSPERSEC*60), (time/REALGAMETICSPERSEC)%60);
2403     return tempbuf;
2404 }
G_PrintTime3(int32_t time)2405 static const char* G_PrintTime3(int32_t time)
2406 {
2407     Bsprintf(tempbuf, RR ? "%0*d : %02d . %02d" : "%0*d:%02d.%02d", G_PrintTime_ClockPad(), time/(REALGAMETICSPERSEC*60), (time/REALGAMETICSPERSEC)%60, ((time%REALGAMETICSPERSEC)*33)/10);
2408     return tempbuf;
2409 }
2410 
G_PrintYourTime(void)2411 const char* G_PrintYourTime(void)
2412 {
2413     return G_PrintTime3(g_player[myconnectindex].ps->player_par);
2414 }
G_PrintParTime(void)2415 const char* G_PrintParTime(void)
2416 {
2417     if (ud.last_level < 1)
2418         return "<invalid>";
2419     return G_PrintTime2(g_mapInfo[G_LastMapInfoIndex()].partime);
2420 }
G_PrintDesignerTime(void)2421 const char* G_PrintDesignerTime(void)
2422 {
2423     if (ud.last_level < 1)
2424         return "<invalid>";
2425     return G_PrintTime2(g_mapInfo[G_LastMapInfoIndex()].designertime);
2426 }
G_PrintBestTime(void)2427 const char* G_PrintBestTime(void)
2428 {
2429     return G_PrintTime3(ud.playerbest);
2430 }
2431 
G_BonusScreen(int32_t bonusonly)2432 void G_BonusScreen(int32_t bonusonly)
2433 {
2434     int32_t gfx_offset;
2435     int32_t bonuscnt;
2436     int32_t clockpad = 2;
2437     const char *lastmapname;
2438 
2439     if (REALITY)
2440     {
2441         RT_Bonus();
2442         return;
2443     }
2444 
2445     //if (g_networkMode == NET_DEDICATED_SERVER)
2446     //    return;
2447 
2448     G_UpdateAppTitle();
2449 
2450     if (ud.volume_number == 0 && ud.last_level == 8 && boardfilename[0])
2451     {
2452         lastmapname = Bstrrchr(boardfilename, '\\');
2453         if (!lastmapname) lastmapname = Bstrrchr(boardfilename, '/');
2454         if (!lastmapname) lastmapname = boardfilename;
2455     }
2456     else
2457     {
2458         lastmapname = g_mapInfo[G_LastMapInfoIndex()].name;
2459         if (!lastmapname) // this isn't right but it's better than no name at all
2460             lastmapname = g_mapInfo[G_LastMapInfoIndex()].name;
2461     }
2462 
2463     if (RR)
2464     {
2465         if ((g_lastLevel && ud.volume_number == 2) || g_vixenLevel)
2466             lastmapname = "CLOSE ENCOUNTERS";
2467         else if (g_turdLevel)
2468             lastmapname = "SMELTING PLANT";
2469     }
2470 
2471 
2472     fadepal(0, 0, 0, 0, 252, RR ? 4 : 28);
2473     videoSetViewableArea(0, 0, xdim-1, ydim-1);
2474     videoClearScreen(0L);
2475     videoNextPage();
2476     renderFlushPerms();
2477 
2478     FX_StopAllSounds();
2479     S_ClearSoundLocks();
2480     FX_SetReverb(0L);
2481     CONTROL_BindsEnabled = 1; // so you can use your screenshot bind on the score screens
2482 
2483     if (!bonusonly)
2484         G_BonusCutscenes();
2485 
2486     P_SetGamePalette(g_player[myconnectindex].ps, BASEPAL, 8+2+1);   // JBF 20040308
2487     G_FadePalette(0, 0, 0, 252);   // JBF 20031228
2488     KB_FlushKeyboardQueue();
2489     totalclock = 0;
2490     bonuscnt = 0;
2491 
2492     S_StopMusic();
2493     FX_StopAllSounds();
2494     S_ClearSoundLocks();
2495 
2496     if (g_mostConcurrentPlayers > 1 && (g_gametypeFlags[ud.coop]&GAMETYPE_SCORESHEET))
2497     {
2498         videoClearScreen(0);
2499         G_DisplayMPResultsScreen();
2500 
2501         if (ud.config.MusicToggle)
2502             S_PlaySound(BONUSMUSIC);
2503 
2504         videoNextPage();
2505         I_ClearAllInput();
2506         fadepal(0, 0, 0, 252, 0, RR ? -4 : -28);
2507         totalclock = 0;
2508 
2509         while (totalclock < TICRATE*10)
2510         {
2511             G_HandleAsync();
2512             MUSIC_Update();
2513 
2514             if (engineFPSLimit())
2515             {
2516                 videoClearScreen(0);
2517                 G_DisplayMPResultsScreen();
2518                 videoNextPage();
2519             }
2520 
2521             if (I_CheckAllInput())
2522             {
2523                 I_ClearAllInput();
2524                 break;
2525             }
2526         }
2527 
2528         fadepal(0, 0, 0, 0, 252, RR ? 4 : 28);
2529     }
2530 
2531     if (bonusonly || (g_netServer || ud.multimode > 1)) return;
2532 
2533     if (!RR)
2534     {
2535         gfx_offset = (ud.volume_number==1) ? 5 : 0;
2536         gfx_offset += BONUSSCREEN;
2537         rotatesprite_fs(160<<16, 100<<16, 65536L, 0, gfx_offset, 0, 0, 2+8+64+128+BGSTRETCH);
2538 
2539         if (lastmapname)
2540             menutext_center(20-6, lastmapname);
2541         menutext_center(36-6, "Completed");
2542 
2543         gametext_center_shade(192, "Press any key or button to continue", quotepulseshade);
2544 
2545         if (ud.config.MusicToggle)
2546             S_PlaySound(BONUSMUSIC);
2547     }
2548     else
2549     {
2550         gfx_offset = (ud.volume_number==0) ? RRTILE403 : RRTILE409;
2551         gfx_offset += ud.level_number-1;
2552 
2553         if (g_lastLevel || g_vixenLevel)
2554             gfx_offset = RRTILE409+7;
2555 
2556         if (boardfilename[0])
2557             gfx_offset = RRTILE403;
2558 
2559         rotatesprite_fs(160<<16, 100<<16, 65536L, 0, gfx_offset, 0, 0, 2+8+64+128+BGSTRETCH);
2560         if (lastmapname)
2561             menutext(80,16, lastmapname);
2562 
2563         menutext(15, 192, "Press any key to continue");
2564     }
2565 
2566     videoNextPage();
2567     I_ClearAllInput();
2568     fadepal(0, 0, 0, 252, 0, -4);
2569     bonuscnt = 0;
2570     totalclock = 0;
2571 
2572     do
2573     {
2574         int32_t yy = 0, zz;
2575 
2576         G_HandleAsync();
2577         MUSIC_Update();
2578 
2579         if (engineFPSLimit())
2580         {
2581             if (g_player[myconnectindex].ps->gm&MODE_EOL)
2582             {
2583                 videoClearScreen(0);
2584                 rotatesprite_fs(160<<16, 100<<16, 65536L, 0, gfx_offset, 0, 0, 2+8+64+128+BGSTRETCH);
2585 
2586                 if (totalclock >= 1000000000 && totalclock < 1000000320)
2587                 {
2588                     switch (((int32_t) totalclock>>4)%15)
2589                     {
2590                     case 0:
2591                         if (bonuscnt == 6)
2592                         {
2593                             bonuscnt++;
2594                             S_PlaySound(RR ? 425 : SHOTGUN_COCK);
2595                             switch (rand()&3)
2596                             {
2597                             case 0:
2598                                 S_PlaySound(BONUS_SPEECH1);
2599                                 break;
2600                             case 1:
2601                                 S_PlaySound(BONUS_SPEECH2);
2602                                 break;
2603                             case 2:
2604                                 S_PlaySound(BONUS_SPEECH3);
2605                                 break;
2606                             case 3:
2607                                 S_PlaySound(BONUS_SPEECH4);
2608                                 break;
2609                             }
2610                         }
2611                         fallthrough__;
2612                     case 1:
2613                     case 4:
2614                     case 5:
2615                         if (!RR)
2616                             rotatesprite_fs(199<<16, 31<<16, 65536L, 0, 3+gfx_offset, 0, 0, 2+8+16+64+128+BGSTRETCH);
2617                         break;
2618                     case 2:
2619                     case 3:
2620                         if (!RR)
2621                             rotatesprite_fs(199<<16, 31<<16, 65536L, 0, 4+gfx_offset, 0, 0, 2+8+16+64+128+BGSTRETCH);
2622                         break;
2623                     }
2624                 }
2625                 else if (totalclock > (10240+120L)) break;
2626                 else
2627                 {
2628                     switch (((int32_t) totalclock>>5)&3)
2629                     {
2630                     case 1:
2631                     case 3:
2632                         if (!RR)
2633                             rotatesprite_fs(199<<16, 31<<16, 65536L, 0, 1+gfx_offset, 0, 0, 2+8+16+64+128+BGSTRETCH);
2634                         break;
2635                     case 2:
2636                         if (!RR)
2637                             rotatesprite_fs(199<<16, 31<<16, 65536L, 0, 2+gfx_offset, 0, 0, 2+8+16+64+128+BGSTRETCH);
2638                         break;
2639                     }
2640                 }
2641 
2642                 if (!RR)
2643                 {
2644                     if (lastmapname)
2645                         menutext_center(20-6, lastmapname);
2646                     menutext_center(36-6, "Completed");
2647 
2648                     gametext_center_shade(192, "Press any key or button to continue", quotepulseshade);
2649                 }
2650                 else
2651                 {
2652                     if (lastmapname)
2653                         menutext(80, 16, lastmapname);
2654 
2655                     menutext(15, 192, "Press any key to continue");
2656                 }
2657 
2658                 const int yystep = RR ? 16 : 10;
2659                 if (totalclock > (60*3))
2660                 {
2661                     yy = zz = RR ? 48 : 59;
2662 
2663                     if (!RR)
2664                         gametext(10, yy+9, "Your Time:");
2665                     else
2666                         menutext(30, yy, "Yer Time:");
2667 
2668                     yy+= yystep;
2669                     if (!(ud.volume_number == 0 && ud.last_level-1 == 7 && boardfilename[0]))
2670                     {
2671                         if (g_mapInfo[G_LastMapInfoIndex()].partime)
2672                         {
2673                             if (!RR)
2674                                 gametext(10, yy+9, "Par Time:");
2675                             else
2676                                 menutext(30, yy, "Par Time:");
2677                             yy+=yystep;
2678                         }
2679                         if (g_mapInfo[G_LastMapInfoIndex()].designertime)
2680                         {
2681                             // EDuke 2.0 / NAM source suggests "Green Beret's Time:"
2682                             if (DUKE)
2683                                 gametext(10, yy+9, "3D Realms' Time:");
2684                             else if (RR)
2685                                 menutext(30, yy, "Xatrix Time:");
2686                             yy+=yystep;
2687                         }
2688 
2689                     }
2690                     if (ud.playerbest > 0)
2691                     {
2692                         if (!RR)
2693                             gametext(10, yy+9, (g_player[myconnectindex].ps->player_par > 0 && g_player[myconnectindex].ps->player_par < ud.playerbest) ? "Prev Best Time:" : "Your Best Time:");
2694                         else
2695                             menutext(30, yy, (g_player[myconnectindex].ps->player_par > 0 && g_player[myconnectindex].ps->player_par < ud.playerbest) ? "Prev Best:" : "Yer Best:");
2696                         yy += yystep;
2697                     }
2698 
2699                     if (bonuscnt == 0)
2700                         bonuscnt++;
2701 
2702                     yy = zz;
2703                     if (totalclock >(60*4))
2704                     {
2705                         if (bonuscnt == 1)
2706                         {
2707                             bonuscnt++;
2708                             S_PlaySound(RR ? 404 : PIPEBOMB_EXPLODE);
2709                         }
2710 
2711                         if (g_player[myconnectindex].ps->player_par > 0)
2712                         {
2713                             G_PrintYourTime();
2714                             if (!RR)
2715                             {
2716                                 gametext_number((320>>2)+71, yy+9, tempbuf);
2717                                 if (g_player[myconnectindex].ps->player_par < ud.playerbest)
2718                                     gametext((320>>2)+89+(clockpad*24), yy+9, "New record!");
2719                             }
2720                             else
2721                             {
2722                                 menutext(191, yy, tempbuf);
2723                                 //if (g_player[myconnectindex].ps->player_par < ud.playerbest)
2724                                 //    menutext(191 + 30 + (clockpad*24), yy, "New record!");
2725                             }
2726                         }
2727                         else if (!RR)
2728                             gametext_pal((320>>2)+71, yy+9, "Cheated!", 2);
2729                         else
2730                             menutext(191, yy, "Cheated!");
2731                         yy+=yystep;
2732 
2733                         if (!(ud.volume_number == 0 && ud.last_level-1 == 7 && boardfilename[0]))
2734                         {
2735                             if (g_mapInfo[G_LastMapInfoIndex()].partime)
2736                             {
2737                                 G_PrintParTime();
2738                                 if (!RR)
2739                                     gametext_number((320>>2)+71, yy+9, tempbuf);
2740                                 else
2741                                     menutext(191, yy, tempbuf);
2742                                 yy+=yystep;
2743                             }
2744                             if (g_mapInfo[G_LastMapInfoIndex()].designertime)
2745                             {
2746                                 G_PrintDesignerTime();
2747                                 if (DUKE)
2748                                     gametext_number((320>>2)+71, yy+9, tempbuf);
2749                                 else if (RR)
2750                                     menutext(191, yy, tempbuf);
2751                                 yy+=yystep;
2752                             }
2753                         }
2754 
2755                         if (ud.playerbest > 0)
2756                         {
2757                             G_PrintBestTime();
2758                             if (!RR)
2759                                 gametext_number((320>>2)+71, yy+9, tempbuf);
2760                             else
2761                                 menutext(191, yy, tempbuf);
2762                             yy+=yystep;
2763                         }
2764                     }
2765                 }
2766 
2767                 zz = yy += RR ? 16 : 5;
2768                 if (totalclock > (60*6))
2769                 {
2770                     if (!RR)
2771                         gametext(10, yy+9, "Enemies Killed:");
2772                     else
2773                         menutext(30, yy, "Varmints Killed:");
2774                     yy += yystep;
2775                     if (!RR)
2776                         gametext(10, yy+9, "Enemies Left:");
2777                     else
2778                         menutext(30, yy, "Varmints Left:");
2779                     yy += yystep;
2780 
2781                     if (bonuscnt == 2)
2782                     {
2783                         bonuscnt++;
2784                         if (!RR)
2785                             S_PlaySound(FLY_BY);
2786                     }
2787 
2788                     yy = zz;
2789 
2790                     if (totalclock > (60*7))
2791                     {
2792                         if (bonuscnt == 3)
2793                         {
2794                             bonuscnt++;
2795                             S_PlaySound(RR ? 422 : PIPEBOMB_EXPLODE);
2796                         }
2797                         Bsprintf(tempbuf, "%-3d", g_player[myconnectindex].ps->actors_killed);
2798                         if (!RR)
2799                             gametext_number((320>>2)+70, yy+9, tempbuf);
2800                         else
2801                             menutext(231,yy,tempbuf);
2802                         yy += yystep;
2803                         if (ud.player_skill > 3 && !RR)
2804                         {
2805                             if (!RR)
2806                                 gametext((320>>2)+70, yy+9, "N/A");
2807                             else
2808                                 menutext(231,yy, "N/A");
2809                             yy += yystep;
2810                         }
2811                         else
2812                         {
2813                             if ((g_player[myconnectindex].ps->max_actors_killed-g_player[myconnectindex].ps->actors_killed) < 0)
2814                                 Bsprintf(tempbuf, "%-3d", 0);
2815                             else Bsprintf(tempbuf, "%-3d", g_player[myconnectindex].ps->max_actors_killed-g_player[myconnectindex].ps->actors_killed);
2816                             if (!RR)
2817                                 gametext_number((320>>2)+70, yy+9, tempbuf);
2818                             else
2819                                 menutext(231, yy, tempbuf);
2820                             yy += yystep;
2821                         }
2822                     }
2823                 }
2824 
2825                 zz = yy += RR ? 0 : 5;
2826                 if (totalclock > (60*9))
2827                 {
2828                     if (!RR)
2829                         gametext(10, yy+9, "Secrets Found:");
2830                     else
2831                         menutext(30, yy, "Secrets Found:");
2832                     yy += yystep;
2833                     if (!RR)
2834                         gametext(10, yy+9, "Secrets Missed:");
2835                     else
2836                         menutext(30, yy, "Secrets Missed:");
2837                     yy += yystep;
2838                     if (bonuscnt == 4) bonuscnt++;
2839 
2840                     yy = zz;
2841                     if (totalclock > (60*10))
2842                     {
2843                         if (bonuscnt == 5)
2844                         {
2845                             bonuscnt++;
2846                             S_PlaySound(RR ? 404 : PIPEBOMB_EXPLODE);
2847                         }
2848                         Bsprintf(tempbuf, "%-3d", g_player[myconnectindex].ps->secret_rooms);
2849                         if (!RR)
2850                             gametext_number((320>>2)+70, yy+9, tempbuf);
2851                         else
2852                             menutext(231, yy, tempbuf);
2853                         yy += yystep;
2854 #if 0
2855                         // Always overwritten.
2856                         if (g_player[myconnectindex].ps->secret_rooms > 0)
2857                             Bsprintf(tempbuf, "%-3d%%", (100*g_player[myconnectindex].ps->secret_rooms/g_player[myconnectindex].ps->max_secret_rooms));
2858 #endif
2859                         Bsprintf(tempbuf, "%-3d", g_player[myconnectindex].ps->max_secret_rooms-g_player[myconnectindex].ps->secret_rooms);
2860                         if (!RR)
2861                             gametext_number((320>>2)+70, yy+9, tempbuf);
2862                         else
2863                             menutext(231, yy, tempbuf);
2864                         yy += yystep;
2865                         }
2866                     }
2867 
2868                 if (totalclock > 10240 && totalclock < 10240+10240)
2869                     totalclock = 1024;
2870 
2871                 if (I_CheckAllInput() && totalclock >(60*2)) // JBF 20030809
2872                 {
2873                     I_ClearAllInput();
2874                     if (totalclock < (60*13))
2875                     {
2876                         KB_FlushKeyboardQueue();
2877                         totalclock = (60*13);
2878                     }
2879                     else if (totalclock < 1000000000)
2880                         totalclock = 1000000000;
2881                 }
2882             }
2883             else
2884                 break;
2885 
2886             videoNextPage();
2887         }
2888     } while (1);
2889     if (g_turdLevel)
2890         g_turdLevel = 0;
2891     if (g_vixenLevel)
2892         g_vixenLevel = 0;
2893 }
2894 
G_PlayMapAnim(void)2895 void G_PlayMapAnim(void)
2896 {
2897     const char *animFile;
2898     if (ud.volume_number == 0)
2899     {
2900         switch (ud.level_number)
2901         {
2902             case 1:
2903                 animFile = "lvl1.anm";
2904                 break;
2905             case 2:
2906                 animFile = "lvl2.anm";
2907                 break;
2908             case 3:
2909                 animFile = "lvl3.anm";
2910                 break;
2911             case 4:
2912                 animFile = "lvl4.anm";
2913                 break;
2914             case 5:
2915                 animFile = "lvl5.anm";
2916                 break;
2917             case 6:
2918                 animFile = "lvl6.anm";
2919                 break;
2920             default:
2921                 animFile = "lvl7.anm";
2922                 break;
2923         }
2924     }
2925     else
2926     {
2927         switch (ud.level_number)
2928         {
2929             case 1:
2930                 animFile = "lvl8.anm";
2931                 break;
2932             case 2:
2933                 animFile = "lvl9.anm";
2934                 break;
2935             case 3:
2936                 animFile = "lvl10.anm";
2937                 break;
2938             case 4:
2939                 animFile = "lvl11.anm";
2940                 break;
2941             case 5:
2942                 animFile = "lvl12.anm";
2943                 break;
2944             case 6:
2945                 animFile = "lvl13.anm";
2946                 break;
2947             default:
2948                 animFile = NULL;
2949                 break;
2950         }
2951     }
2952 
2953     if (animFile == NULL)
2954         return;
2955 
2956     Anim_Play(animFile);
2957 }
2958 
G_ShowMapFrame(void)2959 void G_ShowMapFrame(void)
2960 {
2961     int frame = -1;
2962 
2963     if (ud.volume_number == 0)
2964     {
2965         switch (ud.level_number)
2966         {
2967         case 1:
2968             frame = 0;
2969             break;
2970         case 2:
2971             frame = 1;
2972             break;
2973         case 3:
2974             frame = 2;
2975             break;
2976         case 4:
2977             frame = 3;
2978             break;
2979         case 5:
2980             frame = 4;
2981             break;
2982         case 6:
2983             frame = 5;
2984             break;
2985         default:
2986             frame = 6;
2987             break;
2988         }
2989     }
2990     else
2991     {
2992         switch (ud.level_number)
2993         {
2994         case 1:
2995             frame = 7;
2996             break;
2997         case 2:
2998             frame = 8;
2999             break;
3000         case 3:
3001             frame = 9;
3002             break;
3003         case 4:
3004             frame = 10;
3005             break;
3006         case 5:
3007             frame = 11;
3008             break;
3009         case 6:
3010             frame = 12;
3011             break;
3012         default:
3013             frame = -1;
3014             break;
3015         }
3016     }
3017     rotatesprite_fs(160<<16,100<<16,65536L,0,RRTILE8624+frame,0,0,10+64+128);
3018 }
3019 
G_BonusScreenRRRA(int32_t bonusonly)3020 void G_BonusScreenRRRA(int32_t bonusonly)
3021 {
3022     int32_t gfx_offset;
3023     int32_t bonuscnt;
3024     int32_t showMap = 0;
3025     const char *lastmapname;
3026 
3027     //if (g_networkMode == NET_DEDICATED_SERVER)
3028     //    return;
3029 
3030     G_UpdateAppTitle();
3031 
3032     if (ud.volume_number == 0 && ud.last_level == 8 && boardfilename[0])
3033     {
3034         lastmapname = Bstrrchr(boardfilename, '\\');
3035         if (!lastmapname) lastmapname = Bstrrchr(boardfilename, '/');
3036         if (!lastmapname) lastmapname = boardfilename;
3037     }
3038     else
3039     {
3040         lastmapname = g_mapInfo[G_LastMapInfoIndex()].name;
3041         if (!lastmapname) // this isn't right but it's better than no name at all
3042             lastmapname = g_mapInfo[G_LastMapInfoIndex()].name;
3043     }
3044 
3045     if ((g_lastLevel && ud.volume_number == 2) || g_vixenLevel)
3046         lastmapname = "CLOSE ENCOUNTERS";
3047     else if (g_turdLevel)
3048         lastmapname = "SMELTING PLANT";
3049 
3050 
3051     fadepal(0, 0, 0, 0, 252, 4);
3052     videoSetViewableArea(0, 0, xdim-1, ydim-1);
3053     videoClearScreen(0L);
3054     videoNextPage();
3055     renderFlushPerms();
3056 
3057     FX_StopAllSounds();
3058     S_ClearSoundLocks();
3059     FX_SetReverb(0L);
3060     CONTROL_BindsEnabled = 1; // so you can use your screenshot bind on the score screens
3061 
3062     if (boardfilename[0] == 0 && numplayers < 2)
3063     {
3064         if ((ud.eog == 0 || ud.volume_number != 1) && ud.volume_number <= 1)
3065         {
3066             showMap = 1;
3067             MUSIC_StopSong();
3068             KB_FlushKeyboardQueue();
3069 
3070             P_SetGamePalette(g_player[myconnectindex].ps, BASEPAL, 8+2+1);
3071             G_ShowMapFrame();
3072             fadepal(0, 0, 0, 252, 0, -4);
3073             P_SetGamePalette(g_player[myconnectindex].ps, BASEPAL, 8+2+1);
3074         }
3075     }
3076 
3077     if (!bonusonly)
3078         G_BonusCutscenes();
3079 
3080     P_SetGamePalette(g_player[myconnectindex].ps, BASEPAL, 8+2+1);   // JBF 20040308
3081     //G_FadePalette(0, 0, 0, 252);   // JBF 20031228
3082     KB_FlushKeyboardQueue();
3083     totalclock = 0;
3084     bonuscnt = 0;
3085 
3086     S_StopMusic();
3087     FX_StopAllSounds();
3088     S_ClearSoundLocks();
3089 
3090     if (g_mostConcurrentPlayers > 1 && (g_gametypeFlags[ud.coop]&GAMETYPE_SCORESHEET))
3091     {
3092         videoClearScreen(0);
3093         G_DisplayMPResultsScreen();
3094 
3095         if (ud.config.MusicToggle)
3096             S_PlaySound(BONUSMUSIC);
3097 
3098         videoNextPage();
3099         I_ClearAllInput();
3100         fadepal(0, 0, 0, 252, 0, -4);
3101         totalclock = 0;
3102 
3103         while (totalclock < TICRATE*10)
3104         {
3105             G_HandleAsync();
3106             MUSIC_Update();
3107 
3108             if (engineFPSLimit())
3109             {
3110                 videoClearScreen(0);
3111                 G_DisplayMPResultsScreen();
3112                 videoNextPage();
3113             }
3114 
3115             if (I_CheckAllInput())
3116             {
3117                 I_ClearAllInput();
3118                 break;
3119             }
3120         }
3121 
3122         fadepal(0, 0, 0, 0, 252, 4);
3123     }
3124 
3125     if (bonusonly || (g_netServer || ud.multimode > 1)) return;
3126 
3127     gfx_offset = (ud.volume_number==0) ? RRTILE403 : RRTILE409;
3128     gfx_offset += ud.level_number-1;
3129 
3130     if (g_lastLevel || g_vixenLevel)
3131         gfx_offset = RRTILE409+7;
3132 
3133     if (boardfilename[0])
3134         gfx_offset = RRTILE403;
3135 
3136     if (!showMap)
3137         rotatesprite_fs(160<<16, 100<<16, 65536L, 0, gfx_offset, 0, 0, 2+8+64+128+BGSTRETCH);
3138     if (lastmapname)
3139         menutext(80,16, lastmapname);
3140 
3141     menutext(15, 192, "Press any key to continue");
3142 
3143     I_ClearAllInput();
3144     if (!showMap)
3145     {
3146         videoNextPage();
3147         fadepal(0, 0, 0, 252, 0, -4);
3148     }
3149     bonuscnt = 0;
3150     totalclock = 0;
3151 
3152     do
3153     {
3154         int32_t yy = 0, zz;
3155 
3156         G_HandleAsync();
3157         MUSIC_Update();
3158 
3159         if (engineFPSLimit())
3160         {
3161             if (g_player[myconnectindex].ps->gm&MODE_EOL)
3162             {
3163                 videoClearScreen(0);
3164                 if (showMap)
3165                     G_ShowMapFrame();
3166                 else
3167                     rotatesprite_fs(160<<16, 100<<16, 65536L, 0, gfx_offset, 0, 0, 2+8+64+128+BGSTRETCH);
3168 
3169                 if (showMap)
3170                 {
3171                     if (bonuscnt == 7)
3172                     {
3173                         bonuscnt++;
3174                         MUSIC_StopSong();
3175                         G_PlayMapAnim();
3176                         break;
3177                     }
3178                 }
3179 
3180                 if (totalclock >= 1000000000 && totalclock < 1000000320)
3181                 {
3182                     switch (((int32_t) totalclock>>4)%15)
3183                     {
3184                     case 0:
3185                         if (bonuscnt == 6)
3186                         {
3187                             bonuscnt++;
3188                             S_PlaySound(425);
3189                             switch (rand()&3)
3190                             {
3191                             case 0:
3192                                 S_PlaySound(BONUS_SPEECH1);
3193                                 break;
3194                             case 1:
3195                                 S_PlaySound(BONUS_SPEECH2);
3196                                 break;
3197                             case 2:
3198                                 S_PlaySound(BONUS_SPEECH3);
3199                                 break;
3200                             case 3:
3201                                 S_PlaySound(BONUS_SPEECH4);
3202                                 break;
3203                             }
3204                         }
3205                         fallthrough__;
3206                     case 1:
3207                     case 4:
3208                     case 5:
3209                         break;
3210                     case 2:
3211                     case 3:
3212                         break;
3213                     }
3214                 }
3215                 else if (totalclock > (10240+120L)) break;
3216                 else
3217                 {
3218                     switch (((int32_t) totalclock>>5)&3)
3219                     {
3220                     case 1:
3221                     case 3:
3222                         break;
3223                     case 2:
3224                         break;
3225                     }
3226                 }
3227 
3228                 if (lastmapname)
3229                     menutext(80, 16, lastmapname);
3230 
3231                 menutext(15, 192, "Press any key to continue");
3232 
3233                 const int yystep = 16;
3234                 if (totalclock > (60*3))
3235                 {
3236                     yy = zz = 48;
3237 
3238                     menutext(30, yy, "Yer Time:");
3239 
3240                     yy+= yystep;
3241                     if (!(ud.volume_number == 0 && ud.last_level-1 == 7 && boardfilename[0]))
3242                     {
3243                         if (g_mapInfo[G_LastMapInfoIndex()].partime)
3244                         {
3245                             menutext(30, yy, "Par Time:");
3246                             yy+=yystep;
3247                         }
3248                         if (g_mapInfo[G_LastMapInfoIndex()].designertime)
3249                         {
3250                             menutext(30, yy, "Xatrix Time:");
3251                             yy+=yystep;
3252                         }
3253 
3254                     }
3255                     if (ud.playerbest > 0)
3256                     {
3257                         menutext(30, yy, (g_player[myconnectindex].ps->player_par > 0 && g_player[myconnectindex].ps->player_par < ud.playerbest) ? "Prev Best:" : "Yer Best:");
3258                         yy += yystep;
3259                     }
3260 
3261                     if (bonuscnt == 0)
3262                         bonuscnt++;
3263 
3264                     yy = zz;
3265                     if (totalclock >(60*4))
3266                     {
3267                         if (bonuscnt == 1)
3268                         {
3269                             bonuscnt++;
3270                             S_PlaySound(404);
3271                         }
3272 
3273                         if (g_player[myconnectindex].ps->player_par > 0)
3274                         {
3275                             G_PrintYourTime();
3276                             menutext(191, yy, tempbuf);
3277                             //if (g_player[myconnectindex].ps->player_par < ud.playerbest)
3278                             //    menutext(191 + 30 + (clockpad*24), yy, "New record!");
3279                         }
3280                         else
3281                             menutext(191, yy, "Cheated!");
3282                         yy+=yystep;
3283 
3284                         if (!(ud.volume_number == 0 && ud.last_level-1 == 7 && boardfilename[0]))
3285                         {
3286                             if (g_mapInfo[G_LastMapInfoIndex()].partime)
3287                             {
3288                                 G_PrintParTime();
3289                                 menutext(191, yy, tempbuf);
3290                                 yy+=yystep;
3291                             }
3292                             if (g_mapInfo[G_LastMapInfoIndex()].designertime)
3293                             {
3294                                 G_PrintDesignerTime();
3295                                 menutext(191, yy, tempbuf);
3296                                 yy+=yystep;
3297                             }
3298                         }
3299 
3300                         if (ud.playerbest > 0)
3301                         {
3302                             G_PrintBestTime();
3303                             menutext(191, yy, tempbuf);
3304                             yy+=yystep;
3305                         }
3306                     }
3307                 }
3308 
3309                 zz = yy += 16;
3310                 if (totalclock > (60*6))
3311                 {
3312                     menutext(30, yy, "Varmints Killed:");
3313                     yy += yystep;
3314                     menutext(30, yy, "Varmints Left:");
3315                     yy += yystep;
3316 
3317                     if (bonuscnt == 2)
3318                         bonuscnt++;
3319 
3320                     yy = zz;
3321 
3322                     if (totalclock > (60*7))
3323                     {
3324                         if (bonuscnt == 3)
3325                         {
3326                             bonuscnt++;
3327                             S_PlaySound(422);
3328                         }
3329                         Bsprintf(tempbuf, "%-3d", g_player[myconnectindex].ps->actors_killed);
3330                         menutext(231,yy,tempbuf);
3331                         yy += yystep;
3332                         //if (ud.player_skill > 3)
3333                         //{
3334                         //    menutext(231,yy, "N/A");
3335                         //    yy += yystep;
3336                         //}
3337                         //else
3338                         {
3339                             if ((g_player[myconnectindex].ps->max_actors_killed-g_player[myconnectindex].ps->actors_killed) < 0)
3340                                 Bsprintf(tempbuf, "%-3d", 0);
3341                             else Bsprintf(tempbuf, "%-3d", g_player[myconnectindex].ps->max_actors_killed-g_player[myconnectindex].ps->actors_killed);
3342                             menutext(231, yy, tempbuf);
3343                             yy += yystep;
3344                         }
3345                     }
3346                 }
3347 
3348                 zz = yy += 0;
3349                 if (totalclock > (60*9))
3350                 {
3351                     menutext(30, yy, "Secrets Found:");
3352                     yy += yystep;
3353                     menutext(30, yy, "Secrets Missed:");
3354                     yy += yystep;
3355                     if (bonuscnt == 4) bonuscnt++;
3356 
3357                     yy = zz;
3358                     if (totalclock > (60*10))
3359                     {
3360                         if (bonuscnt == 5)
3361                         {
3362                             bonuscnt++;
3363                             S_PlaySound(404);
3364                         }
3365                         Bsprintf(tempbuf, "%-3d", g_player[myconnectindex].ps->secret_rooms);
3366                         menutext(231, yy, tempbuf);
3367                         yy += yystep;
3368 #if 0
3369                         // Always overwritten.
3370                         if (g_player[myconnectindex].ps->secret_rooms > 0)
3371                             Bsprintf(tempbuf, "%-3d%%", (100*g_player[myconnectindex].ps->secret_rooms/g_player[myconnectindex].ps->max_secret_rooms));
3372 #endif
3373                         Bsprintf(tempbuf, "%-3d", g_player[myconnectindex].ps->max_secret_rooms-g_player[myconnectindex].ps->secret_rooms);
3374                         menutext(231, yy, tempbuf);
3375                         yy += yystep;
3376                         }
3377                     }
3378 
3379                 if (totalclock > 10240 && totalclock < 10240+10240)
3380                     totalclock = 1024;
3381 
3382                 if (I_CheckAllInput() && totalclock >(60*2)) // JBF 20030809
3383                 {
3384                     I_ClearAllInput();
3385 
3386                     if (totalclock < (60*13))
3387                     {
3388                         KB_FlushKeyboardQueue();
3389                         totalclock = (60*13);
3390                     }
3391                     else if (totalclock < 1000000000)
3392                         totalclock = 1000000000;
3393                 }
3394             }
3395             else
3396                 break;
3397             videoNextPage();
3398         }
3399     } while (1);
3400     if (ud.eog)
3401     {
3402         fadepal(0, 0, 0, 0, 252, 4);
3403         videoClearScreen(0L);
3404         videoNextPage();
3405         S_PlaySound(35);
3406         G_FadePalette(0, 0, 0, 0);
3407         P_SetGamePalette(g_player[myconnectindex].ps, BASEPAL, 8+2+1);
3408         while (1)
3409         {
3410             switch (((int32_t) totalclock >> 4) & 1)
3411             {
3412             case 0:
3413                 rotatesprite(0,0,65536,0,RRTILE8677,0,0,2+8+16+64+128,0,0,xdim-1,ydim-1);
3414                 videoNextPage();
3415                 G_FadePalette(0, 0, 0, 0);
3416                 P_SetGamePalette(g_player[myconnectindex].ps, BASEPAL, 8+2+1);
3417                 Net_GetPackets();
3418                 break;
3419             case 1:
3420                 rotatesprite(0,0,65536,0,RRTILE8677+1,0,0,2+8+16+64+128,0,0,xdim-1,ydim-1);
3421                 videoNextPage();
3422                 G_FadePalette(0, 0, 0, 0);
3423                 P_SetGamePalette(g_player[myconnectindex].ps, BASEPAL, 8+2+1);
3424                 Net_GetPackets();
3425                 break;
3426             }
3427             S_Cleanup();
3428             if (!S_CheckSoundPlaying(-1,35)) break;
3429             if (I_CheckAllInput())
3430             {
3431                 I_ClearAllInput();
3432                 S_StopSound(35);
3433                 break;
3434             }
3435         }
3436     }
3437     if (g_RAendEpisode)
3438     {
3439         g_RAendEpisode = 0;
3440         ud.m_volume_number = ud.volume_number = 1;
3441         ud.m_level_number = ud.level_number = 0;
3442         ud.eog = 0;
3443     }
3444     if (g_turdLevel)
3445         g_turdLevel = 0;
3446     if (g_vixenLevel)
3447         g_vixenLevel = 0;
3448 }
3449 
3450