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