fix 24bit wire mode
[micropolis] / src / sim / g_map.c
CommitLineData
6a5fa4e0
MG
1/* g_map.c
2 *
3 * Micropolis, Unix Version. This game was released for the Unix platform
4 * in or about 1990 and has been modified for inclusion in the One Laptop
5 * Per Child program. Copyright (C) 1989 - 2007 Electronic Arts Inc. If
6 * you need assistance with this program, you may contact:
7 * http://wiki.laptop.org/go/Micropolis or email micropolis@laptop.org.
8 *
9 * This program is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 3 of the License, or (at
12 * your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details. You should have received a
18 * copy of the GNU General Public License along with this program. If
19 * not, see <http://www.gnu.org/licenses/>.
20 *
21 * ADDITIONAL TERMS per GNU GPL Section 7
22 *
23 * No trademark or publicity rights are granted. This license does NOT
24 * give you any right, title or interest in the trademark SimCity or any
25 * other Electronic Arts trademark. You may not distribute any
26 * modification of this program using the trademark SimCity or claim any
27 * affliation or association with Electronic Arts Inc. or its employees.
28 *
29 * Any propagation or conveyance of this program must include this
30 * copyright notice and these terms.
31 *
32 * If you convey this program (or any modifications of it) and assume
33 * contractual liability for the program to recipients of it, you agree
34 * to indemnify Electronic Arts for any liability that those contractual
35 * assumptions impose on Electronic Arts.
36 *
37 * You may not misrepresent the origins of this program; modified
38 * versions of the program must be marked as such and not identified as
39 * the original program.
40 *
41 * This disclaimer supplements the one included in the General Public
42 * License. TO THE FULLEST EXTENT PERMISSIBLE UNDER APPLICABLE LAW, THIS
43 * PROGRAM IS PROVIDED TO YOU "AS IS," WITH ALL FAULTS, WITHOUT WARRANTY
44 * OF ANY KIND, AND YOUR USE IS AT YOUR SOLE RISK. THE ENTIRE RISK OF
45 * SATISFACTORY QUALITY AND PERFORMANCE RESIDES WITH YOU. ELECTRONIC ARTS
46 * DISCLAIMS ANY AND ALL EXPRESS, IMPLIED OR STATUTORY WARRANTIES,
47 * INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY, SATISFACTORY QUALITY,
48 * FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT OF THIRD PARTY
49 * RIGHTS, AND WARRANTIES (IF ANY) ARISING FROM A COURSE OF DEALING,
50 * USAGE, OR TRADE PRACTICE. ELECTRONIC ARTS DOES NOT WARRANT AGAINST
51 * INTERFERENCE WITH YOUR ENJOYMENT OF THE PROGRAM; THAT THE PROGRAM WILL
52 * MEET YOUR REQUIREMENTS; THAT OPERATION OF THE PROGRAM WILL BE
53 * UNINTERRUPTED OR ERROR-FREE, OR THAT THE PROGRAM WILL BE COMPATIBLE
54 * WITH THIRD PARTY SOFTWARE OR THAT ANY ERRORS IN THE PROGRAM WILL BE
55 * CORRECTED. NO ORAL OR WRITTEN ADVICE PROVIDED BY ELECTRONIC ARTS OR
56 * ANY AUTHORIZED REPRESENTATIVE SHALL CREATE A WARRANTY. SOME
57 * JURISDICTIONS DO NOT ALLOW THE EXCLUSION OF OR LIMITATIONS ON IMPLIED
58 * WARRANTIES OR THE LIMITATIONS ON THE APPLICABLE STATUTORY RIGHTS OF A
59 * CONSUMER, SO SOME OR ALL OF THE ABOVE EXCLUSIONS AND LIMITATIONS MAY
60 * NOT APPLY TO YOU.
61 */
62#include "sim.h"
63
64
65#define VAL_NONE 0
66#define VAL_LOW 1
67#define VAL_MEDIUM 2
68#define VAL_HIGH 3
69#define VAL_VERYHIGH 4
70#define VAL_PLUS 5
71#define VAL_VERYPLUS 6
72#define VAL_MINUS 7
73#define VAL_VERYMINUS 8
74
75short valMap[] = {
76 -1, COLOR_LIGHTGRAY, COLOR_YELLOW, COLOR_ORANGE, COLOR_RED,
77 COLOR_DARKGREEN, COLOR_LIGHTGREEN, COLOR_ORANGE, COLOR_YELLOW
78};
79
80short valGrayMap[] = {
81 -1, 31, 127, 191, 255,
82 223, 255, 31, 0
83};
84
85
86int (*mapProcs[NMAPS])();
87
88int drawAll(SimView *view);
89int drawRes(SimView *view);
90int drawCom(SimView *view);
91int drawInd(SimView *view);
92int drawPower(SimView *view);
93int drawLilTransMap(SimView *view);
94int drawPopDensity(SimView *view);
95int drawRateOfGrowth(SimView *view);
96int drawTrafMap(SimView *view);
97int drawPolMap(SimView *view);
98int drawCrimeMap(SimView *view);
99int drawLandMap(SimView *view);
100int drawFireRadius(SimView *view);
101int drawPoliceRadius(SimView *view);
102int drawDynamic(SimView *view);
103
104
105short GetCI(short x)
106{
107 if (x < 50) return(VAL_NONE);
108 if (x < 100) return(VAL_LOW);
109 if (x < 150) return(VAL_MEDIUM);
110 if (x < 200) return(VAL_HIGH);
111 return(VAL_VERYHIGH);
112}
113
114
115drawPopDensity(SimView *view)
116{
117 short x, y;
118
119 drawAll(view);
120 for (x = 0; x < HWLDX; x++) {
121 for (y = 0; y < HWLDY; y++) {
122 maybeDrawRect(view, GetCI(PopDensity[x][y]),
123 x * 6, y * 6, 6, 6);
124 }
125 }
126}
127
128
129drawRateOfGrowth(SimView *view)
130{
131 short x, y;
132
133 drawAll(view);
134 for (x = 0; x < SmX; x++) {
135 for (y = 0; y < SmY; y++) {
136 short val, z = RateOGMem[x][y];
137
138 if (z > 100) val = VAL_VERYPLUS;
139 else {
140 if (z > 20) val = VAL_PLUS;
141 else {
142 if (z < -100) val = VAL_VERYMINUS;
143 else {
144 if (z < -20) val = VAL_MINUS;
145 else val = VAL_NONE;
146 }
147 }
148 }
149 maybeDrawRect(view, val,
150 x * 24, y * 24, 24, 24);
151 }
152 }
153}
154
155
156drawTrafMap(SimView *view)
157{
158 short x;
159 short y;
160
161 drawLilTransMap(view);
162
163 for (x = 0; x < HWLDX; x++) {
164 for (y = 0; y < HWLDY; y++) {
165 maybeDrawRect(view, GetCI(TrfDensity[x][y]),
166 x * 6, y * 6, 6, 6);
167 }
168 }
169}
170
171
172drawPolMap(SimView *view)
173{
174 short x, y;
175
176 drawAll(view);
177
178 for (x = 0; x < HWLDX; x++) {
179 for (y = 0; y < HWLDY; y++) {
180 maybeDrawRect(view, GetCI(10 + PollutionMem[x][y]),
181 x * 6, y * 6, 6, 6);
182 }
183 }
184}
185
186
187drawCrimeMap(SimView *view)
188{
189 short x, y;
190
191 drawAll(view);
192
193 for (x = 0; x < HWLDX; x++) {
194 for (y = 0; y < HWLDY; y++) {
195 maybeDrawRect(view, GetCI(CrimeMem[x][y]),
196 x * 6, y * 6, 6, 6);
197 }
198 }
199}
200
201
202drawLandMap(SimView *view)
203{
204 short x, y;
205
206 drawAll(view);
207
208 for (x = 0; x < HWLDX; x++) {
209 for (y = 0; y < HWLDY; y++) {
210 maybeDrawRect(view, GetCI(LandValueMem[x][y]),
211 x * 6, y * 6, 6, 6);
212 }
213 }
214}
215
216
217drawFireRadius(SimView *view)
218{
219 short x, y;
220
221 drawAll(view);
222 for (x = 0; x < SmY; x++) {
223 for (y = 0; y < SmY; y++) {
224 maybeDrawRect(view, GetCI(FireRate[x][y]),
225 x * 24, y * 24, 24, 24);
226 }
227 }
228}
229
230
231drawPoliceRadius(SimView *view)
232{
233 short x, y;
234
235 drawAll(view);
236 for (x = 0; x < SmX; x++) {
237 for (y = 0; y < SmY; y++) {
238 maybeDrawRect(view, GetCI(PoliceMapEffect[x][y]),
239 x * 24, y * 24, 24, 24);
240 }
241 }
242}
243
244
245setUpMapProcs(void)
246{
247 mapProcs[ALMAP] = drawAll;
248 mapProcs[REMAP] = drawRes;
249 mapProcs[COMAP] = drawCom;
250 mapProcs[INMAP] = drawInd;
251 mapProcs[PRMAP] = drawPower;
252 mapProcs[RDMAP] = drawLilTransMap;
253 mapProcs[PDMAP] = drawPopDensity;
254 mapProcs[RGMAP] = drawRateOfGrowth;
255 mapProcs[TDMAP] = drawTrafMap;
256 mapProcs[PLMAP] = drawPolMap;
257 mapProcs[CRMAP] = drawCrimeMap;
258 mapProcs[LVMAP] = drawLandMap;
259 mapProcs[FIMAP] = drawFireRadius;
260 mapProcs[POMAP] = drawPoliceRadius;
261 mapProcs[DYMAP] = drawDynamic;
262}
263
264
265MemDrawMap(SimView *view)
266{
267 (*mapProcs[view->map_state])(view);
268 if (!view->x->color) {
269 ditherMap(view);
270 XSetForeground(view->x->dpy, view->x->gc, view->pixels[COLOR_BLACK]);
271 XSetBackground(view->x->dpy, view->x->gc, view->pixels[COLOR_WHITE]);
272 XPutImage(view->x->dpy, view->pixmap, view->x->gc, view->image,
273 0, 0, 0, 0, view->m_width, view->m_height);
274 }
275}
276
277
278ditherMap(SimView *view)
279{
280 int i, x, y, width, height;
281 int err, pixel1, pixel8;
282 int line_bytes1 = view->line_bytes;
283 int line_bytes8 = view->line_bytes8;
284 unsigned char *image1 = view->data;
285 unsigned char *image8 = view->data8;
286 int *errors;
287
288 width = view->m_width; height = view->m_height;
289
290 errors = (int *)malloc(sizeof(int) * (width));
291
292 for (i = 0; i < width; i++)
293 errors[i] = (Rand16() & 15) - 7;
294
295 err = (Rand16() & 15) - 7;
296
297 for (y = 0; y < height; y += 2) {
298 unsigned char *i1 = image1;
299 unsigned char *i8 = image8;
300
301 image1 += line_bytes1;
302 image8 += line_bytes8;
303
304 for (x = 0; x < width; x += 8) {
305 pixel1 = 0;
306 for (i = 0; i < 8; i++) {
307 pixel1 <<= 1;
308 pixel8 = *(i8++) + err + errors[x + i];
309 if (pixel8 > 127) {
310 err = pixel8 - 255;
311 } else {
312 pixel1 |= 1;
313 err = pixel8;
314 }
315 errors[x + i] = err/2;
316 err = err/2;
317 }
318 *(i1++) = pixel1;
319 }
320
321 i1 = image1 + (width / 8) - 1;
322 i8 = image8 + width - 1;
323
324 image1 += line_bytes1;
325 image8 += line_bytes8;
326
327 for (x = width - 8; x >= 0; x -= 8) {
328 pixel1 = 0;
329 for (i = 7; i >= 0; i--) {
330 pixel1 >>= 1;
331 pixel8 = *(i8--) + err + errors[x + i];
332 if (pixel8 > 127) {
333 err = pixel8 - 255;
334 } else {
335 pixel1 |= 128;
336 err = pixel8;
337 }
338 errors[x + i] = err/2;
339 err = err/2;
340 }
341 *(i1--) = pixel1;
342 }
343 }
344
345 free(errors);
346}
347
348
349maybeDrawRect(SimView *view, int val,
350 int x, int y, int w, int h)
351{
352 if (val == VAL_NONE) return;
353
354 if (view->x->color) {
355 drawRect(view, view->pixels[valMap[val]], 0, x, y, w, h);
356 } else {
357 drawRect(view, valGrayMap[val], 1, x, y, w, h);
358 }
359}
360
361
362drawRect(SimView *view, int pixel, int solid,
363 int x, int y, int w, int h)
364{
365 int W = view->m_width, H = view->m_height;
366
367 if (x < 0) {
368 if ((w += x) < 0) w = 0;
369 x = 0;
370 } else if (x > W) {
371 x = 0; w = 0;
372 }
373 if (x + w > W) {
374 w = W - x;
375 }
376 if (y < 0) {
377 if ((h += y) < 0) h = 0;
378 y = 0;
379 } else if (y > H) {
380 y = 0; h = 0;
381 }
382 if (y + h > H) {
383 h = H - y;
384 }
385
386 if (w && h) {
387 int i, j, stipple = (x ^ y) & 1;
388 unsigned char *data =
389 view->x->color ? view->data : view->data8;
390
391 /* In the case of black and white, we use an 8 bit buffer and dither it. */
392 int pixelBytes =
393 view->x->color ? view->pixel_bytes : 1;
394 QUAD line =
395 view->x->color ? view->line_bytes : view->line_bytes8;
396
397 unsigned char *image =
398 &(data[(line * y) + (x * pixelBytes)]);
399
400 switch (pixelBytes) {
401
402 case 1:
403 {
404 unsigned char *data =
405 view->data8;
406 unsigned char *image =
407 &data[(line * y) + (x * pixelBytes)];
408
409 if (solid) {
410 for (i = h; i > 0; i--) {
411 for (j = w; j > 0; j--) {
412 *image = pixel;
413 image++;
414 }
415 image += line - w;
416 }
417 } else {
418 for (i = h; i > 0; i--) {
419 for (j = w; j > 0; j--) {
420 if (stipple++ & 1)
421 *image = pixel;
422 image++;
423 }
424 if (!(w & 1))
425 stipple++;
426 image += line - w;
427 }
428 }
429 }
430 break;
431
432 case 2:
433 {
434 unsigned short *data =
435 (unsigned short *)view->data;
436 unsigned short *image;
437 line >>= 1; /* Convert from byte offset to short offset */
438 image =
439 &data[(line * y) + x];
440
441 if (solid) {
442 for (i = h; i > 0; i--) {
443 for (j = w; j > 0; j--) {
444 *image = pixel;
445 image++;
446 }
447 image += line - w;
448 }
449 } else {
450 for (i = h; i > 0; i--) {
451 for (j = w; j > 0; j--) {
452 if (stipple++ & 1)
453 *image = pixel;
454 image++;
455 }
456 if (!(w & 1))
457 stipple++;
458 image += line - w;
459 }
460 }
461 }
462 break;
463
464 case 3:
465 case 4:
466 {
467 unsigned char *data =
468 (unsigned char *)view->data;
469 unsigned char *image;
6a5fa4e0 470 image =
93200beb 471 &data[(line * y) + x * pixelBytes];
6a5fa4e0
MG
472
473 if (solid) {
474 for (i = h; i > 0; i--) {
475 for (j = w; j > 0; j--) {
476 *(image++) = (pixel >> 0) & 0xff;
477 *(image++) = (pixel >> 8) & 0xff;
478 *(image++) = (pixel >> 16) & 0xff;
93200beb 479 if (pixelBytes == 4) {
6a5fa4e0
MG
480 image++;
481 }
482 }
93200beb 483 image += line - w * pixelBytes;
6a5fa4e0
MG
484 }
485 } else {
486 for (i = h; i > 0; i--) {
487 for (j = w; j > 0; j--) {
488 if (stipple++ & 1) {
489 *(image++) = (pixel >> 0) & 0xff;
490 *(image++) = (pixel >> 8) & 0xff;
491 *(image++) = (pixel >> 16) & 0xff;
93200beb
MG
492 } else {
493 image += 3;
494 }
495 if (pixelBytes == 4) {
496 image++;
6a5fa4e0
MG
497 }
498 }
499 if (!(w & 1)) {
500 stipple++;
501 }
93200beb 502 image += line - w * pixelBytes;
6a5fa4e0
MG
503 }
504 }
505 }
506 break;
507
508 default:
509 assert(0); /* Undefined depth */
510 break;
511 }
512
513 }
514}
515
516
517
Impressum, Datenschutz