]> git.zerfleddert.de Git - micropolis/blob - src/sim/s_fileio.c
show description (including time limit) when hovering over a scenario
[micropolis] / src / sim / s_fileio.c
1 /* s_fileio.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 SWAP_SHORTS(a,b) _swap_shorts(a,b)
66 #define SWAP_LONGS(a,b) _swap_longs(a,b)
67 #define HALF_SWAP_LONGS(a,b) _half_swap_longs(a,b)
68
69 #define NOOP_ON_BE { int test = 1; if (!(*(unsigned char*) (&test))) return; }
70
71 static void
72 _swap_shorts(short *buf, int len)
73 {
74 int i;
75
76 NOOP_ON_BE;
77
78 /* Flip bytes in each short! */
79 for (i = 0; i < len; i++) {
80 *buf = ((*buf & 0xFF) <<8) | ((*buf &0xFF00) >>8);
81 buf++;
82 }
83 }
84
85 static void
86 _swap_longs(long *buf, int len)
87 {
88 int i;
89
90 NOOP_ON_BE;
91
92 /* Flip bytes in each long! */
93 for (i = 0; i < len; i++) {
94 long l = *buf;
95 *buf =
96 ((l & 0x000000ff) << 24) |
97 ((l & 0x0000ff00) << 8) |
98 ((l & 0x00ff0000) >> 8) |
99 ((l & 0xff000000) >> 24);
100 buf++;
101 }
102 }
103
104 static void
105 _half_swap_longs(long *buf, int len)
106 {
107 int i;
108
109 NOOP_ON_BE
110
111 /* Flip bytes in each long! */
112 for (i = 0; i < len; i++) {
113 long l = *buf;
114 *buf =
115 ((l & 0x0000ffff) << 16) |
116 ((l & 0xffff0000) >> 16);
117 buf++;
118 }
119 }
120
121 static int
122 _load_short(short *buf, int len, FILE *f)
123 {
124 if (fread(buf, sizeof(short), len, f) != len)
125 return 0;
126
127 SWAP_SHORTS(buf, len); /* to intel */
128
129 return 1;
130 }
131
132
133 static int
134 _load_long(long *buf, int len, FILE *f)
135 {
136 if (fread(buf, sizeof(long), len, f) != len)
137 return 0;
138
139 SWAP_LONGS(buf, len); /* to intel */
140
141 return 1;
142 }
143
144
145 static int
146 _save_short(short *buf, int len, FILE *f)
147 {
148
149 SWAP_SHORTS(buf, len); /* to MAC */
150
151 if (fwrite(buf, sizeof(short), len, f) != len)
152 return 0;
153
154 SWAP_SHORTS(buf, len); /* back to intel */
155
156 return 1;
157 }
158
159
160 static int
161 _save_long(long *buf, int len, FILE *f)
162 {
163
164 SWAP_LONGS(buf, len); /* to MAC */
165
166 if (fwrite(buf, sizeof(long), len, f) != len)
167 return 0;
168
169 SWAP_LONGS(buf, len); /* back to intel */
170
171 return 1;
172 }
173
174
175 static
176 int
177 _load_file(char *filename, char *dir)
178 {
179 FILE *f;
180 char path[512];
181 QUAD size;
182
183 #ifdef MSDOS
184 if (dir != NULL) {
185 sprintf(path, "%s\\%s", dir, filename);
186 filename = path;
187 }
188 if ((f = fopen(filename, "rb")) == NULL) {
189 return 0;
190 }
191 #else
192 if (dir != NULL) {
193 sprintf(path, "%s/%s", dir, filename);
194 filename = path;
195 }
196 if ((f = fopen(filename, "r")) == NULL) {
197 return (0);
198 }
199 #endif
200
201 fseek(f, 0L, SEEK_END);
202 size = ftell(f);
203 fseek(f, 0L, SEEK_SET);
204
205 switch (size) {
206 case 27120: /* Normal city */
207 break;
208
209 case 99120: /* 2x2 city */
210 break;
211
212 case 219120: /* 3x3 city */
213 break;
214
215 default:
216 return (0);
217 }
218
219 if ((_load_short(ResHis, HISTLEN / 2, f) == 0) ||
220 (_load_short(ComHis, HISTLEN / 2, f) == 0) ||
221 (_load_short(IndHis, HISTLEN / 2, f) == 0) ||
222 (_load_short(CrimeHis, HISTLEN / 2, f) == 0) ||
223 (_load_short(PollutionHis, HISTLEN / 2, f) == 0) ||
224 (_load_short(MoneyHis, HISTLEN / 2, f) == 0) ||
225 (_load_short(MiscHis, MISCHISTLEN / 2, f) == 0) ||
226 (_load_short((&Map[0][0]), WORLD_X * WORLD_Y, f) < 0)) {
227
228 /* TODO: report error */
229 fclose(f);
230 return(0);
231 }
232
233 fclose(f);
234 return(1);
235 }
236
237
238 int loadFile(char *filename)
239 {
240 long l;
241
242 if (_load_file(filename, NULL) == 0)
243 return(0);
244
245 /* total funds is a long..... MiscHis is array of shorts */
246 /* total funds is being put in the 50th & 51th word of MiscHis */
247 /* find the address, cast the ptr to a lontPtr, take contents */
248
249 l = *(QUAD *)(MiscHis + 50);
250 HALF_SWAP_LONGS(&l, 1);
251 SetFunds(l);
252
253 l = *(QUAD *)(MiscHis + 8);
254 HALF_SWAP_LONGS(&l, 1);
255 CityTime = l;
256
257 autoBulldoze = MiscHis[52]; /* flag for autoBulldoze */
258 autoBudget = MiscHis[53]; /* flag for autoBudget */
259 autoGo = MiscHis[54]; /* flag for autoGo */
260 UserSoundOn = MiscHis[55]; /* flag for the sound on/off */
261 CityTax = MiscHis[56];
262 SimSpeed = MiscHis[57];
263 // sim_skips = sim_skip = 0;
264 ChangeCensus();
265 MustUpdateOptions = 1;
266
267 /* yayaya */
268
269 l = *(QUAD *)(MiscHis + 58);
270 HALF_SWAP_LONGS(&l, 1);
271 policePercent = l / 65536.0;
272
273 l = *(QUAD *)(MiscHis + 60);
274 HALF_SWAP_LONGS(&l, 1);
275 firePercent = l / 65536.0;
276
277 l = *(QUAD *)(MiscHis + 62);
278 HALF_SWAP_LONGS(&l, 1);
279 roadPercent = l / 65536.0;
280
281 policePercent = (*(QUAD*)(MiscHis + 58)) / 65536.0; /* and 59 */
282 firePercent = (*(QUAD*)(MiscHis + 60)) / 65536.0; /* and 61 */
283 roadPercent =(*(QUAD*)(MiscHis + 62)) / 65536.0; /* and 63 */
284
285 if (CityTime < 0)
286 CityTime = 0;
287 if ((CityTax > 20) || (CityTax < 0))
288 CityTax = 7;
289 if ((SimSpeed < 0) || (SimSpeed > 3))
290 SimSpeed = 3;
291
292 setSpeed(SimSpeed);
293 setSkips(0);
294
295 InitFundingLevel();
296
297 /* set the scenario id to 0 */
298 InitWillStuff();
299 ScenarioID = 0;
300 InitSimLoad = 1;
301 DoInitialEval = 0;
302 DoSimInit();
303 InvalidateEditors();
304 InvalidateMaps();
305
306 return (1);
307 }
308
309
310 int saveFile(char *filename)
311 {
312 long l;
313 FILE *f;
314
315 #ifdef MSDOS
316 if ((f = fopen(filename, "wb")) == NULL) {
317 #else
318 if ((f = fopen(filename, "w")) == NULL) {
319 #endif
320 /* TODO: report error */
321 return(0);
322 }
323
324 /* total funds is a long..... MiscHis is array of ints */
325 /* total funds is bien put in the 50th & 51th word of MiscHis */
326 /* find the address, cast the ptr to a lontPtr, take contents */
327
328 l = TotalFunds;
329 HALF_SWAP_LONGS(&l, 1);
330 (*(QUAD *)(MiscHis + 50)) = l;
331
332 l = CityTime;
333 HALF_SWAP_LONGS(&l, 1);
334 (*(QUAD *)(MiscHis + 8)) = l;
335
336 MiscHis[52] = autoBulldoze; /* flag for autoBulldoze */
337 MiscHis[53] = autoBudget; /* flag for autoBudget */
338 MiscHis[54] = autoGo; /* flag for autoGo */
339 MiscHis[55] = UserSoundOn; /* flag for the sound on/off */
340 MiscHis[57] = SimSpeed;
341 MiscHis[56] = CityTax; /* post release */
342
343 /* yayaya */
344
345 l = (int)(policePercent * 65536);
346 HALF_SWAP_LONGS(&l, 1);
347 (*(QUAD *)(MiscHis + 58)) = l;
348
349 l = (int)(firePercent * 65536);
350 HALF_SWAP_LONGS(&l, 1);
351 (*(QUAD *)(MiscHis + 60)) = l;
352
353 l = (int)(roadPercent * 65536);
354 HALF_SWAP_LONGS(&l, 1);
355 (*(QUAD *)(MiscHis + 62)) = l;
356
357 if ((_save_short(ResHis, HISTLEN / 2, f) == 0) ||
358 (_save_short(ComHis, HISTLEN / 2, f) == 0) ||
359 (_save_short(IndHis, HISTLEN / 2, f) == 0) ||
360 (_save_short(CrimeHis, HISTLEN / 2, f) == 0) ||
361 (_save_short(PollutionHis, HISTLEN / 2, f) == 0) ||
362 (_save_short(MoneyHis, HISTLEN / 2, f) == 0) ||
363 (_save_short(MiscHis, MISCHISTLEN / 2, f) == 0) ||
364 (_save_short((&Map[0][0]), WORLD_X * WORLD_Y, f) < 0)) {
365
366 /* TODO: report error */
367 fclose(f);
368 return(0);
369 }
370
371 fclose(f);
372 return(1);
373 }
374
375
376 LoadScenario(short s)
377 {
378 char *name, *fname;
379
380 if (CityFileName != NULL) {
381 ckfree(CityFileName);
382 CityFileName = NULL;
383 }
384
385 SetGameLevel(0);
386
387 if ((s < 1) || (s > 8)) s = 1;
388
389 switch (s) {
390 case 1:
391 name = "Dullsville";
392 fname = "snro.111";
393 ScenarioID = 1;
394 CityTime = ((1900 - 1900) * 48) + 2;
395 SetFunds(5000);
396 break;
397 case 2:
398 name = "San Francisco";
399 fname = "snro.222";
400 ScenarioID = 2;
401 CityTime = ((1906 - 1900) * 48) + 2;
402 SetFunds(20000);
403 break;
404 case 3:
405 name = "Hamburg";
406 fname = "snro.333";
407 ScenarioID = 3;
408 CityTime = ((1944 - 1900) * 48) + 2;
409 SetFunds(20000);
410 break;
411 case 4:
412 name = "Bern";
413 fname = "snro.444";
414 ScenarioID = 4;
415 CityTime = ((1965 - 1900) * 48) + 2;
416 SetFunds(20000);
417 break;
418 case 5:
419 name = "Tokyo";
420 fname = "snro.555";
421 ScenarioID = 5;
422 CityTime = ((1957 - 1900) * 48) + 2;
423 SetFunds(20000);
424 break;
425 case 6:
426 name = "Detroit";
427 fname = "snro.666";
428 ScenarioID = 6;
429 CityTime = ((1972 - 1900) * 48) + 2;
430 SetFunds(20000);
431 break;
432 case 7:
433 name = "Boston";
434 fname = "snro.777";
435 ScenarioID = 7;
436 CityTime = ((2010 - 1900) * 48) + 2;
437 SetFunds(20000);
438 break;
439 case 8:
440 name = "Rio de Janeiro";
441 fname = "snro.888";
442 ScenarioID = 8;
443 CityTime = ((2047 - 1900) * 48) + 2;
444 SetFunds(20000);
445 break;
446 }
447
448 setAnyCityName(name);
449 // sim_skips = sim_skip = 0;
450 InvalidateMaps();
451 InvalidateEditors();
452 setSpeed(3);
453 CityTax = 7;
454 gettimeofday(&start_time, NULL);
455
456 _load_file(fname, ResourceDir);
457
458 InitWillStuff();
459 InitFundingLevel();
460 UpdateFunds();
461 InvalidateEditors();
462 InvalidateMaps();
463 InitSimLoad = 1;
464 DoInitialEval = 0;
465 DoSimInit();
466 DidLoadScenario();
467 Kick();
468 }
469
470
471 DidLoadScenario()
472 {
473 Eval("UIDidLoadScenario");
474 }
475
476
477 int LoadCity(char *filename)
478 {
479 char *cp;
480 char msg[256];
481
482 if (loadFile(filename)) {
483 if (CityFileName != NULL)
484 ckfree(CityFileName);
485 CityFileName = (char *)ckalloc(strlen(filename) + 1);
486 strcpy(CityFileName, filename);
487
488 if (cp = (char *)rindex(filename, '.'))
489 *cp = 0;
490 #ifdef MSDOS
491 if (cp = (char *)rindex(filename, '\\'))
492 #else
493 if (cp = (char *)rindex(filename, '/'))
494 #endif
495 cp++;
496 else
497 cp = filename;
498 filename = (char *)ckalloc(strlen(cp) + 1);
499 strcpy(filename, cp);
500 setCityName(filename);
501 gettimeofday(&start_time, NULL);
502
503 InvalidateMaps();
504 InvalidateEditors();
505 DidLoadCity();
506 return (1);
507 } else {
508 sprintf(msg, "Unable to load a city from the file named \"%s\". %s",
509 filename ? filename : "(null)",
510 errno ? strerror(errno) : "");
511 DidntLoadCity(msg);
512 return (0);
513 }
514 }
515
516
517 DidLoadCity()
518 {
519 Eval("UIDidLoadCity");
520 }
521
522
523 DidntLoadCity(char *msg)
524 {
525 char buf[1024];
526 sprintf(buf, "UIDidntLoadCity {%s}", msg);
527 Eval(buf);
528 }
529
530
531 SaveCity()
532 {
533 char msg[256];
534
535 if (CityFileName == NULL) {
536 DoSaveCityAs();
537 } else {
538 if (saveFile(CityFileName))
539 DidSaveCity();
540 else {
541 sprintf(msg, "Unable to save the city to the file named \"%s\". %s",
542 CityFileName ? CityFileName : "(null)",
543 errno ? strerror(errno) : "");
544 DidntSaveCity(msg);
545 }
546 }
547 }
548
549
550 DoSaveCityAs()
551 {
552 Eval("UISaveCityAs");
553 }
554
555
556 DidSaveCity()
557 {
558 Eval("UIDidSaveCity");
559 }
560
561
562 DidntSaveCity(char *msg)
563 {
564 char buf[1024];
565 sprintf(buf, "UIDidntSaveCity {%s}", msg);
566 Eval(buf);
567 }
568
569
570 SaveCityAs(char *filename)
571 {
572 char msg[256];
573 char *cp;
574
575 if (CityFileName != NULL)
576 ckfree(CityFileName);
577 CityFileName = (char *)ckalloc(strlen(filename) + 1);
578 strcpy(CityFileName, filename);
579
580 if (saveFile(CityFileName)) {
581 if (cp = (char *)rindex(filename, '.'))
582 *cp = 0;
583 #ifdef MSDOS
584 if (cp = (char *)rindex(filename, '\\'))
585 #else
586 if (cp = (char *)rindex(filename, '/'))
587 #endif
588 cp++;
589 else
590 cp = filename;
591 filename = (char *)ckalloc(strlen(cp) + 1);
592 strcpy(filename, cp);
593 setCityName(cp);
594 DidSaveCity();
595 } else {
596 sprintf(msg, "Unable to save the city to the file named \"%s\". %s",
597 CityFileName ? CityFileName : "(null)",
598 errno ? strerror(errno) : "");
599 DidntSaveCity(msg);
600 }
601 }
602
603
Impressum, Datenschutz