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/olhscan.c $
21 * $Revision: 1.6 $
22 * $Author: dc $
23 * $Date: 1994/11/21 09:10:45 $
24 */
25
26 #include <stdlib.h>
27 #include <string.h>
28
29 #include "faketime.h"
30
31 #include "frtypes.h"
32 #include "frintern.h"
33 #include "frparams.h"
34 #include "frflags.h"
35 #include "olhint.h"
36 #include "objects.h"
37 #include "objprop.h"
38 #include "game_screen.h"
39 #include "fullscrn.h"
40
41 #define SCAN_OBJ_LIST 8
42
43 #define MIN_OLH_RADIUS 2
44 #define MAX_OLH_RADIUS 5
45
46 ubyte olh_radius = MIN_OLH_RADIUS;
47
48 #define BOTTOM_MARGIN (SCAN_HGT - 15 / SCAN_RATIO)
49 #define RIGHT_MARGIN (OLH_WRAP_WID / SCAN_RATIO)
50
51 fauxrend_context *olh_full_context = NULL;
52
53 extern fauxrend_context *svga_render_context;
54
55 #define FULL_SCAN_WID (FULL_VIEW_WIDTH / SCAN_RATIO)
56 #define FULL_SCAN_HGT (FULL_VIEW_HEIGHT / SCAN_RATIO)
57
58 void olh_init_single_scan(fauxrend_context **outxt, fauxrend_context *intxt);
59 void olh_init_scan(void);
60 void olh_free_scan(void);
61 void olh_svga_deal(void);
62 ushort olh_scan_objs(void);
63
olh_init_single_scan(fauxrend_context ** outxt,fauxrend_context * intxt)64 void olh_init_single_scan(fauxrend_context **outxt, fauxrend_context *intxt) {
65 uchar *mem = ((grs_canvas *)fr_get_canvas(intxt))->bm.bits;
66
67 *outxt = (fauxrend_context *)fr_place_view(FR_NEWVIEW, FR_DEFCAM, mem,
68 FR_CURVIEW_STRT | FR_DOUBLEB_MASK | FR_PICKUPM_MASK, 0, 0, 0, 0,
69 intxt->xwid / SCAN_RATIO, intxt->ywid / SCAN_RATIO);
70 fr_set_callbacks(*outxt, NULL, NULL, NULL);
71 }
72
73 /*KLC - no longer used
74 void olh_init_scan(void)
75 {
76 olh_init_single_scan(&olh_full_context, (fauxrend_context *)full_game_fr_context);
77 }
78 */
olh_free_scan(void)79 void olh_free_scan(void) {
80 if (olh_full_context)
81 fr_free_view(olh_full_context);
82 }
83
84 fix x_mul = fix_make(1, 0), y_mul = fix_make(1, 0);
olh_svga_deal(void)85 void olh_svga_deal(void) {
86 if (olh_full_context)
87 fr_free_view(olh_full_context);
88 olh_init_single_scan(&olh_full_context, svga_render_context);
89 x_mul = fix_div(fix_make(320, 0), fix_make(grd_mode_cap.w, 0));
90 y_mul = fix_div(fix_make(200, 0), fix_make(grd_mode_cap.h, 0));
91 }
92
93 extern int last_real_time;
94
olh_scan_objs(void)95 ushort olh_scan_objs(void) {
96 int xl, yl;
97 int col;
98 int (*fr_ptr_idx)(void) = fr_get_idx;
99 short x, y;
100 struct _obj_scandata {
101 ObjID obj;
102 int x, y; // TOTAL x and y coordinates for all samples
103 ushort count;
104 } objdata[SCAN_OBJ_LIST];
105 short objcount = 0;
106 #ifdef SVGA_SUPPORT
107 fauxrend_context *fr = olh_full_context;
108 #else
109 fauxrend_context *fr = (full_game_3d) ? olh_full_context : olh_context;
110 #endif
111 ubyte save_radius = _frp.view.radius;
112
113 // Do a monochrome render
114 // olh_replace_view(SCREEN_CONTEXT->xwid/SCAN_RATIO,SCREEN_CONTEXT->ywid/SCAN_RATIO);
115 // _fr_top(fr);
116 _fr_glob_flags |= FR_PICKUPM_MASK;
117 fr_cur_obj_col = FR_CUR_OBJ_BASE;
118 fr_get_idx = fr_pickup_idx;
119 _frp.view.radius = olh_radius;
120 fr_rend(fr);
121 _frp.view.radius = save_radius;
122 fr_get_idx = fr_ptr_idx;
123 _fr_glob_flags &= ~FR_PICKUPM_MASK;
124
125 if (*tmd_ticks - last_real_time < CIT_CYCLE / 15)
126 olh_radius = lg_min(olh_radius + 1, MAX_OLH_RADIUS);
127 else if (*tmd_ticks - last_real_time > CIT_CYCLE / 10)
128 olh_radius = lg_max(olh_radius - 1, MIN_OLH_RADIUS);
129
130 xl = yl = 0;
131
132 #ifdef DEBUGGING_BLIT
133 gr_push_canvas(grd_screen_canvas);
134 gr_bitmap(&fr->draw_canvas.bm, 0, 200 - fr->draw_canvas.bm.h);
135 gr_pop_canvas();
136 #endif
137
138 olh_object.obj = OBJ_NULL;
139 // collect samples
140 for (y = yl; y < fr->draw_canvas.bm.h; y++)
141 for (x = xl; x < fr->draw_canvas.bm.w; x++) {
142 if (y > BOTTOM_MARGIN && x > fr->draw_canvas.bm.w - RIGHT_MARGIN)
143 break;
144 col = (int)(*((fr->draw_canvas.bm.bits) + (y * fr->draw_canvas.bm.row) + (x)));
145 if ((col >= FR_CUR_OBJ_BASE) && (col < fr_cur_obj_col)) // if we are actually exactly over an object
146 {
147 ObjID obj = (ObjID)fr_col_to_obj[col - FR_CUR_OBJ_BASE];
148 if (olh_candidate(obj)) {
149 int i;
150 for (i = 0; i < objcount; i++)
151 if (objdata[i].obj == obj) {
152 objdata[i].x += x;
153 objdata[i].y += y;
154 objdata[i].count++;
155 goto found;
156 }
157 // not found, so add the object
158 if (objcount >= SCAN_OBJ_LIST) // no more room in list, how sad.
159 continue;
160 i = objcount++;
161 objdata[i].obj = obj;
162 objdata[i].x = x;
163 objdata[i].y = y;
164 objdata[i].count = 1;
165 found:
166 // mprintf ("found %d at (%d,%d) (x,y) now (%d,%d), count now
167 // %d\n",obj,x,y,objdata[i].x,objdata[i].y,objdata[i].count);
168 ;
169 }
170 }
171 }
172
173 // now pick the best one.
174 if (objcount > 0) {
175 int i;
176 uint best_weight = 0;
177 for (i = 0; i < objcount; i++) {
178 struct _obj_scandata *dat = &objdata[i];
179 LGPoint pos = MakePoint((short)(dat->x / dat->count), (short)(dat->y / dat->count));
180 uint weight =
181 dat->count * (fr->xwid + fr->ywid) / (abs(2 * pos.x - fr->xwid) + abs(2 * pos.y - fr->ywid) + 1);
182 if (weight > best_weight) {
183 olh_object.obj = dat->obj;
184 olh_object.loc = pos;
185 best_weight = weight;
186 }
187 }
188 #ifdef SVGA_SUPPORT
189 {
190 fix tmp;
191 tmp = fix_make(olh_object.loc.x, 0);
192 tmp = fix_mul(tmp, x_mul);
193 olh_object.loc.x = fix_int(tmp);
194 tmp = fix_make(olh_object.loc.y, 0);
195 tmp = fix_mul(tmp, y_mul);
196 olh_object.loc.y = fix_int(tmp);
197 }
198 #endif
199 } else
200 olh_object.obj = OBJ_NULL;
201 return OBJ_NULL;
202 }
203