1 /*
2
3 Copyright (C) 2015-2018 Night Dive Studios, LLC.
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 */
19 /*
20 * $Source: u://RCS/gamerend.c $
21 * $Revision: 1.77 $
22 * $Author: xemu $
23 * $Date: 1994/11/25 08:22:19 $
24 */
25
26 #define __GAMEREND_SRC
27
28 #include <stdlib.h>
29
30 #include "tools.h"
31
32 #include "cyber.h"
33 #include "gamerend.h"
34 #include "weapons.h"
35 #include "colors.h"
36 #include "rcolors.h"
37 #include "cybstrng.h" // for resurrect text
38 #include "gamestrn.h"
39 #include "citres.h"
40 #include "gamescr.h"
41 #include "mainloop.h"
42 #include "game_screen.h"
43 #include "player.h"
44 #include "shodan.h"
45 #include "criterr.h"
46
47 #include "cit2d.h"
48 #include "diffq.h" // for time limit
49 #include "newmfd.h"
50 #include "fullscrn.h"
51
52 #include "grenades.h"
53 #include "hud.h"
54 #include "hand.h"
55 #include "wares.h"
56 #include "rendfx.h"
57 #include "hudobj.h" // for beam effect following
58
59 // maybe we can not have this
60 #include "frtypes.h" // has to be before frprotox so proto gets the context for real
61 #include "frprotox.h"
62 #include "frflags.h"
63 #include "gr2ss.h"
64
65 #include "faketime.h"
66 #include "hkeyfunc.h"
67
68 #include "status.h"
69 #include "statics.h"
70
71 #ifdef AUDIOLOGS
72 #include "audiolog.h"
73 #endif
74
75 extern uchar tmap_big_buffer[];
76
77 // prototypes
78 void set_shield_raisage(uchar going_up);
79 void begin_shodan_conquer_fx(uchar begin);
80 void set_dmg_percentage(int which, ubyte percent);
81 void do_secret_fx(void);
82 void gamesys_render_effects(void);
83 uchar use_ir_hack(void);
84 void draw_single_static_line(uchar *line_base, int lx, int rx, int c_base);
85 void draw_line_static(grs_bitmap *stat_dest, int dens1, int color1);
86 void draw_full_static(grs_bitmap *stat_dest, int c_base);
87 uchar gamesys_draw_func(void *fake_dest_canvas, void *fake_dest_bm, int x, int y, int flags);
88 void gamesys_render_func(void *fake_dest_bitmap, int flags);
89
gamerend_init(void)90 errtype gamerend_init(void) {
91 handart_show = 1;
92 return (OK);
93 }
94
95 // note these are now 0-255, like all computer percentages should be...
96 static ubyte fr_sfx_color;
97 static ubyte dmg_percentage;
98 static char shield_raisage;
99
set_shield_raisage(uchar going_up)100 void set_shield_raisage(uchar going_up) {
101 if (going_up)
102 shield_raisage = 1;
103 else
104 shield_raisage = -15;
105 fr_global_mod_flag(FR_SFX_SHIELD, FR_SFX_MASK);
106 }
107
begin_shodan_conquer_fx(uchar begin)108 void begin_shodan_conquer_fx(uchar begin) {
109 if (begin)
110 fr_global_mod_flag(FR_OVERLAY_SHODAN, FR_OVERLAY_MASK);
111 else
112 fr_global_mod_flag(0, FR_OVERLAY_SHODAN);
113 }
114
115 uchar color_base[] = {BLUE_8_BASE, RED_8_BASE, GREEN_8_BASE};
116
117 #define MIN_STATIC 10
118
set_dmg_percentage(int which,ubyte percent)119 void set_dmg_percentage(int which, ubyte percent) {
120 if (percent > dmg_percentage) {
121 fr_sfx_color = color_base[which];
122 dmg_percentage = percent;
123 if (dmg_percentage < MIN_STATIC)
124 dmg_percentage = MIN_STATIC;
125 fr_global_mod_flag(FR_SFX_STATIC, FR_SFX_MASK);
126 }
127 }
128
129 // -----------------------------------------------
130 // beam_effect_update()
131 //
132
133 extern ObjID beam_effect_id;
134
135 #define PRE_FINAL_DEATH 0x1A
136 #define DYING_FRAMES 0x20
137 #define REBORN_VISION_TICK 0x10
138 #define REBORN_FRAMES 0x18
139 #define FAKEWIN_FRAMES 0x30
140
141 #define FAKEWIN_NUM_FONT RES_bigLEDFont
142 #define FAKEWIN_TEXT_FONT RES_readingFont
143 #define FAKEWIN_EMAIL_MUNGE 0x01c
144 #define FAKEWIN_PAPER 0x8
145 #define FAKEWIN_STRING_BASE REF_STR_fakewinStrings
146
147 extern uchar kill_player(void);
148
149 // about a quarter second, really
150 #define V_CLOCK 0x040
151 #define V_MASK (~0x03f)
152
153 #define build_systems_y_coor(i) (5 + (14 * i))
154
155 static uchar systems_line_colors[] = {RED_8_BASE, RED_8_BASE + 3, ORANGE_8_BASE, ORANGE_8_BASE + 3, GREEN_8_BASE};
156
157 //#define NUM_SYS_LINES ((sizeof(systems_lines)/sizeof(systems_lines[0])))
158 // There is probably a clever way to get this out of the resource, but this is much simpler...
159 #define NUM_SYS_LINES 5
160 #define SYSTEM_BASE REF_STR_ResurrectBase
161 #define LINE_BUF_SIZE 40
162
163 #define STATUS_CHI_AMP 8
164
165 #define CURRENT_VIEW_W (_current_view->r->lr.x - _current_view->r->ul.x)
166 #define CURRENT_VIEW_H (_current_view->r->lr.y - _current_view->r->ul.y)
167
168 extern uchar flatline_heart;
169 extern uchar chi_amp;
170
171 extern void regenerate_player(void);
172 ulong secret_sfx_time;
do_secret_fx(void)173 void do_secret_fx(void) { // boy is this a hack....
174 static char dot_buf[] = "........";
175 static char tmp_buf[] = "99";
176 static grs_font *fx_font = NULL;
177 static long sfx_time = 0;
178 int c_val = secret_render_fx & VAL_REND_SFX, i, cap;
179 char line_buf[LINE_BUF_SIZE];
180 Ref str;
181
182 if (fx_font == NULL)
183 fx_font = ResLock(RES_mfdFont);
184 switch (secret_render_fx & TYPE_REND_SFX) {
185 case DYING_REND_SFX: // chevron drain, perhaps dim out, view rock at end.....
186 secret_render_fx++;
187 flatline_heart = TRUE;
188 chi_amp = STATUS_CHI_AMP * (DYING_FRAMES - c_val) / DYING_FRAMES;
189 if (c_val == DYING_FRAMES) {
190 if (kill_player()) {
191 secret_render_fx = 0;
192 player_struct.dead = FALSE;
193 flatline_heart = FALSE;
194 chi_amp = STATUS_CHI_AMP;
195 } else {
196 secret_render_fx = REBORN_REND_SFX;
197 fr_global_mod_flag(FR_SOLIDFR_SLDKEEP, FR_SOLIDFR_MASK | FR_SFX_MASK);
198 fr_solidfr_color = 0xff;
199 dmg_percentage = 0;
200 regenerate_player();
201 }
202 } else {
203 if (c_val >= PRE_FINAL_DEATH)
204 fr_global_mod_flag(FR_SOLIDFR_STATIC, FR_SOLIDFR_MASK);
205 dmg_percentage = 20 + (c_val << 2);
206 fr_global_mod_flag(FR_SFX_STATIC, FR_SFX_MASK);
207 }
208 break;
209 case REBORN_REND_SFX: // add chevron growth, lighting and dimming, starting on back...
210 gr_set_font(fx_font);
211 cap = c_val >> 2;
212 if (cap >= NUM_SYS_LINES)
213 cap = NUM_SYS_LINES;
214 for (i = 0; i < cap; i++) {
215 gr_set_fcolor(systems_line_colors[i]);
216 ss_string(dot_buf, 30, build_systems_y_coor(i));
217 ss_string(get_string(str = (SYSTEM_BASE + i), line_buf, LINE_BUF_SIZE), 56, build_systems_y_coor(i));
218 }
219 if (str == REF_STR_StartHeartString)
220 flatline_heart = FALSE;
221 else if (str == REF_STR_StartBrainString)
222 chi_amp = STATUS_CHI_AMP;
223 if (c_val < REBORN_VISION_TICK) {
224 gr_set_fcolor(systems_line_colors[i]);
225 dot_buf[c_val & 7] = '\0';
226 ss_string(dot_buf, 30, build_systems_y_coor(i));
227 dot_buf[c_val & 7] = '.';
228 }
229
230 if (*tmd_ticks - sfx_time > V_CLOCK) {
231 secret_render_fx++;
232 if (c_val == REBORN_FRAMES) {
233 extern errtype spoof_mouse_event(void);
234 extern uchar music_on;
235 secret_render_fx = 0;
236
237 // look - we should say the player is no longer dead!
238 player_struct.dead = FALSE;
239 uiFlush();
240 // KLC spoof_mouse_event();
241 if (music_on)
242 start_music();
243 break;
244 } else if (c_val == REBORN_VISION_TICK)
245 fr_global_mod_flag(0, FR_SOLIDFR_MASK);
246
247 sfx_time = (*tmd_ticks) & V_MASK;
248 }
249 break;
250 case TIMELIMIT_REND_SFX: {
251 grs_font *f;
252 short w, h;
253 int stage = (MISSION_3_TICKS - player_struct.game_time) / CIT_CYCLE;
254
255 tmp_buf[0] = tmp_buf[1] = '0';
256 f = ResLock(FAKEWIN_NUM_FONT);
257 gr_set_font(f);
258 gr_string_size(tmp_buf, &w, &h);
259
260 if (stage < 0 || stage > 99)
261 stage = 0;
262 tmp_buf[0] = '0' + stage / 10;
263 tmp_buf[1] = '0' + stage % 10;
264 draw_shadowed_string(tmp_buf, (CURRENT_VIEW_W - w) / 2, (CURRENT_VIEW_H - h) / 2, TRUE);
265 ResUnlock(FAKEWIN_NUM_FONT);
266 break;
267 }
268 case FAKEWIN_REND_SFX: // do stuff
269 {
270 char stage = (*tmd_ticks - secret_sfx_time) / CIT_CYCLE;
271 gr_set_fcolor(RED_BASE + 6);
272 if (stage < 2)
273 break;
274 if (stage < 5) {
275 res_draw_string(FAKEWIN_TEXT_FONT, FAKEWIN_STRING_BASE, 30, 20);
276 res_draw_string(FAKEWIN_TEXT_FONT, FAKEWIN_STRING_BASE + 1, 50, 45);
277 break;
278 }
279 if (stage < 18) {
280 if ((stage > 10) && (c_val == 0)) {
281 fr_global_mod_flag(FR_SFX_SHAKE, FR_SFX_MASK);
282 secret_render_fx++;
283 }
284 res_draw_string(FAKEWIN_TEXT_FONT, FAKEWIN_STRING_BASE + 2, 50, 30);
285 tmp_buf[0] = '0' + ((20 - stage) / 10);
286 tmp_buf[1] = '0' + ((20 - stage) % 10);
287 res_draw_text(FAKEWIN_NUM_FONT, tmp_buf, 85, 45);
288 res_draw_string(FAKEWIN_TEXT_FONT, FAKEWIN_STRING_BASE + 3, 95, 80);
289 break;
290 }
291 if (stage < 22) {
292 if (c_val == 1) {
293 extern void long_bark(ObjID speaker_id, uchar mug_id, int string_id, ubyte color);
294 extern void add_email_datamunge(short mung, uchar select);
295 extern void read_email(Id new_base, int num);
296 fr_global_mod_flag(FR_SFX_SHAKE, FR_SFX_MASK);
297 long_bark(OBJ_NULL, FIRST_SHODAN_MUG + 3, REF_STR_Null, 0);
298 mfd_change_slot(MFD_LEFT, MFD_INFO_SLOT);
299 mfd_change_slot(MFD_RIGHT, MFD_INFO_SLOT);
300 // KLC-duplicate mail add_email_datamunge(FAKEWIN_EMAIL_MUNGE, FALSE);
301 #ifdef AUDIOLOGS
302 if (audiolog_setting)
303 audiolog_play(FAKEWIN_EMAIL_MUNGE);
304 if (audiolog_setting != 1)
305 #endif
306 read_email(RES_paper0, FAKEWIN_PAPER);
307 fr_global_mod_flag(0, FR_SFX_MASK);
308 secret_render_fx++;
309 }
310 gr_set_fcolor(RED_BASE + 6);
311 res_draw_string(FAKEWIN_TEXT_FONT, FAKEWIN_STRING_BASE + 4, 75, 50);
312 break;
313 } else {
314 secret_render_fx = 0;
315 }
316 } break;
317 }
318 if (secret_render_fx == 0) // why must we unset both
319 {
320 ResUnlock(RES_mfdFont);
321 fx_font = NULL;
322 chg_unset_sta(GL_CHG_2);
323 chg_unset_flg(GL_CHG_2);
324 }
325 }
326
327 extern short mouse_attack_x;
328 extern short mouse_attack_y;
329 extern ulong next_fire_time;
330 extern uchar overload_beam;
331 extern uchar saveload_static;
332 extern bool DoubleSize;
333
334 byte beam_offset[NUM_BEAM_GUN] = {-12, -8, -4};
335 #define DRAW_BEAM_LINE(c1, c2, c3, c4) \
336 { \
337 a = mx + (c1); \
338 b = my + (c2); \
339 ss_point_convert(&a, &b, TRUE); \
340 ss_thick_fix_line(fix_make(a, 0), fix_make(b, 0), fix_make(deltax + (c3) + boff + beamx, 0), \
341 fix_make(deltay + (c4) + boff + 6, 0)); \
342 }
343
344 /*
345 #define DRAW_BEAM_LINE(c1,c2,c3,c4) { \
346 a = mx+(c1);\
347 b = my+(c2);\
348 if (DoubleSize) \
349 gr_fix_line(fix_make(a,0),fix_make(b,0),fix_make(deltax+(c3)+boff,0), fix_make(deltay+22,0));\
350 else \
351 { \
352 ss_point_convert(&a,&b,TRUE);\
353 ss_thick_fix_line(fix_make(a,0),fix_make(b,0),fix_make(deltax+(c3)+boff,0),fix_make(deltay+(c4)+boff,0));\
354 } \
355 }
356 */
357
gamesys_render_effects(void)358 void gamesys_render_effects(void) {
359 Ref temp;
360 int deltax, deltay, beamx;
361 short mx, my;
362 extern uchar full_game_3d;
363
364 TRACE("%s: gamerend", __FUNCTION__);
365
366 if ((!global_fullmap->cyber) && (!secret_render_fx)) {
367 ubyte active = player_struct.actives[ACTIVE_WEAPON];
368 extern uchar hack_takeover;
369 extern ulong player_death_time;
370
371 // check to make sure we have an active weapon before drawing handart
372 if ((player_struct.weapons[active].type != EMPTY_WEAPON_SLOT) && !hack_takeover && !saveload_static) {
373 // For hand-to-hand weapons, draw them in the center of the screen.
374 if (player_struct.weapons[active].type == GUN_SUBCLASS_HANDTOHAND) {
375 mx = (SCREEN_VIEW_WIDTH / 2) + SCREEN_VIEW_X;
376 my = (SCREEN_VIEW_Y);
377 ss_point_convert(&mx, &my, TRUE);
378 } else if (handart_show != 1) // Use mouse position for other weapons
379 {
380 mx = mouse_attack_x;
381 my = mouse_attack_y;
382 if (!DoubleSize)
383 ss_point_convert(&mx, &my, TRUE);
384 else
385 ui_mouse_get_xy(&mx, &my);
386 } else // Not showing a weapon
387 {
388 ui_mouse_get_xy(&mx, &my);
389 }
390
391 // Get the weapon art to draw.
392 temp = get_handart(&deltax, &deltay, &beamx, mx, my);
393 if (temp != ID_NULL) {
394 extern uchar ready_to_draw_handart(void);
395
396 if (handart_show != 1) // are we showing an attack frame?
397 {
398 // If this is a beam weapon, we need to draw the beam during attack.
399 if (player_struct.weapons[active].type == GUN_SUBCLASS_BEAM) {
400 short base_color = (overload_beam) ? BLUE_BASE : TURQUOISE_BASE;
401 byte boff = beam_offset[player_struct.weapons[active].subtype];
402
403 if (beam_effect_id) {
404 int i;
405 uchar draw_beam = FALSE;
406
407 for (i = 0; i < current_num_hudobjs; i++) {
408 struct _hudobj_data *dat = &hudobj_vec[i];
409 if ((dat->id == beam_effect_id) && beam_effect_id) {
410 mx = (dat->xl + dat->xh) / 2;
411 my = (dat->yl + dat->yh) / 2;
412 if (DoubleSize) {
413 mx *= 2;
414 my *= 2;
415 }
416 draw_beam = TRUE;
417 }
418 }
419 if (draw_beam) {
420 short a, b;
421
422 gr_set_fcolor(base_color + 5);
423 if (overload_beam) {
424 DRAW_BEAM_LINE(-2, 0, 17, 12);
425 gr_set_fcolor(base_color + 1);
426 }
427 DRAW_BEAM_LINE(-1, 0, 18, 12);
428 gr_set_fcolor(base_color + 1);
429 DRAW_BEAM_LINE(0, 0, 19, 12);
430 if (!overload_beam)
431 gr_set_fcolor(base_color + 5);
432 DRAW_BEAM_LINE(1, 0, 20, 12);
433
434 if (overload_beam) {
435 gr_set_fcolor(base_color + 5);
436 DRAW_BEAM_LINE(2, 0, 21, 12);
437 }
438 }
439 }
440 }
441 }
442 if ((handart_show != 1) || ready_to_draw_handart()) {
443 // draw_hires_resource_bm(temp, SCONV_X(deltax), SCONV_Y(deltay));
444 draw_res_bm(temp, deltax, deltay);
445 notify_draw_handart();
446 }
447 }
448 }
449 }
450
451 // Redraw hud displays as appropriate
452 // HOW ABOUT A FLAG HERE, NOT HARDCODED LOOP NUMBERS
453 if (!secret_render_fx && _current_loop <= FULLSCREEN_LOOP) {
454 hud_update(FALSE, _current_fr_context);
455 }
456
457 if (secret_render_fx)
458 do_secret_fx();
459
460 // draw the gamescreen border
461 if (!full_game_3d) {
462 // was draw_hires_resource_bm
463 draw_res_bm(REF_IMG_bm3dBackground1, 0, -2);
464 draw_res_bm(REF_IMG_bm3dBackground2, 226, -1);
465 draw_res_bm(REF_IMG_bm3dBackground2, 270, -1);
466 draw_res_bm(REF_IMG_bm3dBackground3, 522, -2);
467 draw_res_bm(REF_IMG_bm3dBackground4, 0, 197);
468
469 // whoop whoop whoop!
470 // hack alert! hack alert!
471 if (convert_use_mode == 3) {
472 draw_res_bm(REF_IMG_bm3dBackground5, 27, 257);
473 draw_res_bm(REF_IMG_bm3dBackground6, 415, 257);
474 }
475 } else
476 fullscreen_overlay();
477 }
478
use_ir_hack(void)479 uchar use_ir_hack(void) { return (WareActive(player_struct.hardwarez_status[HARDWARE_GOGGLE_INFRARED])); }
480
481 //#pragma aux c_ror_by_5 = "ror eax,5" parm [eax] modify exact [eax];
482
483 // stolen from RND.LIB, without shift gruesomeness...
484 #define LC16_MULT 2053
485 #define LC16_ADD 13849
486
draw_single_static_line(uchar * line_base,int lx,int rx,int c_base)487 void draw_single_static_line(uchar *line_base, int lx, int rx, int c_base) {
488 uchar *cur_pix;
489 int our_seed = rand();
490 for (cur_pix = line_base + lx; lx < rx; lx++, cur_pix++) {
491 #ifdef SIMPLE_LC_WAY
492 our_seed = (our_seed * LC16_MULT) + LC16_ADD;
493 if (our_seed & 0x300) // 3/4 are colored
494 *cur_pix = c_base + (our_seed & 0x7);
495 else // 1/4 black
496 *cur_pix = 0;
497 #else
498 if (our_seed & 0x300) {
499 *cur_pix = c_base + (our_seed & 0x7);
500 our_seed += (long)cur_pix;
501 our_seed = ((our_seed >> 5) & 0x07ffffff) | (our_seed << 27); //ror by 5
502 } else {
503 *cur_pix = 0;
504 our_seed += (our_seed * LC16_MULT) + LC16_ADD;
505 }
506 // { *cur_pix=0; our_seed+=rand(); }
507 #endif
508 }
509 }
510
511 #define LAST_INITIAL 32
512 // probably have to split it up, and then have a static pass and a translucency pass...
draw_line_static(grs_bitmap * stat_dest,int dens1,int color1)513 void draw_line_static(grs_bitmap *stat_dest, int dens1, int color1) {
514 int y, last = 0, lx, rx, cwid = stat_dest->w;
515 uchar *line_base;
516
517 dens1 >>= 1;
518 for (line_base = stat_dest->bits, y = 0; y < stat_dest->h; y++, line_base += stat_dest->row) {
519 if ((last == LAST_INITIAL) || ((rand() & 0xff) < (dens1 + last))) {
520 lx = (rand() & 0xff) - 0x80;
521 if (lx > cwid)
522 lx = cwid - (lx & 0x1f);
523 if (lx < 0)
524 lx = 0;
525 rx = (rand() & 0xff) - 0x80;
526 if (rx > cwid)
527 rx = cwid - (rx & 0x1f);
528 if (rx < 0)
529 rx = 0;
530 rx = cwid - rx;
531 if (rx < lx) {
532 if (cwid - lx > rx)
533 lx = 0;
534 else {
535 lx = rx;
536 rx = cwid;
537 } // gnosis move
538 }
539 draw_single_static_line(line_base, lx, rx, color1);
540 if (last == 0)
541 last = LAST_INITIAL;
542 else if (last > 1)
543 last >>= 1; // decay repeat freq, stop at 1
544 } else
545 last = 0;
546 }
547 }
548
draw_full_static(grs_bitmap * stat_dest,int c_base)549 void draw_full_static(
550 grs_bitmap *stat_dest,
551 int c_base) { // note we do this as a for, not a big fill, so it will work with row hacks, full screen, so on....
552 uchar *line_base;
553 int y;
554
555 for (line_base = stat_dest->bits, y = 0; y < stat_dest->h; y++, line_base += stat_dest->row)
556 draw_single_static_line(line_base, 0, stat_dest->w, c_base);
557 }
558
559 #define TELEPORT_COLOR 0x1C
560 #define VHOLD_SHIFT_AMOUNT 7
561 short vhold_shift = 0;
562
563 #define FULL_CONVERT_X
564
565 // returns whether to send the bitmap out in the render
gamesys_draw_func(void * fake_dest_canvas,void * fake_dest_bm,int x,int y,int flags)566 uchar gamesys_draw_func(void *fake_dest_canvas, void *fake_dest_bm, int x, int y, int flags) {
567 extern void hud_do_objs(short xtop, short ytop, short xwid, short ywid, uchar rev);
568 grs_canvas *dest_canvas = (grs_canvas *)fake_dest_canvas;
569 grs_bitmap *dest_bm = (grs_bitmap *)fake_dest_bm;
570 uchar *orig_bits;
571 int orig_h, loop, orig_w;
572
573 TRACE("%s: gamerend", __FUNCTION__);
574
575 if (flags & FR_WINDOWD_MASK)
576 gamesys_render_effects(); // static gets drawn over window dressing due to this
577 else
578 hud_do_objs(x, y, dest_bm->w, dest_bm->h, (flags & FR_DOHFLIP_MASK) != 0);
579
580 if (flags & FR_DOUBLEB_MASK) // looks like a bug to me, eh?
581 {
582 switch (flags & FR_SFX_MASK) {
583 case FR_SFX_VHOLD:
584 (*fr_mouse_hide)();
585 gr_set_canvas(dest_canvas);
586
587 // Save off original state
588 orig_bits = dest_bm->bits;
589 orig_h = dest_bm->h;
590
591 // KLC - adjust x and y if in doublesize mode.
592 if (DoubleSize) {
593 x *= 2;
594 y *= 2;
595 if (y > 0)
596 y++; // It's one off in slot view.
597 }
598
599 // Note that all of this contrivance to keep vhold_shift in original
600 // 320x200 coordinates is to avoid the wacky class of bugs of
601 // shifting screen mode in the middle of an EMP grenade
602 {
603 short vhs = vhold_shift;
604 if (convert_use_mode)
605 vhs = SCONV_Y(vhold_shift);
606
607 // Draw top bitmap
608 dest_bm->bits += dest_bm->row * (orig_h - vhs);
609 dest_bm->h = vhs;
610 if (dest_bm->h != 0)
611 gr_bitmap(dest_bm, x, y);
612
613 // Draw bottom bitmap
614 dest_bm->bits = orig_bits;
615 dest_bm->h = orig_h - vhs;
616 if (dest_bm->h != 0)
617 gr_bitmap(dest_bm, x, y + vhs);
618
619 // Restore state & increment shift
620 dest_bm->h = orig_h;
621 if (convert_use_mode)
622 vhold_shift += SCONV_Y(VHOLD_SHIFT_AMOUNT);
623 else
624 vhold_shift += VHOLD_SHIFT_AMOUNT;
625 if (convert_use_mode)
626 vhs = SCONV_Y(vhold_shift);
627 else
628 vhs = vhold_shift;
629 if (vhs > orig_h)
630 vhold_shift = 0;
631 }
632 (*fr_mouse_show)();
633 return FALSE;
634 case FR_SFX_STATIC:
635 draw_line_static(dest_bm, dmg_percentage, fr_sfx_color);
636 dmg_percentage >>= 2;
637 if (dmg_percentage == 0)
638 fr_global_mod_flag(0, FR_SFX_MASK);
639 break;
640 case FR_SFX_TELEPORT: {
641 uchar *p = dest_bm->bits;
642 int count = 0;
643 while (count < (dest_bm->w * dest_bm->h)) {
644 *p = TELEPORT_COLOR + (rand() & 0x3);
645 p++;
646 count++;
647 }
648 } break;
649 case FR_SFX_SHIELD:
650 orig_h = (dest_bm->h >> 1) - (dest_bm->h >> 5) * abs(shield_raisage);
651 orig_w = (dest_bm->w >> 1) - (dest_bm->w >> 5) * abs(shield_raisage);
652 orig_bits = dest_bm->bits;
653 for (loop = 1; loop < 5; loop++) {
654 draw_single_static_line(orig_bits + (orig_h + loop) * dest_bm->w, orig_w + loop,
655 dest_bm->w - orig_w - loop, BLUE_8_BASE);
656 draw_single_static_line(orig_bits + (dest_bm->h - (orig_h + loop)) * dest_bm->w, orig_w + loop,
657 dest_bm->w - orig_w - loop, BLUE_8_BASE);
658 }
659 if (shield_raisage & 0xf)
660 shield_raisage++;
661 else
662 fr_global_mod_flag(0, FR_SFX_MASK);
663 break;
664 }
665 switch (flags & FR_OVERLAY_MASK) {
666 case FR_OVERLAY_SHODAN: {
667 int i;
668 extern uchar *shodan_bitmask;
669 extern grs_bitmap shodan_draw_fs;
670 extern grs_bitmap shodan_draw_normal;
671 extern char thresh_fail;
672 uchar *shodan_draw_bits;
673 grs_bitmap *curr_shodan;
674 short shodan_level = (player_struct.game_time - time_until_shodan_avatar) >> SHODAN_TIME_SHIFT;
675 if (shodan_level > MAX_SHODAN_LEVEL)
676 shodan_level = MAX_SHODAN_LEVEL;
677 if (full_game_3d) {
678 curr_shodan = &shodan_draw_fs;
679 shodan_draw_bits = shodan_draw_fs.bits;
680 } else {
681 curr_shodan = &shodan_draw_normal;
682 shodan_draw_bits = shodan_draw_normal.bits;
683 }
684 if ((thresh_fail) || ((rand() & 0x1FF) == 1)) {
685 #ifdef SVGA_SUPPORT
686 if (convert_use_mode) {
687 grs_bitmap temp_bm;
688
689 // Note that we can use this since we know that audiologs aren't playing
690 // and that we don't want normal texture maps
691 gr_init_bitmap(&temp_bm, tmap_big_buffer, BMT_FLAT8, BMF_TRANS, curr_shodan->w, curr_shodan->h);
692
693 for (i = 0; i < temp_bm.h * temp_bm.w; i = i + ((thresh_fail) ? 1 : 2))
694 *(temp_bm.bits + i) = *(shodan_draw_bits + i);
695
696 // Copy in and scale up the snowy bitmap
697 ss_bitmap(&temp_bm, 0, 0);
698 } else
699 #endif
700 {
701 for (i = 0; i < dest_bm->h * dest_bm->w; i = i + ((thresh_fail) ? 1 : 2))
702 *(dest_bm->bits + i) = *(shodan_draw_bits + i);
703 }
704 } else {
705 #ifdef SVGA_SUPPORT
706 if (convert_use_mode) {
707 grs_bitmap temp_bm;
708
709 // Note that we can use this since we know that audiologs aren't playing
710 // and that we don't want normal texture maps
711 gr_init_bitmap(&temp_bm, tmap_big_buffer, BMT_FLAT8, BMF_TRANS, curr_shodan->w, curr_shodan->h);
712
713 for (i = 0; i < temp_bm.h * temp_bm.w; i++) {
714 if (SHODAN_CONQUER_GET(shodan_bitmask, i))
715 *(temp_bm.bits + i) = *(shodan_draw_bits + i);
716 else
717 *(temp_bm.bits + i) = 0;
718 }
719 // Copy in and scale up the snowy bitmap
720 ss_bitmap(&temp_bm, 0, 0);
721 } else
722 #endif
723 {
724 for (i = 0; i < dest_bm->h * dest_bm->w; i++) {
725 if (SHODAN_CONQUER_GET(shodan_bitmask, i))
726 *(dest_bm->bits + i) = *(shodan_draw_bits + i);
727 }
728 }
729 }
730 } break;
731 }
732 }
733
734 return TRUE; // let the renderer do the blit
735 }
736
gamesys_render_func(void * fake_dest_bitmap,int flags)737 void gamesys_render_func(void *fake_dest_bitmap, int flags) {
738 grs_bitmap *dest_bitmap = (grs_bitmap *)fake_dest_bitmap;
739 grs_canvas temp_canvas;
740
741 gr_make_canvas(dest_bitmap, &temp_canvas);
742 gr_push_canvas(&temp_canvas);
743 switch (flags & FR_SOLIDFR_MASK) {
744 case FR_SOLIDFR_SLDCLR: // if clearing, reset the mask
745 fr_global_mod_flag(0, FR_SOLIDFR_MASK);
746 case FR_SOLIDFR_SLDKEEP: // else just clear to the color
747 gr_clear(fr_solidfr_color);
748 break;
749 case FR_SOLIDFR_STATIC:
750 draw_full_static(dest_bitmap, GRAY_8_BASE);
751 break;
752 }
753 gr_pop_canvas();
754 }
755