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