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