|
|
1.1 root 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 [email protected].
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:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.