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: r:/prj/cit/src/RCS/render.c $
21  * $Revision: 1.43 $
22  * $Author: xemu $
23  * $Date: 1994/10/27 04:55:24 $
24  */
25 
26 #include <string.h>
27 
28 #define __RENDER_SRC
29 #include "render.h"
30 #include "frprotox.h"
31 #include "faketime.h"
32 #include "game_screen.h"
33 #include "fullscrn.h"
34 #include "mainloop.h"
35 #include "hudobj.h"
36 #include "cybmem.h"
37 
38 // Hack camera stuff
39 #include "gamerend.h"
40 #include "frcamera.h"
41 #include "frflags.h"
42 #include "froslew.h"
43 #include "player.h"
44 #include "cybmem.h"
45 
46 #include "rcolors.h"
47 
48 #include "map.h"
49 #include "mapflags.h"
50 #include "wares.h"
51 #include "gr2ss.h"
52 
53 frc *hack_cam_frcs[MAX_CAMERAS_VISIBLE];
54 grs_canvas hack_cam_canvases[MAX_CAMERAS_VISIBLE], static_canvas;
55 grs_bitmap *hack_cam_bitmaps[MAX_CAMERAS_VISIBLE], *static_bitmap;
56 cams hack_cam;
57 char camera_map[NUM_HACK_CAMERAS];
58 ObjID hack_frc_objs[MAX_CAMERAS_VISIBLE];
59 ObjID hack_cam_objs[NUM_HACK_CAMERAS];
60 ObjID hack_cam_surrogates[NUM_HACK_CAMERAS];
61 
62 #define HACK_CAMERA_X 0
63 #define HACK_CAMERA_Y 0
64 #define HACK_CAMERA_WIDTH ((start_mem < BIG_HACKCAM_THRESHOLD) ? 64 : 128)
65 #define HACK_CAMERA_HEIGHT ((start_mem < BIG_HACKCAM_THRESHOLD) ? 64 : 128)
66 //#define HACK_CAMERA_WIDTH  128
67 //#define HACK_CAMERA_HEIGHT  128
68 //#define HACK_CAMERA_WIDTH  64
69 //#define HACK_CAMERA_HEIGHT 64
70 
71 #define STATIC_HEIGHT 32
72 #define STATIC_WIDTH 32
73 
74 #define FRAME_SKIP_MASK 0x03
75 #define FRAME_PARITY_SHF 2 // skip every 4 frames when rendering screen images
76 
77 uchar hack_cameras_needed = 0;
78 char curr_hack_cam = 0;
79 ulong hack_cam_fr_count = 0;
80 uchar screen_static_drawn = FALSE;
81 
82 // -----------
83 // PROTOTYPES
84 //------------
85 int hack_camera_draw_callback(grs_canvas *cvs, grs_bitmap *bm, int u1, int u2, int u3);
86 void update_cspace_tiles(void);
87 void tile_hit(int mx, int my);
88 
hack_camera_draw_callback(grs_canvas * cvs,grs_bitmap * bm,int u1,int u2,int u3)89 int hack_camera_draw_callback(grs_canvas *cvs, grs_bitmap *bm, int u1, int u2, int u3) {
90     //   gr_push_canvas(&hack_cam_canvases[curr_hack_cam]);
91     //   gr_bitmap(bm,0,0);
92     //   gr_pop_canvas();
93     return (FALSE);
94 }
95 
96 typedef int (*frdraw)(void *dstc, void *dstbm, int x, int y, int flg);
97 
init_hack_cameras()98 errtype init_hack_cameras() {
99     int i;
100     grs_canvas *tmp_cnv;
101     uchar *tmp_mem;
102 
103     static_bitmap = gr_alloc_bitmap(BMT_FLAT8, 0, STATIC_WIDTH, STATIC_HEIGHT);
104     gr_make_canvas(static_bitmap, &static_canvas);
105     gr_push_canvas(&static_canvas);
106     gr_clear(0);
107     gr_pop_canvas();
108 
109     fr_camera_create(&hack_cam, CAMTYPE_OBJ, player_struct.rep, NULL, NULL);
110     for (i = 0; i < MAX_CAMERAS_VISIBLE; i++) {
111         //      hack_cam_bitmaps[i] = gr_alloc_bitmap(BMT_FLAT8, 0, HACK_CAMERA_WIDTH, HACK_CAMERA_HEIGHT);
112         //      gr_make_canvas(hack_cam_bitmaps[i], &hack_cam_canvases[i]);
113         //      hack_cam_frcs[i] = fr_place_view(FR_NEWVIEW, &hack_cam, &hack_cam_canvases[i],
114         //      hack_cam_frcs[i] = fr_place_view(FR_NEWVIEW, &hack_cam, &hack_cam_bitmaps[i],
115 
116         //      Warning(("start_mem = %d, BIG_HACKCAM = %d!\n",start_mem,BIG_HACKCAM_THRESHOLD));
117         //      Warning(("HACK_CAMERA_WID = %d!\n",HACK_CAMERA_WIDTH));
118         tmp_mem = (uchar *)malloc(HACK_CAMERA_WIDTH * HACK_CAMERA_HEIGHT);
119         hack_cam_frcs[i] = fr_place_view(FR_NEWVIEW, &hack_cam, tmp_mem, FR_DOUBLEB_MASK | FR_HACKCAM_FLAG, 0, 0,
120                                          HACK_CAMERA_X, HACK_CAMERA_Y, HACK_CAMERA_WIDTH, HACK_CAMERA_HEIGHT);
121         fr_set_callbacks(hack_cam_frcs[i], (frdraw)hack_camera_draw_callback, NULL, NULL);
122         tmp_cnv = (grs_canvas *)fr_get_canvas(hack_cam_frcs[i]);
123         hack_cam_bitmaps[i] = &tmp_cnv->bm;
124 
125         //      gr_push_canvas(&hack_cam_canvases);
126         //      gr_clear(0);
127         //      gr_pop_canvas();
128     }
129 
130     for (i = 0; i < NUM_HACK_CAMERAS; i++) {
131         camera_map[i] = 0;
132         hack_cam_objs[i] = OBJ_NULL;
133         hack_cam_surrogates[i] = OBJ_NULL;
134     }
135 
136     return (OK);
137 }
138 
shutdown_hack_cameras()139 errtype shutdown_hack_cameras() {
140     int i;
141     for (i = 0; i < MAX_CAMERAS_VISIBLE; i++) {
142         fr_free_view(hack_cam_frcs[i]);
143         free(hack_cam_bitmaps[i]->bits);
144     }
145     return (OK);
146 }
147 
do_screen_static()148 errtype do_screen_static() {
149     extern void draw_full_static(grs_bitmap * stat_dest, int c_base);
150     if (!screen_static_drawn)
151         draw_full_static(static_bitmap, GRAY_8_BASE);
152     return (OK);
153 }
154 
render_hack_cameras()155 errtype render_hack_cameras() {
156     int i, count;
157 
158     // efficiency good....
159     if (hack_cameras_needed == 0)
160         return OK;
161 
162     hack_cam_fr_count++;
163     count = 0;
164     for (i = 0; i < NUM_HACK_CAMERAS; i++) {
165         if ((hack_cameras_needed & (1 << i)) && !((hack_cam_objs[i] == OBJ_NULL) || (count == MAX_CAMERAS_VISIBLE)))
166             camera_map[i] = ++count;
167         else
168             camera_map[i] = 0;
169     }
170     for (i = 0; i < NUM_HACK_CAMERAS; i++) {
171         if (camera_map[i] && (hack_frc_objs[camera_map[i] - 1] != hack_cam_objs[i] ||
172                               (((hack_cam_fr_count & FRAME_SKIP_MASK) == 0) &&
173                                (count == 1 || (((hack_cam_fr_count >> FRAME_PARITY_SHF) ^ camera_map[i]) & 1) == 0)))) {
174             curr_hack_cam = camera_map[i] - 1;
175             hack_frc_objs[curr_hack_cam] = hack_cam_objs[i];
176             fr_camera_update(&hack_cam, (unsigned int)hack_cam_objs[i], 0, 0);
177             fr_rend(hack_cam_frcs[camera_map[i] - 1]);
178         }
179     }
180     curr_hack_cam = 0;
181     hack_cameras_needed = 0;
182     return (OK);
183 }
184 
185 // Okay, takeover and relinquish are what we do when you double
186 // click on a hack-camera-ed screen.  Note that we always relinquish
187 // back to the player, if this is insufficient it's easy to store off
188 // some of the camera data.
189 uchar hack_takeover = 0;
190 int hack_eye; // the fierce pirate
191 
hack_camera_takeover(int hack_cam)192 errtype hack_camera_takeover(int hack_cam) {
193     LGRect start = {{-5, -5}, {5, 5}};
194     extern LGPoint use_cursor_pos;
195     LGPoint ucp;
196     extern void zoom_rect(LGRect * start, LGRect * end);
197     extern bool DoubleSize;
198     extern LGRect mainview_rect;
199     extern LGRect fscrn_rect;
200     cams *cam = fr_camera_getdef();
201 
202     // Turn off the 360 ware, if it is on
203     if (WareActive(player_struct.hardwarez_status[HARDWARE_360]))
204         use_ware(WARE_HARD, HARDWARE_360);
205 
206     // do a wacky zoom thing
207     ucp = use_cursor_pos;
208     if (!DoubleSize)
209         ss_point_convert(&(ucp.x), &(ucp.y), TRUE);
210     RECT_MOVE(&start, ucp);
211     zoom_rect(&start, (full_game_3d) ? &fscrn_rect : &mainview_rect);
212 
213     // level out the eye & store off old position
214     hack_eye = eye_mods[1];
215     eye_mods[1] = 0;
216 
217     fr_camera_update(cam, (unsigned int)hack_cam_objs[hack_cam], 0, 0);
218     hack_takeover = hack_cam + 1;
219     return (OK);
220 }
221 
hack_camera_relinquish()222 errtype hack_camera_relinquish() {
223     cams *cam = fr_camera_getdef();
224     fr_camera_update(cam, (unsigned int)PLAYER_OBJ, 0, 0);
225 
226     // force refresh of this hack camera.
227     hack_frc_objs[camera_map[hack_takeover - 1] - 1] = OBJ_NULL;
228     camera_map[hack_takeover - 1] = 0;
229 
230     hack_takeover = 0;
231     eye_mods[1] = hack_eye;
232     return (OK);
233 }
234 
235 #define inc_area(tp)                   \
236     if (((tp >= 0) && (tp < 64 * 64))) \
237     (*(tmp_ptr + tp))++
238 #define val_area(tp) (*(tmp_ptr + tp))
239 
update_cspace_tiles(void)240 void update_cspace_tiles(void) {
241     int cur_tp, i, j, s, t, x;
242     uchar *tmp_ptr = (uchar *)big_buffer;
243     MapElem *mmp;
244 
245     LG_memset(tmp_ptr, 0, 64 * 64);
246     mmp = MAP_GET_XY(0, 0);
247     for (i = 0, cur_tp = 0; i < 64; i++)
248         for (j = 0; j < 64; j++, cur_tp++, mmp++)
249             if (me_bits_flip_x(mmp))
250                 for (s = -1; s <= 1; s++)
251                     for (t = -1; t <= 1; t++)
252                         if (s | t) {
253                             x = cur_tp + (s * 64) + t;
254                             inc_area(x);
255                         }
256     mmp = MAP_GET_XY(0, 0);
257     for (i = 0, cur_tp = 0; i < 64; i++)
258         for (j = 0; j < 64; j++, cur_tp++, mmp++)
259             if (me_bits_flip(mmp)) {
260                 if (me_bits_flip(mmp) == 1)
261                     me_flip_set(mmp, 3);
262                 else if (me_bits_flip(mmp) == 3)
263                     me_flip_set(mmp, 2);
264                 if (val_area(cur_tp) != 0)
265                     if ((val_area(cur_tp) < 2) || (val_area(cur_tp) > 3))
266                         me_flip_set(mmp, 0);
267             } else if (val_area(cur_tp) == 3)
268                 me_flip_set(mmp, 2);
269 
270 #ifdef STATE_RULES
271     switch (me_bits_flip(mmp)) {
272     case 2:
273         if ((val_area(cur_tp) < 2) || (val_area(cur_tp) > 3))
274             me_flip_set(mmp, 0);
275         break;
276     case 1:
277         me_flip_set(mmp, 3);
278         break;
279     case 0:
280         if (val_area(cur_tp) == 3)
281             me_flip_set(mmp, 2);
282         break;
283     case 3:
284         if (((val_area(cur_tp) + i + j) & 0xf) < 4)
285             me_flip_set(mmp, 2);
286     }
287 #endif
288 }
289 
tile_hit(int mx,int my)290 void tile_hit(int mx, int my) {
291     static int lx, ly;
292     static long last_time = 0;
293     int dsq = ((lx - mx) | (ly - my));
294     MapElem *mp;
295 
296     if (dsq || ((last_time + (CIT_CYCLE >> 2) < *tmd_ticks))) {
297         last_time = *tmd_ticks;
298         mp = MAP_GET_XY(mx, my);
299         if (dsq) {
300             me_flip_set(mp, 1);
301             lx = mx;
302             ly = my;
303         } else if (me_bits_flip(mp))
304             me_flip_set(mp, 0);
305         else
306             me_flip_set(mp, 1);
307     }
308 }
309 
310 #define LIFE_UPDATE_RATE (256 >> 2)
311 
render_run(void)312 errtype render_run(void) {
313     extern uchar view360_render_on;
314     extern void view360_render(void);
315     static long last_cspace_update = 0;
316 
317 #ifdef POPUPS_ALLOWED
318     if (region_obscured(mainview_region, mainview_region->r) == UNOBSCURED)
319 #endif
320     {
321         // printf("render_run_start\n");
322         screen_static_drawn = FALSE;
323         current_num_hudobjs = 0; // clear the hud objects
324         rendrect = mainview_region->r;
325 
326         // printf("fr_rend\n");
327         fr_rend(NULL);
328 
329         if (view360_render_on)
330             view360_render();
331         render_hack_cameras();
332         if (global_fullmap->cyber)
333             if ((last_cspace_update + LIFE_UPDATE_RATE) < (*tmd_ticks)) {
334                 last_cspace_update = (*tmd_ticks) & (~(LIFE_UPDATE_RATE - 1));
335                 update_cspace_tiles();
336             }
337     }
338     return OK;
339 }
340