Noble Ape
The Central Directories of the Noble Ape Simulation.
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros
draw.c
Go to the documentation of this file.
1 /****************************************************************
2 
3  draw.c
4 
5  =============================================================
6 
7  Copyright 1996-2014 Tom Barbalet. All rights reserved.
8 
9  Permission is hereby granted, free of charge, to any person
10  obtaining a copy of this software and associated documentation
11  files (the "Software"), to deal in the Software without
12  restriction, including without limitation the rights to use,
13  copy, modify, merge, publish, distribute, sublicense, and/or
14  sell copies of the Software, and to permit persons to whom the
15  Software is furnished to do so, subject to the following
16  conditions:
17 
18  The above copyright notice and this permission notice shall be
19  included in all copies or substantial portions of the Software.
20 
21  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
23  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
25  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
26  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
28  OTHER DEALINGS IN THE SOFTWARE.
29 
30  This software and Noble Ape are a continuing work of Tom Barbalet,
31  begun on 13 June 1996. No apes or cats were harmed in the writing
32  of this software.
33 
34  ****************************************************************/
35 
36 #include "gui.h"
37 
38 #include <stdio.h>
39 
40 /* the weather/time of day icons hard coded */
41 
42 #ifndef GRAPHLESS_GUI
43 
44 extern void graph_draw(noble_simulation * local_sim, n_byte * graph, n_int dim_x, n_int dim_y);
45 
46 #endif
47 
48 static const n_byte icns[896] =
49 {
50  /* sunny day */
51  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
52  0x00, 0x02, 0x00, 0x00, 0x00, 0x0A, 0x80, 0x00, 0x01, 0x0A, 0x84, 0x00, 0x04, 0x8A, 0x89, 0x00,
53  0x02, 0x4A, 0x92, 0x00, 0x09, 0x2A, 0xA4, 0x80, 0x04, 0x9F, 0xC9, 0x00, 0x02, 0x70, 0x72, 0x00,
54  0x01, 0x60, 0x34, 0x00, 0x00, 0xC0, 0x18, 0x00, 0x1F, 0x80, 0x0F, 0xC0, 0x00, 0x80, 0x08, 0x00,
55  0x3F, 0x80, 0x0F, 0xE0, 0x00, 0x80, 0x08, 0x00, 0x1F, 0x80, 0x0F, 0xC0, 0x00, 0xC0, 0x18, 0x00,
56  0x01, 0x60, 0x34, 0x00, 0x02, 0x70, 0x72, 0x00, 0x04, 0x9F, 0xC9, 0x00, 0x09, 0x2A, 0xA4, 0x80,
57  0x02, 0x4A, 0x92, 0x00, 0x04, 0x8A, 0x89, 0x00, 0x01, 0x0A, 0x84, 0x00, 0x00, 0x0A, 0x80, 0x00,
58  0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
59  /* cloudy day */
60  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
61  0x00, 0x02, 0x00, 0x00, 0x00, 0x0A, 0x80, 0x00, 0x01, 0x0A, 0x84, 0x00, 0x04, 0x8A, 0x89, 0x00,
62  0x02, 0x4A, 0x92, 0x00, 0x09, 0x2A, 0xA4, 0x80, 0x04, 0x9F, 0xC9, 0x00, 0x02, 0x70, 0x72, 0x00,
63  0x01, 0x60, 0x34, 0x00, 0x00, 0xC0, 0x18, 0x00, 0x1F, 0x80, 0x0F, 0xC0, 0x00, 0xB8, 0x08, 0x00,
64  0x01, 0xC7, 0x1C, 0x00, 0x0E, 0x00, 0xE3, 0x00, 0x10, 0x00, 0x00, 0x80, 0x20, 0x00, 0x00, 0x40,
65  0x20, 0x00, 0x00, 0x40, 0x20, 0x00, 0x00, 0x40, 0x10, 0x00, 0x00, 0x80, 0x10, 0x00, 0x00, 0x80,
66  0x10, 0x00, 0x00, 0x80, 0x08, 0x00, 0x00, 0x40, 0x08, 0x00, 0x00, 0x40, 0x08, 0x01, 0xC0, 0x40,
67  0x07, 0x8E, 0x38, 0x80, 0x00, 0x70, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
68  /* rainy day */
69  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
70  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00,
71  0x00, 0x38, 0xE3, 0x80, 0x01, 0xC0, 0x1C, 0x60, 0x02, 0x00, 0x00, 0x10, 0x04, 0x00, 0x00, 0x08,
72  0x04, 0x00, 0x00, 0x08, 0x04, 0x00, 0x00, 0x08, 0x02, 0x00, 0x00, 0x10, 0x02, 0x00, 0x00, 0x10,
73  0x02, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x08, 0x01, 0x00, 0x00, 0x08, 0x01, 0x00, 0x38, 0x08,
74  0x00, 0xF1, 0xD7, 0x10, 0x00, 0xAE, 0xAA, 0xE0, 0x01, 0x55, 0x55, 0x40, 0x02, 0xAA, 0xAA, 0x80,
75  0x05, 0x55, 0x55, 0x00, 0x0A, 0xAA, 0xAA, 0x00, 0x05, 0x55, 0x54, 0x00, 0x0A, 0xAA, 0xA8, 0x00,
76  0x05, 0x55, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
77  /* clear night */
78  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
79  0xF1, 0xFF, 0xFF, 0xFF, 0xE6, 0xFF, 0xFF, 0xFF, 0xE7, 0xFF, 0xFF, 0xFF, 0xE6, 0xFF, 0xFF, 0xFF,
80  0xF1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
81  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
82  0xFF, 0xFF, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
83  0xFF, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF,
84  0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
85  0xFF, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
86  /* cloudy night */
87  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0x7F, 0xFF,
88  0xF1, 0xEA, 0xAE, 0xBF, 0xE7, 0x55, 0x55, 0x5F, 0xE6, 0xAA, 0xAA, 0xAF, 0xE7, 0x55, 0x55, 0x57,
89  0xF2, 0xAA, 0xAA, 0xAF, 0xFF, 0x55, 0x55, 0x5F, 0xFF, 0xAA, 0xAA, 0xAF, 0xFF, 0x55, 0x55, 0x5F,
90  0xFB, 0xAA, 0xAA, 0xAF, 0xF5, 0xD5, 0x55, 0x57, 0xEA, 0xAA, 0xAA, 0xAF, 0xD5, 0xFD, 0xF7, 0xDF,
91  0xEB, 0xEF, 0xBE, 0xFF, 0xFF, 0x55, 0x57, 0x57, 0xFA, 0xAA, 0xAA, 0xAF, 0xF5, 0x55, 0x55, 0x57,
92  0xEA, 0xAA, 0xAA, 0xEB, 0xF5, 0x55, 0x55, 0x57, 0xFA, 0xAA, 0xAA, 0xAF, 0xF5, 0x55, 0x55, 0xDF,
93  0xFA, 0xAA, 0xAA, 0xFF, 0xFD, 0x55, 0x55, 0x7F, 0xFA, 0xAA, 0xAA, 0xFF, 0xFD, 0x55, 0xD5, 0x7F,
94  0xFF, 0xAF, 0xFA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
95  /* rainy night */
96  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0xFF,
97  0xFF, 0xFF, 0xFF, 0xBF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
98  0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xE2, 0x3E, 0x7F, 0xFE, 0x00, 0x00, 0x1F, 0xFC, 0x88, 0x88, 0x8F,
99  0xDC, 0x00, 0x00, 0x0F, 0xFE, 0x22, 0x22, 0x2F, 0xFE, 0x00, 0x00, 0x1F, 0xFE, 0x88, 0x88, 0x9F,
100  0xFE, 0x00, 0x00, 0x1F, 0xFB, 0x22, 0x22, 0x2F, 0xFF, 0x00, 0x00, 0x0F, 0xFF, 0x88, 0xB8, 0x8F,
101  0xFF, 0xF1, 0xD7, 0x1F, 0xFF, 0xAE, 0xAA, 0xFF, 0xFF, 0x55, 0x55, 0x7F, 0xFE, 0xAA, 0xAA, 0xFF,
102  0xFD, 0x55, 0x55, 0xFF, 0xFA, 0xAA, 0xAB, 0xFF, 0xFD, 0x55, 0x57, 0xFF, 0xFA, 0xAA, 0xBF, 0xFF,
103  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
104  /* sunrise/sunset */
105  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
106  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
107  0xFF, 0xD5, 0xFB, 0xFF, 0xFF, 0xAA, 0xBF, 0xFF, 0x77, 0x55, 0x55, 0xF5, 0xAB, 0xA0, 0xAA, 0xAA,
108  0x55, 0x40, 0x01, 0x55, 0xAA, 0x80, 0x00, 0x2A, 0x54, 0x00, 0x00, 0x55, 0xA0, 0x00, 0x00, 0x2A,
109  0x40, 0x00, 0x00, 0x55, 0xA0, 0x00, 0x00, 0x2A, 0x00, 0x00, 0x00, 0x05, 0x00, 0x02, 0x00, 0x0A,
110  0x00, 0x0A, 0x80, 0x05, 0x01, 0x0A, 0x84, 0x02, 0x04, 0x8A, 0x89, 0x05, 0x02, 0x4A, 0x92, 0x02,
111  0x09, 0x2A, 0xA4, 0x80, 0x04, 0x9F, 0xC9, 0x00, 0x02, 0x70, 0x72, 0x00, 0x01, 0x60, 0x34, 0x00,
112  0x00, 0xC0, 0x18, 0x00, 0x1F, 0x80, 0x0F, 0xC0, 0x00, 0x80, 0x08, 0x00, 0xFF, 0xFF, 0xFF, 0xFF
113 };
114 
115 /* from ASCII 32 - 127, corresponding to the seg14 results */
116 
117 /* n_byte segment = seg14[ conv[ character_value ]]; */
118 static const n_byte conv[ 96 ] =
119 {
120  0, 40, 41, 0, 0, 0, 0, 42, 43, 44, 38, 39, 45, 11, 46, 47, 1, 2, 3, 4, 5, 6, 7,
121  8, 9, 10, 48, 49, 0, 50, 0, 51, 0, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
122  23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 52, 53, 54, 0, 55, 56,
123  12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
124  32, 33, 34, 35, 36, 37, 57, 58, 59, 0, 0
125 };
126 
127 /* one bit per segment */
128 static const n_byte2 seg14[ 60 ] =
129 {
130  0x0000, 0x3F00, 0x1800, 0x36C0, 0x3CC0, 0x19C0, 0x2DC0, 0x2FC0, 0x3800, 0x3FC0,
131  0x3DC0, 0x00C0, 0x3BC0, 0x3CA1, 0x2700, 0x3C21, 0x27C0, 0x23C0, 0x2F80, 0x1BC0,
132  0x2421, 0x1E00, 0x0354, 0x0700, 0x1B06, 0x1B12, 0x3F00, 0x33C0, 0x3F10, 0x33D0,
133  0x2DC0, 0x2021, 0x1F00, 0x030C, 0x1B18, 0x001E, 0x11E0, 0x240C, 0x00FF, 0x00E1,
134 
135  0x8001, 0x0101, 0x0001, 0x0014, 0x000A, 0x0008, 0x8000, 0x000C, 0xC000, 0x4008,
136  0x04C0, 0xA004, 0x2700, 0x0012, 0x3402, 0x0400, 0x0002, 0x244A, 0x0021, 0x2494
137 };
138 
139 
140 #define MAX_NUMBER_ERRORS 35
141 
142 static n_byte number_errors;
143 static n_string_block error_array[MAX_NUMBER_ERRORS + 1];
144 
145 #ifdef BRAIN_ON
146 static n_uint tilt_y = 0;
147 #endif
148 
152 
153 static n_int toggle_weather = 1;
154 static n_int toggle_brain = 1;
155 static n_int toggle_braincode = 0;
156 static n_int toggle_territory = 0;
157 static n_int toggle_tidedaylight = 0;
158 
160 {
161  toggle_weather ^= 1;
162  return toggle_weather;
163 }
164 
166 {
167  toggle_brain ^= 1;
168  return toggle_brain;
169 }
170 
172 {
173  toggle_braincode ^= 1;
174  return toggle_braincode;
175 }
176 
178 {
179  toggle_territory ^= 1;
180  return toggle_territory;
181 }
182 
184 {
185  toggle_tidedaylight ^= 1;
186  return toggle_tidedaylight;
187 }
188 
189 /* this needs to be grouped eventually, it is here as a test */
190 
191 #define UNDRAW_MAX 100000
192 
193 static n_byte * undraw_location[UNDRAW_MAX];
194 static n_byte undraw_color[UNDRAW_MAX];
195 static n_int undraw_count = 0;
196 
198 {
199  undraw_count = 0;
200 }
201 
202 static void draw_undraw()
203 {
204  if (undraw_count == 0) return;
205  undraw_count--;
206  do
207  {
208  *undraw_location[undraw_count] = undraw_color[undraw_count];
209  undraw_count--;
210  }
211  while(undraw_count > -1);
212  undraw_count = 0;
213 }
214 
215 static n_byte * local_offscreen = 0L;
216 
218 {
219  local_offscreen = value;
220  return local_offscreen;
221 }
222 
223 static n_byte pixel_color8_hires(n_int px, n_int py, n_int dx, n_int dy, void * information)
224 {
225  n_color8 *local_col = information;
226  n_byte *location = &local_col->screen[ (px<<1) | (py<<(HI_RES_MAP_BITS+1)) | 1 ];
227  undraw_location[undraw_count] = location;
228  undraw_color[undraw_count] = location[0];
229  undraw_count++;
230 
231  if (undraw_count > UNDRAW_MAX)
232  {
233  (void)SHOW_ERROR("Erase count outside limit");
234  }
235  location[0] = local_col->color;
236  return 0;
237 }
238 
239 static n_byte pixel_color8(n_int px, n_int py, n_int dx, n_int dy, void * information)
240 {
241  n_color8 *local_col = information;
242  local_col->screen[ px | (py<<MAP_BITS) ] = local_col->color;
243  return 0;
244 }
245 
246 static n_int terrain_dim_x = 512;
247 static n_int terrain_dim_y = 511;
248 
249 static n_byte pixel_map(n_int px, n_int py, n_int dx, n_int dy, void * information)
250 {
251  n_byte *byte_info = information;
252  byte_info[ px | (py<<MAP_BITS) ] = COLOUR_YELLOW;
253  return 0;
254 }
255 
256 static n_byte pixel_map_checker(n_int px, n_int py, n_int dx, n_int dy, void * information)
257 {
258  if ((px + py) & 1)
259  {
260  return pixel_map(px, py, dx, dy, information);
261  }
262  return 0;
263 }
264 
265 static n_byte pixel_overlay(n_int px, n_int py, n_int dx, n_int dy, void * information)
266 {
267  n_byte *byte_info = information;
268  byte_info[ px + (py * terrain_dim_x) ] = COLOUR_YELLOW;
269  return 0;
270 }
271 
272 static n_byte pixel_black(n_int px, n_int py, n_int dx, n_int dy, void * information)
273 {
274  n_byte *byte_info = information;
275  byte_info[ px + (py * terrain_dim_x) ] = 0;
276  return 0;
277 }
278 
279 
280 static n_byte pixel_grey(n_int px, n_int py, n_int dx, n_int dy, void * information)
281 {
282  n_byte *byte_info = information;
283  byte_info[ px + (py * terrain_dim_x) ] = COLOUR_GREY;
284  return 0;
285 }
286 
288 {
289  n_byte *local_buffer = local_offscreen;
290 
291  if (local_buffer == 0L)
292  {
293  return local_buffer;
294  }
295 
296  switch(which_one)
297  {
298  case NUM_TERRAIN:
299  return TERRAINWINDOW(local_buffer);
300  break;
301  case NUM_VIEW:
302  return VIEWWINDOW(local_buffer);
303  break;
304 #ifndef GRAPHLESS_GUI
305  case NUM_GRAPH:
306  return GRAPHWINDOW(local_buffer);
307  break;
308 #endif
309  }
310  return 0L;
311 }
312 
313 #ifdef MULTITOUCH_CONTROLS
314 
315 extern touch_control_state tc_state;
316 
317 void draw_tc_controls(n_join * local_mono)
318 {
319  const n_int half_y = terrain_dim_y / 2;
320  n_vect2 point1, point2, point3;
321 
322  if (tc_state == TCS_SHOW_CONTROLS)
323  {
324  vect2_populate(&point1, 5, half_y + TC_OFFSET_Y);
325  vect2_populate(&point2, 5, half_y - TC_OFFSET_Y);
326  vect2_populate(&point3, TC_FRACTION_X - 5, half_y);
327 
328  math_line_vect(&point1, &point2, local_mono);
329  math_line_vect(&point2, &point3, local_mono);
330  math_line_vect(&point3, &point1, local_mono);
331 
332  vect2_populate(&point1, terrain_dim_x - 5, half_y + TC_OFFSET_Y);
333  vect2_populate(&point2, terrain_dim_x - 5, half_y - TC_OFFSET_Y);
334  vect2_populate(&point3, terrain_dim_x - TC_FRACTION_X + 5, half_y);
335 
336  math_line_vect(&point1, &point2, local_mono);
337  math_line_vect(&point2, &point3, local_mono);
338  math_line_vect(&point3, &point1, local_mono);
339  }
340 
341  if (tc_state == TCS_LEFT_STATE_CONTROLS)
342  {
343  vect2_populate(&point1, TC_FRACTION_X - 5, half_y + TC_OFFSET_Y);
344  vect2_populate(&point2, TC_FRACTION_X - 5, half_y - TC_OFFSET_Y);
345  vect2_populate(&point3, 5, half_y);
346 
347  math_line_vect(&point1, &point2, local_mono);
348  math_line_vect(&point2, &point3, local_mono);
349  math_line_vect(&point3, &point1, local_mono);
350  }
351 
352  if (tc_state == TCS_RIGHT_STATE_CONTROLS)
353  {
354  vect2_populate(&point1, terrain_dim_x - TC_FRACTION_X + 5, half_y + TC_OFFSET_Y);
355  vect2_populate(&point2, terrain_dim_x - TC_FRACTION_X + 5, half_y - TC_OFFSET_Y);
356  vect2_populate(&point3, terrain_dim_x - 5, half_y);
357 
358  math_line_vect(&point1, &point2, local_mono);
359  math_line_vect(&point2, &point3, local_mono);
360  math_line_vect(&point3, &point1, local_mono);
361  }
362 }
363 
364 #endif
365 
366 /* shows the about information */
368 {
369  n_join local_draw;
370  n_byte *buffer = draw_pointer(NUM_VIEW);
371 #if (MAP_BITS == 9)
372  n_int line_y_offset = 128 + 24;
373  n_int linx_x_offset = 84;
374  n_int tab_offset = 36;
375 #else
376  n_int line_y_offset = 12;
377  n_int linx_x_offset = 12;
378  n_int tab_offset = 0;
379 #endif
380  if(check_about == 1 || buffer == 0L)
381  {
382  check_about = 0;
383  return;
384  }
385 
386  local_draw.information = buffer;
387  local_draw.pixel_draw = &pixel_map;
388 #if (MAP_BITS == 9)
389  {
390  n_int loop = 0;
391  while (loop < 214)
392  {
393  n_int py = (MAP_DIMENSION/2) - 128 + loop;
394  const n_int px = (MAP_DIMENSION/2) - 200;
395  n_byte * from_point = &buffer[(py*MAP_DIMENSION) + px];
396  io_erase(from_point, 400);
397  loop++;
398  }
399  }
400 #endif
401 
402  draw_string(SHORT_VERSION_NAME, linx_x_offset, line_y_offset, &local_draw);
403  line_y_offset += 12;
404  line_y_offset += 12;
405 #if (MAP_BITS == 9)
406  draw_string(FULL_VERSION_COPYRIGHT, linx_x_offset + tab_offset, line_y_offset, &local_draw);
407  line_y_offset += 12;
408 
409  draw_string(COPYRIGHT_FOLLOW, linx_x_offset + tab_offset, line_y_offset, &local_draw);
410 #else
411  draw_string(COPYRIGHT_DATE, linx_x_offset + tab_offset, line_y_offset, &local_draw);
412  line_y_offset += 12;
413 
414  draw_string(COPYRIGHT_NAME, linx_x_offset + tab_offset, line_y_offset, &local_draw);
415 #endif
416  line_y_offset += 12;
417  line_y_offset += 12;
418 
419  draw_string(FULL_DATE, linx_x_offset, line_y_offset, &local_draw);
420  line_y_offset += 12;
421  line_y_offset += 12;
422 
423  draw_string(platform, linx_x_offset + tab_offset, line_y_offset, &local_draw);
424 #if (MAP_BITS == 9)
425  line_y_offset += 12;
426  line_y_offset += 12;
427 
428  draw_string("This software and Noble Ape are a continuing ", linx_x_offset, line_y_offset, &local_draw);
429  line_y_offset += 12;
430 
431  draw_string("work of Tom Barbalet begun on 13 June 1996.", linx_x_offset, line_y_offset, &local_draw);
432  line_y_offset += 12;
433  line_y_offset += 12;
434 
435  draw_string("No apes or cats were harmed in the writing ", linx_x_offset, line_y_offset, &local_draw);
436  line_y_offset += 12;
437 
438  draw_string("of this software.", linx_x_offset, line_y_offset, &local_draw);
439 #endif
440  check_about = 1;
441 }
442 
443 /* draws a string starting at point (off_x,off_y) */
444 
445 #define ledfir(x, y, dx, dy, c) if(((val >> c)&1)) (*local_draw)((x + off_x + offset),((y + off_y)), dx, dy, local_info)
446 
447 
456 void draw_string_line(n_constant_string str, n_int off_x, n_int off_y, n_join * draw)
457 {
458  n_pixel * local_draw = draw->pixel_draw;
459  void * local_info = draw->information;
460 
461  n_int char_loop = 0;
462  while (str[char_loop] > 31)
463  {
464  n_int val = seg14[conv[str[char_loop] - 32]];
465  n_int offset = char_loop << 3;
466  /* draw the character as a 14-segment LCD/LED output */
467 
468  ledfir(3, 8, 0, 0, 15);
469 
470  ledfir(3, 2, 0, 0, 14);
471 
472  ledfir(1, 0, 4, 0, 13);
473 
474  ledfir(6, 1, 0, 2, 12);
475 
476  ledfir(6, 5, 0, 2, 11);
477 
478  ledfir(1, 8, 4, 0, 10);
479 
480  ledfir(0, 5, 0, 2, 9);
481 
482  ledfir(0, 1, 0, 2, 8);
483 
484  ledfir(4, 4, 1, 0, 7);
485 
486  ledfir(1, 4, 1, 0, 6);
487 
488  ledfir(3, 5, 0, 2, 5);
489 
490  ledfir(4, 6, 0, 1, 4);
491 
492  ledfir(2, 6, -1, 1, 3);
493 
494  ledfir(4, 2, 1, -1, 2);
495 
496  ledfir(1, 1, 1, 1, 1);
497 
498  ledfir(3, 1, 0, 2, 0);
499  char_loop ++;
500  }
501 }
502 
503 
504 static n_byte draw_character_line(n_int px, n_int py, n_int dx, n_int dy, void * data)
505 {
506  return math_join(px, py, dx, dy, data);
507 }
508 
509 void draw_string(n_constant_string str, n_int off_x, n_int off_y, n_join * draw)
510 {
511  n_join local_pixel;
512  local_pixel.pixel_draw = &draw_character_line;
513  local_pixel.information = draw;
514  draw_string_line(str, off_x, off_y, &local_pixel);
515 }
516 
517 
518 /* this is the ocelot landscape algorithm */
519 
520 #define POS_HIRES(num) ((num+(HI_RES_MAP_DIMENSION*2))&(HI_RES_MAP_DIMENSION-1))
521 
522 #define CONVERT_X(x, cx) (n_uint)((POS_HIRES((x)+cx)) )
523 #define CONVERT_Y(y, cy) (n_uint)((POS_HIRES((y)+cy)) << HI_RES_MAP_BITS)
524 
525 #define CONVERT_XY(x,y) (CONVERT_X(x) | CONVERT_Y(y))
526 
527 #define SUBSTA(c) ((c<<8)|c)
528 
529 static n_byte2 color_group[256*3];
530 
532 {
533  0, 0, 0, 0,
534  106, 43, 70, 120,
535  125, 107, 201, 202,
536  128, 255, 255, 239,
537  150, 88, 169, 79,
538  190, 8, 15, 7,
539  208, 208, 216, 206,
540  255, 255, 255, 255
541 };
542 
543 void draw_fit(n_byte * points, n_byte2 * color_fit)
544 {
545  /* performs a linear interpolation of n 8-bit points to 256 16-bit blend values */
546  n_int lp = 0, lp2 = 0;
547  n_int dr = 0, dg = 0, db = 0;
548  n_int ar = 0, ag = 0, ab = 0, cntr = 0;
549  n_int fp = 0, fl = 0, del_c = 0;
550  while (lp < 256)
551  {
552  if (lp == points[cntr])
553  {
554  ar = SUBSTA(points[(cntr) | 1]);
555  ag = SUBSTA(points[(cntr) | 2]);
556  ab = SUBSTA(points[(cntr) | 3]);
557  fp = lp;
558  cntr += 4;
559 
560  if (lp != 255)
561  {
562  fl = points[cntr];
563  del_c = (fl - fp);
564  dr = SUBSTA(points[(cntr) | 1]);
565  dg = SUBSTA(points[(cntr) | 2]);
566  db = SUBSTA(points[(cntr) | 3]);
567  }
568  }
569 
570  if (del_c == 0)
571  {
572  return;
573  }
574 
575  if (lp != 255)
576  {
577  n_int del_a = (fl - lp), del_b = (lp - fp);
578 
579  color_fit[lp2++] = (n_byte2)(((ar * del_a) + (dr * del_b)) / del_c);
580  color_fit[lp2++] = (n_byte2)(((ag * del_a) + (dg * del_b)) / del_c);
581  color_fit[lp2++] = (n_byte2)(((ab * del_a) + (db * del_b)) / del_c);
582  }
583  else
584  {
585  color_fit[lp2++] = (n_byte2)(ar);
586  color_fit[lp2++] = (n_byte2)(ag);
587  color_fit[lp2++] = (n_byte2)(ab);
588  }
589  lp ++;
590  }
591  if (points == land_points)
592  {
593  color_fit[(COLOUR_GREY*3) ] = 0xcccc;
594  color_fit[(COLOUR_GREY*3) + 1] = 0xcccc;
595  color_fit[(COLOUR_GREY*3) + 2] = 0xcccc;
596 
597  color_fit[(COLOUR_YELLOW*3) ] = 0xeeff;
598  color_fit[(COLOUR_YELLOW*3) + 1] = 0xeeff;
599  color_fit[(COLOUR_YELLOW*3) + 2] = 0x2222;
600 
601  color_fit[(COLOUR_RED_DARK*3) ] = (0xeeff * 3) >> 2;
602  color_fit[(COLOUR_RED_DARK*3) + 1] = 0x0000;
603  color_fit[(COLOUR_RED_DARK*3) + 2] = 0x0000;
604 
605  color_fit[(COLOUR_RED*3) ] = 0xeeff;
606  color_fit[(COLOUR_RED*3) + 1] = 0x0000;
607  color_fit[(COLOUR_RED*3) + 2] = 0x0000;
608 
609  io_copy((n_byte *)color_fit, (n_byte *)color_group, sizeof(n_byte2) * 3 * 256);
610  }
611 }
612 
613 void draw_color_time(n_byte2 * color_fit, n_byte2 time)
614 {
615  n_int day_rotation =((time*255)/TIME_DAY_MINUTES);
616  n_int darken = math_sine(day_rotation + 64 + 128, NEW_SD_MULTIPLE/400);
617  n_int loop = 0;
618  n_int sign = 1;
619 
620  if (!toggle_tidedaylight)
621  {
622  if (darken < 1)
623  sign = -1;
624 
625  darken = (darken * darken) / 402;
626  darken = (sign * darken) + 624;
627 
628  while(loop < (COLOUR_GREY * 3))
629  {
630  n_int cg_val = color_group[loop];
631  n_int response = (cg_val * darken) >> 10;
632 
633  color_fit[loop] = (n_byte2)response;
634 
635  loop++;
636  }
637  }
638  while(loop < (256 * 3))
639  {
640  color_fit[loop] = color_group[loop];
641  loop++;
642  }
643 }
644 
645 typedef struct{
651 
655 
658 
659 static void draw_terrain_scan(void * void_dtss, void * xlocation, void * unused)
660 {
662  n_byte * buf_offscr = (n_byte *) dtss->offscreen;
663  n_int scrx = ((n_int *)xlocation)[0];
664  /* take the very bottom pixel */
665  n_int dim_x = dtss->dimensions.x;
666  n_int dim_y1 = dtss->dimensions.y - 1;
667  n_int pixy = (scrx + (dim_x >> 1)) + (dim_y1 * dim_x );
668  n_int actual = dim_y1;
669  /* start with a map point which is below/off the screen */
670  n_int scry = dtss->const_lowdiv2;
671  /* rotated and add offset (which will be &ed off) */
672  n_int big_x = dtss->lowest_s + (scrx * dtss->value_vector.y);
673  /* rotated and sub offset (subtracted further down) */
674  n_int big_y = dtss->lowest_c - (scrx * dtss->value_vector.x);
675  n_byte2 * combined = dtss->combined;
676  n_int co_x = dtss->co_x;
677  n_int co_y = dtss->co_y;
678  n_int valc2 = dtss->value_vector.y << 1;
679  n_int vals2 = dtss->value_vector.x << 1;
680  while(actual > -1)
681  {
682  const n_uint check_change = CONVERT_X((big_x >> 8), co_x) | CONVERT_Y((big_y >> 8), co_y);
683  const n_byte2 value = combined[check_change];
684  const n_int z00 = value & 255;
685  const n_byte col00 = value >> 8;
686 
687  n_int aval = (scry - z00);
688  if (aval < -1) aval = -1;
689 
690  scry--; /* next map point from screen value */
691  big_x -= vals2;
692  big_y -= valc2;
693 
694  while (actual > aval)
695  {
696  buf_offscr[pixy] = col00;
697  pixy -= dim_x;
698  actual--;
699  }
700  }
701  io_free(&xlocation);
702  io_free(&void_dtss);
703 }
704 
705 static void draw_terrain(noble_simulation * local_sim, n_vect2 * dimensions, n_byte threadable)
706 {
707  n_byte * buf_offscr = draw_pointer(NUM_TERRAIN);
708 
709  if (buf_offscr == 0L)
710  {
711  return;
712  }
713 
714  if (local_sim->select == 0L)
715  {
716  io_erase(buf_offscr, dimensions->x * dimensions->y);
717  return;
718  }
719  {
720  const n_int lowest_y = ((dimensions->y + 256) * dimensions->y)/256;
721  noble_being * loc_being = local_sim->select;
723 
724  /* start at the left-most row */
725  n_int scrx = (0 - (dimensions->x >> 1));
726  /* find the central map point */
727  n_int flatval;
728  n_vect2 value_vector;
729 
730  vect2_direction(&value_vector, terrain_turn + 128, 105);
731 
732  vect2_copy(&(dtss.value_vector), &value_vector);
733 
734  dtss.lowest_s = ((value_vector.x * (((lowest_y)) - dimensions->y)));
735  dtss.lowest_c = ((value_vector.y * (((lowest_y)) - dimensions->y)));
736 
737  dtss.co_x = APESPACE_TO_HR_MAPSPACE(being_location_x(loc_being));
738  dtss.co_y = APESPACE_TO_HR_MAPSPACE(being_location_y(loc_being));
739 
740  dtss.combined = (n_byte2 *)local_sim->land->topology_highdef;
741 
742  flatval = dtss.combined[CONVERT_X((HI_RES_MAP_DIMENSION/2), dtss.co_x) | CONVERT_Y((HI_RES_MAP_DIMENSION/2), dtss.co_y)] & 255;
743 
744  if (flatval < WATER_MAP) /* if the central map point is underwater,*/
745  {
746  flatval = WATER_MAP; /* put it on water level */
747  }
748 
749  dtss.const_lowdiv2 = (((lowest_y)) >> 1) + flatval;
750 
751  vect2_copy(&(dtss.dimensions), dimensions);
752 
753  dtss.offscreen = buf_offscr;
754 
755  /* repeat until the right-most row is reached */
756  while (scrx < (dimensions->x - (dimensions->x >> 1)))
757  {
758  n_int * screen_x_location = io_new(sizeof(n_int));
759 
761 
762  io_copy((n_byte *)&dtss, (n_byte *)local_dtss, sizeof(draw_terrain_scan_struct));
763 
764  screen_x_location[0] = scrx;
765 
766  if (threadable)
767  {
768  execute_add(((execute_function*)draw_terrain_scan), (void*)local_dtss, (void*)screen_x_location, 0L);
769  }
770  else
771  {
772  draw_terrain_scan(local_dtss, screen_x_location, 0L);
773  }
774 
775  scrx++; /* next column */
776  }
777  if (threadable)
778  {
780  }
781  }
782 }
783 
784 #define mndivmin 15
785 #define mndivhr 180
786 
787 #define mndivmonth 7
788 #define mndivyear 91
789 
790 /*
791  * kind = 0, erase
792  * kind = 1, draw-cycle
793  */
794 static void draw_meters(noble_simulation * local_sim)
795 {
796  n_land * loc_land = local_sim->land;
797  noble_being * loc_being = local_sim->select;
798  n_pixel * local_draw = &pixel_overlay;
799  n_pixel * local_draw_black = &pixel_black;
800  n_byte * local_info = draw_pointer(NUM_TERRAIN);
801  const n_byte * local_icon;
802  n_int ha1 = 6;
803  n_int ha2 = 0;
804  n_int hr = 0;
805  n_join local_kind;
806  n_join local_kind_black;
807  n_genetics *genetics = being_genetics(loc_being);
808 
809  if (local_info == 0L)
810  {
811  return;
812  }
813 
814  local_kind.pixel_draw = local_draw;
815  local_kind.information = local_info;
816  local_kind_black.pixel_draw = local_draw_black;
817  local_kind_black.information = local_info;
818 
819  while (hr < 41)
820  {
821  if ((hr != 40) && (hr != 0))
822  {
823  math_join(6, 5+hr, 38, 0, &local_kind_black);
824  }
825 
826  if ((hr&1) == 0)
827  {
828  (*local_draw)(5 , 5 + hr, 0, 0, local_info);
829  (*local_draw)(45, 5 + hr, 0, 0, local_info);
830  (*local_draw)(5 + hr, 45, 0, 0, local_info);
831  (*local_draw)(5 + hr, 5, 0, 0, local_info);
832  }
833 
834  hr ++;
835  }
836 
837  hr = 0;
838 
839  while (hr < 12)
840  {
841  n_vect2 hour_clock;
842  vect2_direction(&hour_clock, ((hr << 8) / 12), 320);
843 
844  (void)math_join((25 + (hour_clock.x / 5)), (25 + (hour_clock.y / 5)), (hour_clock.x / 17), (hour_clock.y / 17), &local_kind);
845  hr++;
846  }
847 
848 #define FACING_OFFSIDE ((terrain_dim_x-(512-411)))
849 #define SP_EN_OFFSIDE ((terrain_dim_x-(512-325)))
850 
851 #define GENETICS_X (terrain_dim_x-69)
852 #define GENETICS_Y (55)
853 
854 #define GENDER_X (terrain_dim_x-110)
855 #define GENDER_Y (10)
856 
857  if (local_sim->select)
858  {
859  hr = 0;
860  while (hr < 41)
861  {
862 
863  if ((hr != 40) && (hr != 0))
864  {
865  math_join(51 + 5 + FACING_OFFSIDE, 5+hr, 38, 0, &local_kind_black);
866  math_join(51 + 55 + SP_EN_OFFSIDE, 5+hr, 6, 0, &local_kind_black);
867  math_join(51 + 55 + 18 + SP_EN_OFFSIDE, 5+hr, 6, 0, &local_kind_black);
868  }
869 
870  if ((hr&1) == 0)
871  {
872  (*local_draw)(50 + 5 + FACING_OFFSIDE, 5 + hr, 0, 0, local_info);
873  (*local_draw)(50 + 45+ FACING_OFFSIDE, 5 + hr, 0, 0, local_info);
874  (*local_draw)(50 + 5 + hr+ FACING_OFFSIDE, 45, 0, 0, local_info);
875  (*local_draw)(50 + 5 + hr+ FACING_OFFSIDE, 5, 0, 0, local_info);
876 
877  (*local_draw)(58 + 55 + SP_EN_OFFSIDE, 5 + hr, 0, 0, local_info);
878  (*local_draw)(50 + 55 + SP_EN_OFFSIDE, 5 + hr, 0, 0, local_info);
879 
880  (*local_draw)(58 + 55 + 18 + SP_EN_OFFSIDE, 5 + hr, 0, 0, local_info);
881  (*local_draw)(50 + 55 + 18 + SP_EN_OFFSIDE, 5 + hr, 0, 0, local_info);
882  }
883  hr ++;
884  }
885  hr = 0;
886  while (hr < 9)
887  {
888  (*local_draw)(50 + 55 + hr + SP_EN_OFFSIDE, 5, 0, 0, local_info);
889  (*local_draw)(50 + 55 + hr + SP_EN_OFFSIDE, 45, 0, 0, local_info);
890  (*local_draw)(50 + 55 + 18 + hr + SP_EN_OFFSIDE, 5, 0, 0, local_info);
891  (*local_draw)(50 + 55 + 18 + hr + SP_EN_OFFSIDE, 45, 0, 0, local_info);
892  hr += 2;
893  }
894 
895  hr = 0;
896 
897  while (hr < 8)
898  {
899  n_vect2 facing_clock;
900  vect2_direction(&facing_clock, (hr << 5), 320);
901  (void)math_join((25 + 50 + (facing_clock.x / 5))+ FACING_OFFSIDE, (25 + (facing_clock.y / 5)),
902  (facing_clock.x / 17), (facing_clock.y / 17), &local_kind);
903  hr++;
904  }
905 
906  (void)math_join(50 + 55 + 18+ SP_EN_OFFSIDE, 25, -1, 0, &local_kind);
907  (void)math_join(58 + 55 + 18+ SP_EN_OFFSIDE, 25, 1, 0, &local_kind);
908  (void)math_join(50 + 55 + 18+ SP_EN_OFFSIDE, 15, -2, 0, &local_kind);
909  (void)math_join(58 + 55 + 18+ SP_EN_OFFSIDE, 15, 2, 0, &local_kind);
910  (void)math_join(50 + 55 + 18+ SP_EN_OFFSIDE, 35, -2, 0, &local_kind);
911  (void)math_join(58 + 55 + 18+ SP_EN_OFFSIDE, 35, 2, 0, &local_kind);
912 
913  /* draw genetics */
914  while (ha2 < CHROMOSOMES)
915  {
916  n_uint ha3 = 0;
917  n_genetics genetic_block = genetics[ha2];
918  ha1 = 0;
919  while (ha3 < (sizeof(n_genetics)*4))
920  {
921  n_int four = ( genetic_block >> (ha3 * 2) ) & 3 ;
922  if ( four != 0 )
923  (void)math_join((ha1)+GENETICS_X, GENETICS_Y + (ha2 * 10), 0, 7, &local_kind);
924  ha1++;
925  if ( four == 3 )
926  (void)math_join((ha1)+GENETICS_X, GENETICS_Y + (ha2 * 10), 0, 7, &local_kind);
927  ha1 += 3;
928  ha3++;
929  }
930  ha2++;
931  }
932 
933  /* draw sex */
934  (void)math_join(5+GENDER_X, (10)+GENDER_Y, 5, (11), &local_kind);
935  (void)math_join(10+GENDER_X, (21)+GENDER_Y, 5, (-11), &local_kind);
936  (void)math_join(15+GENDER_X, (10)+GENDER_Y, -10, 0, &local_kind);
937  if (FIND_SEX(GET_I(loc_being)) == SEX_FEMALE)
938  {
939  (void)math_join(10+GENDER_X, (20)+GENDER_Y, 0, (6), &local_kind);
940  (void)math_join(8+GENDER_X, (23)+GENDER_Y, 4, 0, &local_kind);
941  }
942  else
943  {
944  (void)math_join(15+GENDER_X, (10)+GENDER_Y, 4, (-4), &local_kind);
945  (void)math_join(19+GENDER_X, (6)+GENDER_Y, -2, 0, &local_kind);
946  (void)math_join(19+GENDER_X, (6)+GENDER_Y, 0, (2), &local_kind);
947  }
948 
949  /* draw direction facing */
950  {
951  n_vect2 direction_facing;
952 
953  vect2_direction(&direction_facing, 128 + 64+ 256 - terrain_turn + loc_being->direction_facing, 63 * 32);
954 
955  (void)math_join_vect2(75+ FACING_OFFSIDE, 25, &direction_facing, &local_kind);
956  }
957 
958  {
959  n_int local_speed = being_speed(loc_being);
960  n_int local_energy = being_energy(loc_being);
961  n_int local_x = being_location_x(loc_being);
962  n_int local_y = being_location_y(loc_being);
963 
964  if (local_speed != 0)
965  {
966  (void)math_join(106 +SP_EN_OFFSIDE, (45-local_speed), 6, 0, &local_kind);
967  }
968  if (local_energy > 127)
969  {
970  (void)math_join(106 + 18 + SP_EN_OFFSIDE, (45-(local_energy >> 7)), 6, 0, &local_kind);
971 
972  }
973  local_icon = &icns[weather_seven_values(local_sim->land, local_x, local_y) << 7];
974  }
975 
976  }
977  else
978  {
979  /* still give weather even with no Noble Apes */
980  local_icon = &icns[weather_seven_values(local_sim->land, 0, 0) << 7];
981  }
982 
983  {
984  n_vect2 year_hand;
985  n_vect2 month_hand;
986  n_vect2 hour_hand;
987  n_vect2 minute_hand;
988 
989  vect2_direction(&year_hand, ((loc_land->date) << 6) / mndivyear, 5440);
990  vect2_direction(&month_hand, ((loc_land->date) << 6) / mndivmonth, 5440);
991  vect2_direction(&hour_hand, ((loc_land->time) << 6) / mndivhr, 2688);
992  vect2_direction(&minute_hand, ((loc_land->time) << 6) / mndivmin, 2016);
993 
994  vect2_rotate90(&year_hand);
995  vect2_rotate90(&month_hand);
996  vect2_rotate90(&hour_hand);
997  vect2_rotate90(&minute_hand);
998 
999  (void)math_join_vect2(17, 25, &year_hand, &local_kind);
1000  (void)math_join_vect2(33, 25, &month_hand, &local_kind);
1001 
1002  (void)math_join_vect2(25, 25, &hour_hand, &local_kind);
1003  (void)math_join_vect2(25, 25, &minute_hand, &local_kind);
1004  }
1005  ha1 = 0;
1006  while (ha1 < 32)
1007  {
1008  n_uint icon_stripe = (local_icon[(ha1<<2)|3] << 0) | (local_icon[(ha1<<2)|2] << 8)
1009  | (local_icon[(ha1<<2)|1] << 16) | (local_icon[(ha1<<2)|0] << 24);
1010  ha2 = 0;
1011  while ( ha2 < 32 )
1012  {
1013  if ((icon_stripe >> (31-ha2)) & 1)
1014  {
1015  (*local_draw)(5 + ha2, 55 + ha1, 0, 0, local_info);
1016  }
1017  ha2++;
1018  }
1019  ha1++;
1020  }
1021 
1022 }
1023 
1024 #define ACTIVE_PIXEL(px,py) sketch_psetc(POSITIVE_LAND_COORD(px),POSITIVE_LAND_COORD(py),COLOUR_RED)
1025 #define ERASER_PIXEL(px,py) sketch_psetc(POSITIVE_LAND_COORD(px),POSITIVE_LAND_COORD(py), \
1026  (n_byte)local_val)
1027 
1028 /*
1029  * kind = 0, draw normal ape
1030  * kind = 1, draw selected ape
1031  * kind = 2, erase normal ape
1032  * kind = 3, erase selected ape
1033  */
1034 static void draw_apeloc(noble_simulation * sim, noble_being *bei, n_join * draw)
1035 {
1038  n_pixel *local_draw = draw->pixel_draw;
1039  void *local_info = draw->information;
1040  n_int ty;
1041  n_int start = -1, stop = 2;
1042  n_int time_coef = sim->real_time >> 4;
1043  n_int start_point = ((time_coef &3 )) + 3;
1044  ty = start;
1045  while (ty < stop)
1046  {
1047  n_int tx = start;
1048  while (tx < stop)
1049  {
1050  n_int scrx = (magx + tx);
1051  n_int scry = (magy + ty);
1052  (*local_draw)(POSITIVE_LAND_COORD(scrx), POSITIVE_LAND_COORD(scry), 0, 0, local_info);
1053  tx++;
1054  }
1055  ty++;
1056  }
1057  if (bei == sim->select)
1058  {
1059  ty = -1;
1060  while (ty < 2)
1061  {
1062  (*local_draw)(POSITIVE_LAND_COORD(magx + ty), POSITIVE_LAND_COORD(magy - 2 ), 0, 0, local_info);
1063  (*local_draw)(POSITIVE_LAND_COORD(magx + ty), POSITIVE_LAND_COORD(magy + 2 ), 0, 0, local_info);
1064  (*local_draw)(POSITIVE_LAND_COORD(magx - 2 ), POSITIVE_LAND_COORD(magy + ty), 0, 0, local_info);
1065  (*local_draw)(POSITIVE_LAND_COORD(magx + 2 ), POSITIVE_LAND_COORD(magy + ty), 0, 0, local_info);
1066  ty++;
1067  }
1068  start_point++;
1069  }
1070  if (being_awake(sim, bei) && (being_state(bei) & BEING_STATE_SPEAKING))
1071  {
1072  n_int local_facing = ((((being_facing(bei))>>2) + 4) & 63) >> 3;
1073  /* D C
1074  G F
1075 
1076  H E
1077  B A */
1078  n_color8 *local_col = local_info;
1079  local_col->color = COLOUR_GREY;
1080  if(local_facing == 0 || local_facing == 7)
1081  (*local_draw)(POSITIVE_LAND_COORD(magx + start_point ), POSITIVE_LAND_COORD(magy - 2 ),
1082  0, 0, local_info); /* F */
1083  if(local_facing == 1 || local_facing == 0)
1084  (*local_draw)(POSITIVE_LAND_COORD(magx + start_point ), POSITIVE_LAND_COORD(magy + 2 ),
1085  0, 0, local_info); /* E */
1086  if(local_facing == 2 || local_facing == 1)
1087  (*local_draw)(POSITIVE_LAND_COORD(magx + 2 ), POSITIVE_LAND_COORD(magy + start_point ),
1088  0, 0, local_info); /* A */
1089  if(local_facing == 3 || local_facing == 2)
1090  (*local_draw)(POSITIVE_LAND_COORD(magx - 2 ), POSITIVE_LAND_COORD(magy + start_point ),
1091  0, 0, local_info); /* B */
1092  if(local_facing == 4 || local_facing == 3)
1093  (*local_draw)(POSITIVE_LAND_COORD(magx - start_point ), POSITIVE_LAND_COORD(magy + 2 ),
1094  0, 0, local_info); /* H */
1095  if(local_facing == 5 || local_facing == 4)
1096  (*local_draw)(POSITIVE_LAND_COORD(magx - start_point ), POSITIVE_LAND_COORD(magy - 2 ),
1097  0, 0, local_info); /* G */
1098  if(local_facing == 6 || local_facing == 5)
1099  (*local_draw)(POSITIVE_LAND_COORD(magx - 2 ), POSITIVE_LAND_COORD(magy - start_point ),
1100  0, 0, local_info); /* D */
1101  if(local_facing == 7 || local_facing == 6)
1102  (*local_draw)(POSITIVE_LAND_COORD(magx + 2 ), POSITIVE_LAND_COORD(magy - start_point ),
1103  0, 0, local_info); /* C */
1104  }
1105 }
1106 
1107 
1108 /*
1109  * kind = 0, draw normal ape
1110  * kind = 1, draw selected ape
1111  * kind = 2, erase normal ape
1112  * kind = 3, erase selected ape
1113  */
1114 static void draw_apeloc_hires(noble_simulation * sim, noble_being *bei, n_join * draw)
1115 {
1118  n_pixel *local_draw = draw->pixel_draw;
1119  void *local_info = draw->information;
1120  n_int ty;
1121  n_int start = -1, stop = 2;
1122  n_int time_coef = sim->real_time >> 4;
1123  n_int start_point = ((time_coef &3 )) + 3;
1124 
1125  ty = start;
1126  while (ty < stop)
1127  {
1128  n_int tx = start;
1129  while (tx < stop)
1130  {
1131  n_int scrx = (magx + tx);
1132  n_int scry = (magy + ty);
1133  (*local_draw)(POSITIVE_LAND_COORD_HIRES(scrx), POSITIVE_LAND_COORD_HIRES(scry), 0, 0, local_info);
1134  tx++;
1135  }
1136  ty++;
1137  }
1138  if (bei == sim->select)
1139  {
1140  ty = -1;
1141  while (ty < 2)
1142  {
1143  (*local_draw)(POSITIVE_LAND_COORD_HIRES(magx + ty), POSITIVE_LAND_COORD_HIRES(magy - 2 ), 0, 0, local_info);
1144  (*local_draw)(POSITIVE_LAND_COORD_HIRES(magx + ty), POSITIVE_LAND_COORD_HIRES(magy + 2 ), 0, 0, local_info);
1145  (*local_draw)(POSITIVE_LAND_COORD_HIRES(magx - 2 ), POSITIVE_LAND_COORD_HIRES(magy + ty), 0, 0, local_info);
1146  (*local_draw)(POSITIVE_LAND_COORD_HIRES(magx + 2 ), POSITIVE_LAND_COORD_HIRES(magy + ty), 0, 0, local_info);
1147  ty++;
1148  }
1149  start_point++;
1150  }
1151  if (being_awake(sim, bei) && (being_state(bei) & BEING_STATE_SPEAKING))
1152  {
1153  n_int local_facing = ((((being_facing(bei))>>2) + 4) & 63) >> 3;
1154  /* D C
1155  G F
1156 
1157  H E
1158  B A */
1159  n_color8 *local_col = local_info;
1160  local_col->color = COLOUR_GREY;
1161  if(local_facing == 0 || local_facing == 7)
1162  (*local_draw)(POSITIVE_LAND_COORD_HIRES(magx + start_point ), POSITIVE_LAND_COORD_HIRES(magy - 2 ),
1163  0, 0, local_info); /* F */
1164  if(local_facing == 1 || local_facing == 0)
1165  (*local_draw)(POSITIVE_LAND_COORD_HIRES(magx + start_point ), POSITIVE_LAND_COORD_HIRES(magy + 2 ),
1166  0, 0, local_info); /* E */
1167  if(local_facing == 2 || local_facing == 1)
1168  (*local_draw)(POSITIVE_LAND_COORD_HIRES(magx + 2 ), POSITIVE_LAND_COORD_HIRES(magy + start_point ),
1169  0, 0, local_info); /* A */
1170  if(local_facing == 3 || local_facing == 2)
1171  (*local_draw)(POSITIVE_LAND_COORD_HIRES(magx - 2 ), POSITIVE_LAND_COORD_HIRES(magy + start_point ),
1172  0, 0, local_info); /* B */
1173  if(local_facing == 4 || local_facing == 3)
1174  (*local_draw)(POSITIVE_LAND_COORD_HIRES(magx - start_point ), POSITIVE_LAND_COORD_HIRES(magy + 2 ),
1175  0, 0, local_info); /* H */
1176  if(local_facing == 5 || local_facing == 4)
1177  (*local_draw)(POSITIVE_LAND_COORD_HIRES(magx - start_point ), POSITIVE_LAND_COORD_HIRES(magy - 2 ),
1178  0, 0, local_info); /* G */
1179  if(local_facing == 6 || local_facing == 5)
1180  (*local_draw)(POSITIVE_LAND_COORD_HIRES(magx - 2 ), POSITIVE_LAND_COORD_HIRES(magy - start_point ),
1181  0, 0, local_info); /* D */
1182  if(local_facing == 7 || local_facing == 6)
1183  (*local_draw)(POSITIVE_LAND_COORD_HIRES(magx + 2 ), POSITIVE_LAND_COORD_HIRES(magy - start_point ),
1184  0, 0, local_info); /* C */
1185  }
1186 }
1187 
1188 static void draw_region(noble_being * local)
1189 {
1190  n_join local_draw;
1191  n_byte * draw = draw_pointer(NUM_VIEW);
1192  n_int ly = 63;
1193 
1194  if (draw == 0L) return;
1195 
1196  local_draw.information = draw;
1197  local_draw.pixel_draw = &pixel_map_checker;
1198 
1199  while (ly < MAP_DIMENSION)
1200  {
1201  math_line(0, ly, MAP_DIMENSION, ly, &local_draw);
1202  math_line(ly, 0, ly, MAP_DIMENSION, &local_draw);
1203  ly += 64;
1204  }
1205 
1206 #ifdef TERRITORY_ON
1207 
1208  local_draw.pixel_draw = &pixel_map;
1209 
1210  ly = 0;
1211  while (ly < TERRITORY_DIMENSION)
1212  {
1213  n_int lx = 0;
1214  while (lx < TERRITORY_DIMENSION)
1215  {
1216  n_string_block string_draw;
1217  n_int value = local->territory[lx + (ly * TERRITORY_DIMENSION)].familiarity;
1218  if (value)
1219  {
1220  sprintf(string_draw,"%ld",value);
1221  draw_string(string_draw, (lx*64)+2 , (ly*64)+5, &local_draw);
1222  }
1223  lx++;
1224  }
1225  ly++;
1226  }
1227 #endif
1228 }
1229 
1230 static void draw_weather(n_land * local_land)
1231 {
1232  n_int map_dimensions2 = land_map_dimension(local_land)/2;
1233  n_color8 local_col;
1234  n_pixel * local_draw = &pixel_color8;
1235  void * local_info = &local_col;
1236  n_int py = 0;
1237  local_col.color = COLOUR_GREY;
1238  local_col.screen = draw_pointer(NUM_VIEW);
1239  if (local_col.screen == 0L)
1240  {
1241  return;
1242  }
1243  while(py < (map_dimensions2))
1244  {
1245  n_int px = 0;
1246  n_int scr_y = py << 1;
1247  while(px < (map_dimensions2))
1248  {
1249  n_int scr_x = px << 1;
1250  n_int tmp = weather_pressure(local_land, WEATHER_TO_MAPSPACE(px), WEATHER_TO_MAPSPACE(py)); /* from weather dimension to map dimension */
1251  if(tmp > WEATHER_CLOUD)
1252  {
1253  (*local_draw)(scr_x+1, scr_y+1, 0, 0, local_info);
1254  }
1255  if(tmp > WEATHER_RAIN)
1256  {
1257  (*local_draw)(scr_x, scr_y , 0, 0, local_info);
1258  }
1259  px++;
1260  }
1261  py++;
1262  }
1263 }
1264 
1265 static void draw_count_number(n_uint count, n_string value)
1266 {
1267  n_uint lp = 0, division = 1000000;
1268  while (lp < 6)
1269  {
1270  if ((count + 1) > division)
1271  {
1272  if (division != 0)
1273  {
1274  value[lp] = (n_byte)('0' + ((count / division) % 10));
1275  }
1276  else
1277  {
1278  value[lp] = (n_byte)('0');
1279  }
1280  }
1281  division /= 10;
1282  lp++;
1283  }
1284  value[6] = ('0' + ((count / 1) % 10));
1285 }
1286 
1287 static void draw_metrics(n_uint bcps, n_uint fps, n_join * local_mono)
1288 {
1289  n_int offset_y = 100;
1290 
1291  n_string_block bcps_string = {' ', ' ', ' ', ' ', ' ', ' ', 'X', ' ',
1292  'B', 'P', 'S', ' ', ' ', ' ', ' ', ' ', ' ', 0
1293  };
1294  n_string_block fps_string = {' ', ' ', ' ', ' ', ' ', ' ', 'X', ' ',
1295  'F', 'P', 'S', ' ', ' ', ' ', ' ', ' ', ' ', ' ', 0
1296  };
1297 
1298  if (bcps)
1299  {
1300  draw_count_number(bcps, bcps_string);
1301  draw_string(bcps_string, terrain_dim_x - 98, offset_y, local_mono);
1302  offset_y += 18;
1303  }
1304  if (fps)
1305  {
1306  draw_count_number(fps, fps_string);
1307  draw_string(fps_string, terrain_dim_x - 98, offset_y, local_mono);
1308  }
1309 }
1310 
1311 /* draws the rotating brain, this is always draw and never erase */
1312 
1313 #ifdef BRAIN_ON
1314 
1315 static void draw_brain(noble_simulation *local_sim, n_vect2 * dimensions)
1316 {
1317  n_byte draw_big = 1;
1318  if ((local_sim->select == 0L) || (number_errors != 0))
1319  {
1320  return;
1321  }
1322 
1323  {
1324  n_byte * local = being_brain(local_sim->select);
1325  n_join local_mono;
1326  n_uint turn_y = tilt_z;
1327  n_uint turn_z = tilt_y;
1328  n_pixel * local_draw_brain = &pixel_overlay;
1329  void * local_info_brain = draw_pointer(NUM_TERRAIN);
1330  n_int lpx = 0;
1331  n_int loop = 0;
1332  n_int center_x = dimensions->x >> 1;
1333  n_int center_y = dimensions->y >> 1;
1334  n_int act_x2a, term_1a, term_2a;
1335 
1336  n_byte * brainptr = local;
1337  n_byte * obrainptr = &local[ 32 * 32 * 32 ];
1338  n_int a11, a12, a13, a21, a23, a31, a32, a33;
1339 
1340  n_vect2 vect_y, vect_z;
1341 
1342  vect2_direction(&vect_y, turn_y, 105);
1343 
1344  vect2_direction(&vect_z, turn_z, NEW_SD_MULTIPLE/1152);
1345 
1346  a32 = vect_y.x;
1347  a12 = vect_y.y;
1348  a21 = vect_z.x;
1349  a23 = vect_z.y;
1350 
1351  a11 = -((a32 * a23) >> 8);
1352  a13 = ((a32 * a21) >> 8);
1353  a31 = ((a12 * a23) >> 8);
1354  a33 = -((a12 * a21) >> 8);
1355 
1356  local_mono.pixel_draw = &pixel_overlay;
1357  local_mono.information = draw_pointer(NUM_TERRAIN);
1358 
1359  draw_metrics(local_sim->delta_cycles, local_sim->delta_frames, &local_mono);
1360 
1361  if (local == 0L)
1362  {
1363  return;
1364  }
1365 
1366  a12 = (a12 * 1152) >> 8;
1367  a32 = (a32 * 1152) >> 8;
1368  act_x2a = -((a21 + a23) << 4);
1369  term_1a = -((a11 + a12 + a13) << 4);
1370  term_2a = -((a31 + a32 + a33) << 4);
1371  while (lpx < 32)
1372  {
1373  n_int lpy = 0;
1374  n_int term_1 = term_1a;
1375  n_int term_2 = term_2a;
1376  while (lpy < 32)
1377  {
1378  n_int act_x1 = term_1 ;
1379  n_int act_x2 = act_x2a;
1380  n_int act_y1 = term_2 ;
1381  n_int lpz = 0;
1382  while (lpz < 32)
1383  {
1384  if ((brainptr[loop] ^ obrainptr[loop]) >> 5)
1385  {
1386  n_int scr_z = 256 + (act_x1 >> 11);
1387  n_int s_x = ((act_x2 * scr_z) >> 16) + center_x;
1388  n_int s_y = ((act_y1 * scr_z) >> 16) + center_y - 120;
1389  (*local_draw_brain)(s_x, s_y, 0, 0, local_info_brain);
1390  if ((act_x1 > 0) && draw_big)
1391  {
1392  (*local_draw_brain)(s_x - 1, s_y, 0, 0, local_info_brain);
1393  (*local_draw_brain)(s_x + 1, s_y, 0, 0, local_info_brain);
1394  (*local_draw_brain)(s_x, s_y - 1, 0, 0, local_info_brain);
1395  (*local_draw_brain)(s_x, s_y + 1, 0, 0, local_info_brain);
1396  }
1397  }
1398  act_x1 += a13;
1399  act_x2 += a23;
1400  act_y1 += a33;
1401  loop++;
1402  lpz++;
1403  }
1404  term_1 += a12;
1405  term_2 += a32;
1406  lpy++;
1407  }
1408  term_1a += a11;
1409  term_2a += a31;
1410  act_x2a += a21;
1411  lpx++;
1412  }
1413  tilt_y = ( tilt_y + 2 ) & 255;
1414  }
1415 }
1416 #endif
1417 
1418 n_int draw_error(n_constant_string error_text, n_constant_string location, n_int line_number)
1419 {
1420  n_int loop = 0;
1421  n_byte error_char_copy;
1422  n_string_block simulation_date_time = {0};
1423  n_string_block simulation_date_time_error = {0};
1424  noble_simulation * local_sim = sim_sim();
1425  n_land * local_land = local_sim->land;
1426  n_int position = 0;
1427 
1428  if (error_text)
1429  {
1430 #ifdef NOBLE_APE_ASSERT
1431  printf("ERROR: %s\n", error_text);
1432 #endif
1433  if (local_land)
1434  {
1435  io_time_to_string(simulation_date_time, local_land->time, local_land->date);
1436 
1437  io_string_write(simulation_date_time_error, simulation_date_time, &position);
1438  io_string_write(simulation_date_time_error, " ", &position);
1439  }
1440 
1441  if(number_errors == MAX_NUMBER_ERRORS)
1442  {
1443  io_string_write(simulation_date_time_error, " ** Maximum errors reached **" , &position);
1444  }
1445  else
1446  {
1447  io_string_write(simulation_date_time_error, (n_string)error_text, &position);
1448  }
1449  }
1450  else
1451  {
1452  number_errors = 0;
1453  return 0;
1454  }
1455 
1457  {
1458  io_console_out(simulation_date_time_error);
1459  return -1;
1460  }
1461  do
1462  {
1463  error_char_copy = error_array[number_errors][loop] = simulation_date_time_error[loop];
1464  loop++;
1465  }
1466  while((loop < STRING_BLOCK_SIZE) && (error_char_copy != 0));
1467 
1468  error_array[number_errors][loop] = 0;
1469 
1470  if(number_errors != MAX_NUMBER_ERRORS)
1471  {
1472  number_errors++;
1473  }
1474  return -1;
1475 }
1476 
1477 static void draw_remains(noble_simulation * sim, n_byte * screen)
1478 {
1479  noble_remains * remains = sim->remains;
1480  n_int loop = 0;
1481  while(loop < remains->count)
1482  {
1483  dead_body * body = &(remains->bodies[loop]);
1484  n_int px = body->location[0];
1485  n_int py = body->location[1];
1486  n_int mx = APESPACE_TO_MAPSPACE(px);
1487  n_int my = APESPACE_TO_MAPSPACE(py);
1488 
1489  n_int lx = 510;
1490 
1491  while (lx < 515)
1492  {
1493  screen[((mx + lx)&(MAP_DIMENSION-1)) + (((my)&(MAP_DIMENSION-1)) * MAP_DIMENSION)] = COLOUR_YELLOW;
1494  screen[((mx)&(MAP_DIMENSION-1)) + (((my + lx)&(MAP_DIMENSION-1)) * MAP_DIMENSION)] = COLOUR_YELLOW;
1495  lx++;
1496  }
1497  loop++;
1498  }
1499 }
1500 
1501 static void draw_tides(n_byte * map, n_byte * screen, n_byte tide)
1502 {
1503  n_byte tide_compress[45];
1504  n_int lp = 0;
1505  n_byte tide_point = tide - 106;
1506  n_int ar = 106;
1507  n_int dr = 128;
1508  n_int fl = tide_point;
1509  n_int fp = 0;
1510 
1511  if (toggle_tidedaylight)
1512  {
1513  return;
1514  }
1515 
1516  while (lp < 45)
1517  {
1518  tide_compress[lp] = (n_byte)(((ar * (fl - lp)) + (dr * (lp - fp))) / (fl-fp));
1519  if (lp == tide_point)
1520  {
1521  ar = 128;
1522  dr = 150;
1523  fl = 150 - 106;
1524  fp = tide_point;
1525  }
1526  lp++;
1527  }
1528 
1529  lp = 0;
1530  while (lp < MAP_AREA)
1531  {
1532  n_byte val = map[lp];
1533  if ((val > 105) && (val < 151))
1534  {
1535  screen[lp] = tide_compress[val - 106];
1536  }
1537  lp++;
1538  }
1539 }
1540 
1541 static void draw_tides_hi_res(n_byte * data, n_byte4 * block, n_byte tide)
1542 {
1543  n_byte tide_compress[45];
1544  n_uint lp = 0;
1545  n_byte tide_point = tide - 106;
1546  n_int ar = 106;
1547  n_int dr = 128;
1548  n_int fl = tide_point;
1549  n_int fp = 0;
1550 
1551  if (toggle_tidedaylight)
1552  {
1553  return;
1554  }
1555 
1556  while (lp < 45)
1557  {
1558  tide_compress[lp] = (n_byte)(((ar * (fl - lp)) + (dr * (lp - fp))) / (fl-fp));
1559  if (lp == tide_point)
1560  {
1561  ar = 128;
1562  dr = 150;
1563  fl = 150 - 106;
1564  fp = tide_point;
1565  }
1566  lp++;
1567  }
1568  lp = 0;
1569  while (lp < HI_RES_MAP_AREA)
1570  {
1571  n_byte4 block_group = block[lp >> 5];
1572 
1573  if (block_group != 0)
1574  {
1575  n_int local_loop = lp<<1;
1576  n_int local_loop_end = local_loop+64;
1577  n_int lp = 0;
1578  while (local_loop < local_loop_end)
1579  {
1580  if ((block_group >> lp) & 1)
1581  {
1582  data[local_loop|1] = tide_compress[data[local_loop] - 106];
1583  }
1584  local_loop += 2;
1585  lp++;
1586  }
1587  }
1588  lp += 32;
1589  }
1590 }
1591 
1592 
1593 static void draw_apes_loop(noble_simulation * local_sim, noble_being * bei, void * data)
1594 {
1595  n_join local_8bit;
1596  n_color8 local_col;
1597 
1598  /* makes this use thread safe */
1599  io_copy(data, (n_byte*)&local_col, sizeof(n_color8));
1600 
1601  if (being_los(local_sim->land, local_sim->select, (n_byte2)being_location_x(bei), (n_byte2)being_location_y(bei)) == 1)
1602  {
1603  local_col.color = COLOUR_RED;
1604  }
1605  else
1606  {
1607  local_col.color = COLOUR_RED_DARK;
1608  }
1609 
1610  if (local_col.screen == local_sim->land->topology_highdef)
1611  {
1612  local_8bit.pixel_draw = &pixel_color8_hires;
1613  }
1614  else
1615  {
1616  local_8bit.pixel_draw = &pixel_color8;
1617  }
1618 
1619  local_8bit.information = &local_col;
1620 
1621  if (local_col.screen == local_sim->land->topology_highdef)
1622  {
1623  draw_apeloc_hires(local_sim, bei, &local_8bit);
1624  }
1625  else
1626  {
1627  draw_apeloc(local_sim, bei, &local_8bit);
1628  }
1629 
1630 }
1631 
1632 static void draw_apes(noble_simulation * local_sim, n_byte lores)
1633 {
1634  n_color8 local_col;
1635 
1636  if (lores == 0) /* set up drawing environ */
1637  {
1638  draw_undraw();
1639  local_col.screen = local_sim->land->topology_highdef;
1640  }
1641  else
1642  {
1643  local_col.screen = draw_pointer(NUM_VIEW);
1644  io_copy(local_sim->land->topology, local_col.screen, MAP_AREA);
1645  }
1646 
1647  if (lores == 0)
1648  {
1649  static n_byte local_tide;
1650  if (local_tide != local_sim->land->tide_level)
1651  {
1652  local_tide = local_sim->land->tide_level;
1653  draw_tides_hi_res(local_sim->land->topology_highdef, local_sim->land->highres_tide, local_tide);
1654  }
1655  }
1656  else
1657  {
1658  draw_tides(local_sim->land->topology, local_col.screen, local_sim->land->tide_level);
1659  if (toggle_territory)
1660  {
1661  draw_region(local_sim->select);
1662  }
1663  draw_remains(local_sim, local_col.screen);
1664  }
1665 
1666  if (local_sim->select)
1667  {
1668  being_loop_no_thread(local_sim, 0L, draw_apes_loop, &local_col);
1669  }
1670 
1671 }
1672 
1673 static void draw_errors(noble_simulation * local_sim)
1674 {
1675  n_join local_mono;
1676  local_mono.pixel_draw = &pixel_overlay;
1677  local_mono.information = draw_pointer(NUM_TERRAIN);
1678  if(number_errors != 0)
1679  {
1680  n_int loop = 0;
1681  while(loop< (number_errors+1))
1682  {
1683  draw_string(error_array[loop], 40, (loop*12) + 62, &local_mono);
1684  loop++;
1685  }
1686  }
1687 }
1688 
1689 static void draw_line_braincode(n_string pointer, n_int line)
1690 {
1691  n_join local_mono;
1692  local_mono.pixel_draw = &pixel_grey;
1693  local_mono.information = draw_pointer(NUM_TERRAIN);
1694  draw_string(pointer, 4 + (terrain_dim_x/2) - 256, (line*12) + 246 + (terrain_dim_y/2) - 256, &local_mono);
1695 }
1696 
1697 void draw_terrain_coord(n_int * co_x, n_int * co_y)
1698 {
1699  *co_x = terrain_dim_x;
1700  *co_y = terrain_dim_y;
1701 }
1702 
1703 
1704 void draw_window(n_int dim_x, n_int dim_y)
1705 {
1706  terrain_dim_x = dim_x;
1707  terrain_dim_y = dim_y;
1708 }
1709 
1711 {
1712  noble_simulation * local_sim = sim_sim();
1713  n_vect2 local_vect;
1714  n_join local_mono;
1715 
1716  if (sim_new()) return 0;
1717  if (check_about) return 0;
1718 
1719  local_mono.pixel_draw = &pixel_overlay;
1720  local_mono.information = draw_pointer(NUM_TERRAIN);
1721 
1722  local_vect.x = terrain_dim_x;
1723  local_vect.y = terrain_dim_y;
1724 
1725  draw_apes(local_sim, 0); /* hi res */
1726  draw_apes(local_sim, 1); /* lo res */
1727 
1728 #ifdef EXECUTE_THREADED
1729  /* TODO: Make the threaded draw command line safe */
1731  {
1732  draw_terrain(local_sim, &local_vect, 0);
1733  }
1734  else
1735  {
1736  draw_terrain(local_sim, &local_vect, 1);
1737  }
1738 #else
1739  draw_terrain(local_sim, &local_vect, 0);
1740 #endif
1741  draw_meters(local_sim);
1742  draw_errors(local_sim); /* 12 */
1743 
1744 #ifdef BRAIN_ON
1745  if (toggle_brain)
1746  {
1747  draw_brain(local_sim, &local_vect);
1748  }
1749 #else
1750  {
1751  draw_metrics(0, local_sim->delta_frames, &local_mono);
1752  }
1753 #endif
1754 
1755 #ifdef BRAINCODE_ON
1756  if (toggle_braincode)
1757  {
1758  console_populate_braincode(local_sim, draw_line_braincode);
1759  }
1760 #endif
1761 
1762 
1763 #ifdef WEATHER_ON
1764  if (toggle_weather)
1765  {
1766  draw_weather(local_sim->land); /* 10 */
1767  }
1768 #endif
1769 
1770 #ifdef MULTITOUCH_CONTROLS
1771  draw_tc_controls(&local_mono);
1772 #endif
1773  return 0;
1774 }