saveload.cpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712
  1. /* $Id$
  2. * MegaZeux
  3. *
  4. * Copyright (C) 1996 Greg Janson
  5. * Copyright (C) 1998 Matthew D. Williams - dbwilli@scsn.net
  6. * Copyright (C) 1999 Charles Goetzman
  7. *
  8. * This program is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU General Public License as
  10. * published by the Free Software Foundation; either version 2 of
  11. * the License, or (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16. * General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, write to the Free Software
  20. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21. */
  22. // Saving/loading worlds- dialogs and functions
  23. // *** READ THIS!!!! ****
  24. /* New magic strings
  25. .MZX files:
  26. MZX - Ver 1.x MegaZeux
  27. MZ2 - Ver 2.x MegaZeux
  28. MZA - Ver 2.51S1 Megazeux
  29. M\002\011 - 2.5.1spider2+, 2.9.x
  30. .SAV files:
  31. MZSV2 - Ver 2.x MegaZeux
  32. MZXSA - Ver 2.51S1 MegaZeux
  33. MZS\002\011 - 2.5.1spider2+, 2.9.x
  34. All others are unchanged.
  35. */
  36. #include "helpsys.h"
  37. #include "sfx.h"
  38. #include "scrdisp.h"
  39. #include "window.h"
  40. #include "meter.h"
  41. #include "error.h"
  42. #include "saveload.h"
  43. #include "window.h"
  44. #include "ezboard.h"
  45. #include "boardmem.h"
  46. #include <stdio.h>
  47. #include "const.h"
  48. #include "data.h"
  49. #include "string.h"
  50. #include "password.h"
  51. #include "egacode.h"
  52. #include "palette.h"
  53. #include "struct.h"
  54. #include "roballoc.h"
  55. #include "ems.h"
  56. #include "counter.h"
  57. #define SAVE_INDIVIDUAL
  58. char sd_types[3]={ DE_INPUT,DE_BUTTON,DE_BUTTON };
  59. char sd_xs[3]={ 5,15,37 };
  60. char sd_ys[3]={ 2,4,4 };
  61. char far *sd_strs[3]={ "Save world as: ","OK","Cancel" };
  62. int sd_p1s[3]={ FILENAME_SIZE-1,0,1 };
  63. int sd_p2s=193;
  64. void far *cf_ptr=(void far *)(curr_file);
  65. dialog s_di={ 10,8,69,14,"Save World",3,sd_types,sd_xs,sd_ys,sd_strs,sd_p1s,
  66. &sd_p2s,&cf_ptr,0 };
  67. static int world_magic(const char magic_string[3]) {
  68. if ( magic_string[0] == 'M' ) {
  69. if ( magic_string[1] == 'Z' ) {
  70. switch (magic_string[2]) {
  71. case 'X':
  72. return 0x0100;
  73. case '2':
  74. return 0x0205;
  75. case 'A':
  76. return 0x0209;
  77. default:
  78. return 0;
  79. }
  80. } else {
  81. if ( ( magic_string[1] > 1 ) && ( magic_string[1] < 10 ) ) { // I hope to God that MZX doesn't last beyond 9.x
  82. return ( (int)magic_string[1] << 8 ) + (int)magic_string[2];
  83. } else {
  84. return 0;
  85. }
  86. }
  87. } else {
  88. return 0;
  89. }
  90. }
  91. static int save_magic(const char magic_string[5]) {
  92. if ( ( magic_string[0] == 'M' ) && ( magic_string[1] == 'Z' ) ) {
  93. switch (magic_string[2]) {
  94. case 'S':
  95. if ( ( magic_string[3] == 'V' ) && ( magic_string[4] == '2' ) ) {
  96. return 0x0205;
  97. } else if ( ( magic_string[3] >= 2 ) && ( magic_string[3] <= 10 ) ) {
  98. return ( (int)magic_string[3] << 8 ) + magic_string[4];
  99. } else {
  100. return 0;
  101. }
  102. case 'X':
  103. if ( ( magic_string[3] == 'S' ) && ( magic_string[4] == 'A' ) ) {
  104. return 0x0209;
  105. } else {
  106. return 0;
  107. }
  108. default:
  109. return 0;
  110. }
  111. } else {
  112. return 0;
  113. }
  114. }
  115. char save_world_dialog(void) {
  116. set_context(76);
  117. char t1=run_dialog(&s_di,current_pg_seg);
  118. pop_context();
  119. return t1;
  120. }
  121. char save_game_dialog(void) {
  122. int t1;
  123. set_context(96);
  124. sd_strs[0]="Save game as: ";
  125. s_di.title="Save Game";
  126. cf_ptr=(void far *)(curr_sav);
  127. t1=run_dialog(&s_di,current_pg_seg);
  128. pop_context();
  129. sd_strs[0]="Save world as: ";
  130. s_di.title="Save World";
  131. cf_ptr=(void far *)(curr_file);
  132. return t1;
  133. }
  134. //Saves the world as an edit file (current board MUST be stored first)
  135. //Set savegame to non-zero for a .SAV file and set faded to faded status
  136. void save_world(char far *file,char savegame,char faded) {
  137. int t1,t2,t3,nmb;//nmb==number of boards
  138. unsigned char xor;
  139. unsigned long temp,temp2,temp3;
  140. char r,g,b;
  141. int meter_target=2,meter_curr=0;//Percent meter-
  142. // 1 for global robot
  143. // 1 per board
  144. // 1 for other info
  145. //Count boards...
  146. nmb=1;
  147. for(t1=0;t1<NUM_BOARDS;t1++)
  148. if(board_where[t1]!=W_NOWHERE) nmb=t1+1;
  149. meter_target+=nmb;
  150. FILE *fp=fopen(file,"wb");
  151. if(fp==NULL) {
  152. error("Error saving world",1,24,current_pg_seg,0x0C01);
  153. return;
  154. }
  155. //Save it...
  156. save_screen(current_pg_seg);
  157. meter("Saving...",current_pg_seg,meter_curr,meter_target);
  158. if (savegame) {
  159. fwrite("MZS\002\011",1,5,fp);
  160. fputc(curr_board,fp);
  161. xor=0;
  162. } else {
  163. //Name of game-
  164. fwrite(board_list,1,BOARD_NAME_SIZE,fp);
  165. //Pw info-
  166. write_password(fp);
  167. //File type id-
  168. fwrite("M\002\011",1,3,fp);
  169. //Get xor code...
  170. xor=get_pw_xor_code();
  171. }
  172. //Rest of file is xor encoded. Write character set...
  173. if(xor) mem_xor((char far *)curr_set,3584,xor);
  174. fwrite(curr_set,1,3584,fp);
  175. if(xor) mem_xor((char far *)curr_set,3584,xor);
  176. //Idchars array...
  177. /*id_chars[323] = bullet_color[0];
  178. id_chars[324] = bullet_color[1];
  179. id_chars[325] = bullet_color[2];*/
  180. if(xor) mem_xor((char far *)id_chars,455,xor);
  181. if(xor) mem_xor((char far *)bullet_color,3,xor);
  182. if(xor) missile_color^=xor;
  183. if(xor) mem_xor((char far *)id_dmg,128,xor);
  184. fwrite(id_chars,1,323,fp);
  185. fwrite(&missile_color,1,1,fp);
  186. fwrite(bullet_color,1,3,fp);
  187. fwrite(id_dmg,1,128,fp);
  188. if(xor) mem_xor((char far *)id_chars,455,xor);
  189. if(xor) mem_xor((char far *)bullet_color,3,xor);
  190. if(xor) missile_color^=xor;
  191. if(xor) mem_xor((char far *)id_dmg,128,xor);
  192. //Status counters...
  193. if(xor) mem_xor(status_shown_counters,NUM_STATUS_CNTRS*COUNTER_NAME_SIZE,
  194. xor);
  195. fwrite(status_shown_counters,COUNTER_NAME_SIZE,NUM_STATUS_CNTRS,fp);
  196. if(xor) mem_xor(status_shown_counters,NUM_STATUS_CNTRS*COUNTER_NAME_SIZE,
  197. xor);
  198. //DATA.ASM info... (define SAVE_INDIVIDUAL to save individually...)
  199. #ifndef SAVE_INDIVIDUAL
  200. if(savegame) {
  201. fwrite(keys,1,54+NUM_KEYS,fp);
  202. fputc(scroll_base_color,fp);
  203. fputc(scroll_corner_color,fp);
  204. fputc(scroll_pointer_color,fp);
  205. fputc(scroll_title_color,fp);
  206. fputc(scroll_arrow_color,fp);
  207. fwrite(real_mod_playing,1,FILENAME_SIZE,fp);
  208. }
  209. if(xor) mem_xor((char far *)&edge_color,24,xor);
  210. fwrite(&edge_color,1,24,fp);
  211. if(xor) mem_xor((char far *)&edge_color,24,xor);
  212. #else
  213. if(savegame) {
  214. fwrite(keys,1,NUM_KEYS,fp);
  215. fwrite(&score,4,1,fp);
  216. fputc(blind_dur,fp);
  217. fputc(firewalker_dur,fp);
  218. fputc(freeze_time_dur,fp);
  219. fputc(slow_time_dur,fp);
  220. fputc(wind_dur,fp);
  221. fwrite(pl_saved_x,2,8,fp);
  222. fwrite(pl_saved_y,2,8,fp);
  223. fwrite(pl_saved_board,1,8,fp);
  224. fputc(saved_pl_color,fp);
  225. fputc(under_player_id,fp);
  226. fputc(under_player_color,fp);
  227. fputc(under_player_param,fp);
  228. fputc(mesg_edges,fp);
  229. fputc(scroll_base_color,fp);
  230. fputc(scroll_corner_color,fp);
  231. fputc(scroll_pointer_color,fp);
  232. fputc(scroll_title_color,fp);
  233. fputc(scroll_arrow_color,fp);
  234. fwrite(real_mod_playing,1,FILENAME_SIZE,fp);
  235. }
  236. fputc(edge_color^xor,fp);
  237. fputc(first_board^xor,fp);
  238. fputc(endgame_board^xor,fp);
  239. fputc(death_board^xor,fp);
  240. fputc((endgame_x&255)^xor,fp);
  241. fputc((endgame_x>>8)^xor,fp);
  242. fputc((endgame_y&255)^xor,fp);
  243. fputc((endgame_y>>8)^xor,fp);
  244. fputc(game_over_sfx^xor,fp);
  245. fputc((death_x&255)^xor,fp);
  246. fputc((death_x>>8)^xor,fp);
  247. fputc((death_y&255)^xor,fp);
  248. fputc((death_y>>8)^xor,fp);
  249. fputc((starting_lives&255)^xor,fp);
  250. fputc((starting_lives>>8)^xor,fp);
  251. fputc((lives_limit&255)^xor,fp);
  252. fputc((lives_limit>>8)^xor,fp);
  253. fputc((starting_health&255)^xor,fp);
  254. fputc((starting_health>>8)^xor,fp);
  255. fputc((health_limit&255)^xor,fp);
  256. fputc((health_limit>>8)^xor,fp);
  257. fputc(enemy_hurt_enemy^xor,fp);
  258. fputc(clear_on_exit^xor,fp);
  259. fputc(only_from_swap^xor,fp);
  260. #endif
  261. //Palette...
  262. for(t1=0;t1<16;t1++) {
  263. get_rgb(t1,r,g,b);
  264. if(xor) {
  265. r^=xor;
  266. g^=xor;
  267. b^=xor;
  268. }
  269. fputc(r,fp);
  270. fputc(g,fp);
  271. fputc(b,fp);
  272. }
  273. if(savegame) {
  274. //Intensity palette
  275. for(t1=0;t1<16;t1++)
  276. fputc(get_color_intensity(t1),fp);
  277. fputc(faded,fp);
  278. fwrite(&player_restart_x,2,1,fp);
  279. fwrite(&player_restart_y,2,1,fp);
  280. fputc(under_player_id,fp);
  281. fputc(under_player_param,fp);
  282. fputc(under_player_color,fp);
  283. //Counters
  284. // Here I took out all the old stuff + just made megazeux save all
  285. // 17k of the 1000 counters, ha ha ha. Spid
  286. // Actually, the above is wrong :), I just fixed it so that the fputc(t2,fp) is now a
  287. // fwrite(), and it will write out the # of counters properly (thanx ment&Kev!) Spid
  288. t2=0;
  289. for(t1=0;t1<NUM_COUNTERS;t1++)
  290. if((counters[t1].counter_value)>0) t2=t1+1;
  291. // fputc(t2,fp);
  292. // fprintf(fp, "%d", t2);
  293. fwrite(&t2, sizeof(int), 1, fp); //THIS is the # of counters, as an int. Spid
  294. for(t1=0;t1<t2;t1++)
  295. fwrite(&counters[t1],1,sizeof(Counter),fp);
  296. // for (t1=0;t1<NUM_COUNTERS;t1++) //Write out every last counter Spid
  297. // fwrite(&counters[t1],1,sizeof(Counter),fp);
  298. }
  299. //Save space for global robot pos.
  300. temp3=ftell(fp);
  301. fputc(0,fp);
  302. fputc(0,fp);
  303. fputc(0,fp);
  304. fputc(0,fp);
  305. //Sfx
  306. if(custom_sfx_on) {
  307. fputc(xor,fp);
  308. temp=ftell(fp);//Save pos to store word
  309. fputc(0,fp);
  310. fputc(0,fp);
  311. //Write ea. sfx
  312. for(t3=t1=0;t1<NUM_SFX;t1++) {
  313. fputc((t2=(str_len(&custom_sfx[t1*69])+1))^xor,fp);
  314. if(xor) mem_xor(&custom_sfx[t1*69],t2,xor);
  315. fwrite(&custom_sfx[t1*69],1,t2,fp);
  316. if(xor) mem_xor(&custom_sfx[t1*69],t2,xor);
  317. t3+=t2+1;
  318. }
  319. //Go back and write word
  320. temp2=ftell(fp);
  321. fseek(fp,temp,SEEK_SET);
  322. fputc((t3&255)^xor,fp);
  323. fputc((t3>>8)^xor,fp);
  324. fseek(fp,temp2,SEEK_SET);
  325. }
  326. //Write number of boards
  327. fputc(nmb^xor,fp);
  328. //Write position of global robot... (right after board position info)
  329. temp=ftell(fp);
  330. temp2=temp+(BOARD_NAME_SIZE+8)*nmb;
  331. if(xor) mem_xor((char far *)&temp2,4,xor);
  332. fseek(fp,temp3,SEEK_SET);
  333. fwrite(&temp2,4,1,fp);
  334. fseek(fp,temp,SEEK_SET);
  335. //Write board list
  336. if(xor) mem_xor(board_list,nmb*BOARD_NAME_SIZE,xor);
  337. fwrite(board_list,BOARD_NAME_SIZE,nmb,fp);
  338. if(xor) mem_xor(board_list,nmb*BOARD_NAME_SIZE,xor);
  339. //Write board offsets/lengths (temp keeps track of where to put info)
  340. //First we need to reserve room for the global robot's struct and program,
  341. //then place them after it...
  342. temp=ftell(fp);
  343. temp+=nmb*8;
  344. temp+=sizeof(Robot)+robots[GLOBAL_ROBOT].program_length;
  345. //Cycle through boards...
  346. for(t1=0;t1<nmb;t1++) {
  347. if(board_where[t1]==W_NOWHERE) {
  348. temp2=0;
  349. if(xor) mem_xor((char far *)&temp2,4,xor);
  350. fwrite(&temp2,4,1,fp);
  351. fwrite(&temp2,4,1,fp);
  352. }
  353. else {
  354. //Write board size...
  355. temp2=board_sizes[t1];
  356. if(xor) mem_xor((char far *)&temp2,4,xor);
  357. fwrite(&temp2,4,1,fp);
  358. //Write current offset...
  359. temp2=temp;
  360. if(xor) mem_xor((char far *)&temp2,4,xor);
  361. fwrite(&temp2,4,1,fp);
  362. //Increase offest.
  363. temp+=board_sizes[t1];
  364. }
  365. }
  366. meter_interior(current_pg_seg,++meter_curr,meter_target);
  367. //Write global robot- struct...
  368. robots[GLOBAL_ROBOT].used=1;
  369. if(xor) mem_xor((char far *)&robots[GLOBAL_ROBOT],sizeof(Robot),xor);
  370. fwrite(&robots[GLOBAL_ROBOT],sizeof(Robot),1,fp);
  371. if(xor) mem_xor((char far *)&robots[GLOBAL_ROBOT],sizeof(Robot),xor);
  372. //...then program.
  373. prepare_robot_mem(1);
  374. if(xor) mem_xor((char far *)&robot_mem[robots[GLOBAL_ROBOT].program_location],
  375. robots[GLOBAL_ROBOT].program_length,xor);
  376. fwrite(&robot_mem[robots[GLOBAL_ROBOT].program_location],1,
  377. robots[GLOBAL_ROBOT].program_length,fp);
  378. if(xor) mem_xor((char far *)&robot_mem[robots[GLOBAL_ROBOT].program_location],
  379. robots[GLOBAL_ROBOT].program_length,xor);
  380. meter_interior(current_pg_seg,++meter_curr,meter_target);
  381. //Now write boards.
  382. for(t1=0;t1<nmb;t1++) {
  383. if(board_where[t1]!=W_NOWHERE)
  384. disk_board(t1,fp,0,xor);
  385. meter_interior(current_pg_seg,++meter_curr,meter_target);
  386. }
  387. //...All done!
  388. fclose(fp);
  389. restore_screen(current_pg_seg);
  390. }
  391. //Loads the world from an edit file (current board should be stored first)
  392. //Clears all prev. board mem and global robot for storing.
  393. //Set edit to 1 to mean this is in the editor (IE stricter pw controls)
  394. //Set edit to 2 or higher to load the file no matter what.
  395. //Returns non-0 if error
  396. //Set savegame to 1 for a .SAV file, then modifys *faded
  397. //set edit to -1 to mean swap world; ie for a game but ignore password if
  398. //it is the same as the current.
  399. char load_world(char far *file,char edit,char savegame,char *faded) {
  400. int version;
  401. int t1,t2,nmb;
  402. unsigned char xor;
  403. unsigned long temp,temp2,gl_rob;
  404. char tempstr[16];
  405. int p_m;
  406. char r,g,b;
  407. int meter_target=2,meter_curr=0;//Percent meter-
  408. // 1 for global robot
  409. // 1 per board
  410. // 1 for other info
  411. FILE *fp=fopen(file,"rb");
  412. if(fp==NULL) {
  413. error("Error loading world",1,24,current_pg_seg,0x0D01);
  414. return 1;
  415. }
  416. //Load it...
  417. save_screen(current_pg_seg);
  418. meter("Loading...",current_pg_seg,meter_curr,meter_target);
  419. if(savegame) {
  420. fread(tempstr,1,5,fp);
  421. version = save_magic(tempstr);
  422. if ( version != 0x0209 ) {
  423. restore_screen(current_pg_seg);
  424. if (!version) {
  425. error(".SAV files from other versions of MZX are not supported",1,24,current_pg_seg,0x2101);
  426. } else {
  427. error("Unrecognized magic: file may not be .SAV file",1,24,current_pg_seg,0x2101);
  428. }
  429. fclose(fp);
  430. return 1;
  431. }
  432. curr_board=fgetc(fp);
  433. xor=0;
  434. refresh_mod_playing = 1;
  435. } else {
  436. //Name of game- skip it.
  437. fseek(fp,BOARD_NAME_SIZE,SEEK_CUR);
  438. //Pw info- Save current...
  439. p_m=protection_method;
  440. str_cpy(tempstr,password);
  441. //...get new...
  442. read_password(fp);
  443. if((edit==-1)&&(!str_cmp(tempstr,password))) goto pw_okay;
  444. //...pw check if needed...
  445. if(edit<2) {
  446. if((protection_method==NO_PLAYING)||((protection_method==NO_EDITING)&&(edit==1))) {
  447. if(check_pw()) {
  448. //Invalid- restore old info...
  449. protection_method=p_m;
  450. str_cpy(password,tempstr);
  451. //...close file...
  452. fclose(fp);
  453. //...and exit.
  454. restore_screen(current_pg_seg);
  455. return 1;
  456. }
  457. //Correct password, continue. Forget about old pw info.
  458. }
  459. }
  460. pw_okay:
  461. {
  462. char magic[3];
  463. char error_string[80];
  464. fread(magic,1,3,fp);
  465. version = world_magic(magic);
  466. if ( version < 0x0205 ) {
  467. sprintf(error_string, "World is from old version (%d.%d); use converter", ( version & 0xff00 ) >> 8, version & 0xff);
  468. version = 0;
  469. } else if ( version > 0x0209 ) {
  470. sprintf(error_string, "World is from more recent version (%d.%d)", ( version & 0xff00 ) >> 8, version & 0xff);
  471. version = 0;
  472. } else if ( version == 0 ) {
  473. sprintf(error_string, "Unrecognized magic; file may not be MZX world");
  474. }
  475. if (!version) {
  476. restore_screen(current_pg_seg);
  477. error(error_string,1,24,current_pg_seg,0x0D02);
  478. protection_method=p_m;
  479. str_cpy(password,tempstr);
  480. fclose(fp);
  481. restore_screen(current_pg_seg);
  482. return 1;
  483. }
  484. }
  485. //Get xor code...
  486. xor=get_pw_xor_code();
  487. }
  488. //Version 2.00
  489. //Clear gl robot...
  490. clear_robot(GLOBAL_ROBOT);
  491. //Clear boards...
  492. for(t1=0;t1<NUM_BOARDS;t1++) {
  493. deallocate_board_space(t1);
  494. board_sizes[t1]=0;
  495. board_list[t1*BOARD_NAME_SIZE]=0;
  496. }
  497. //Rest of file is xor encoded. Read character set...
  498. fread(curr_set,1,3584,fp);
  499. if(xor) mem_xor((char far *)curr_set,3584,xor);
  500. ec_update_set();
  501. //Idchars array...
  502. fread(id_chars,1,323,fp);
  503. fread(&missile_color,1,1,fp);
  504. fread(bullet_color,1,3,fp);
  505. fread(id_dmg,1,128,fp);
  506. if(xor) mem_xor((char far *)id_chars,455,xor);
  507. if(xor) mem_xor((char far *)bullet_color,3,xor);
  508. if(xor) missile_color^=xor;
  509. if(xor) mem_xor((char far *)id_dmg,128,xor);
  510. /*bullet_color[0] = id_chars[323];
  511. bullet_color[1] = id_chars[324];
  512. bullet_color[2] = id_chars[325];*/
  513. //Status counters...
  514. fread(status_shown_counters,COUNTER_NAME_SIZE,NUM_STATUS_CNTRS,fp);
  515. if(xor) mem_xor(status_shown_counters,NUM_STATUS_CNTRS*COUNTER_NAME_SIZE,
  516. xor);
  517. //DATA.ASM info... (define SAVE_INDIVIDUAL to load individually...)
  518. #ifndef SAVE_INDIVIDUAL
  519. if(savegame) {
  520. fread(keys,1,54+NUM_KEYS,fp);
  521. scroll_base_color=fgetc(fp);
  522. scroll_corner_color=fgetc(fp);
  523. scroll_pointer_color=fgetc(fp);
  524. scroll_title_color=fgetc(fp);
  525. scroll_arrow_color=fgetc(fp);
  526. fread(real_mod_playing,1,FILENAME_SIZE,fp);
  527. }
  528. fread(&edge_color,1,24,fp);
  529. if(xor) mem_xor((char far *)&edge_color,24,xor);
  530. #else
  531. if(savegame) {
  532. fread(keys,1,NUM_KEYS,fp);
  533. fread(&score,4,1,fp);
  534. blind_dur=fgetc(fp);
  535. firewalker_dur=fgetc(fp);
  536. freeze_time_dur=fgetc(fp);
  537. slow_time_dur=fgetc(fp);
  538. wind_dur=fgetc(fp);
  539. fread(pl_saved_x,2,8,fp);
  540. fread(pl_saved_y,2,8,fp);
  541. fread(pl_saved_board,1,8,fp);
  542. saved_pl_color=fgetc(fp);
  543. under_player_id=fgetc(fp);
  544. under_player_color=fgetc(fp);
  545. under_player_param=fgetc(fp);
  546. mesg_edges=fgetc(fp);
  547. scroll_base_color=fgetc(fp);
  548. scroll_corner_color=fgetc(fp);
  549. scroll_pointer_color=fgetc(fp);
  550. scroll_title_color=fgetc(fp);
  551. scroll_arrow_color=fgetc(fp);
  552. fread(real_mod_playing,1,FILENAME_SIZE,fp);
  553. }
  554. edge_color=fgetc(fp)^xor;
  555. first_board=fgetc(fp)^xor;
  556. endgame_board=fgetc(fp)^xor;
  557. death_board=fgetc(fp)^xor;
  558. endgame_x=fgetc(fp)^xor;
  559. endgame_x+=(fgetc(fp)^xor)<<8;
  560. endgame_y=fgetc(fp)^xor;
  561. endgame_y+=(fgetc(fp)^xor)<<8;
  562. game_over_sfx=fgetc(fp)^xor;
  563. death_x=fgetc(fp)^xor;
  564. death_x+=(fgetc(fp)^xor)<<8;
  565. death_y=fgetc(fp)^xor;
  566. death_y+=(fgetc(fp)^xor)<<8;
  567. starting_lives=fgetc(fp)^xor;
  568. starting_lives+=(fgetc(fp)^xor)<<8;
  569. lives_limit=fgetc(fp)^xor;
  570. lives_limit+=(fgetc(fp)^xor)<<8;
  571. starting_health=fgetc(fp)^xor;
  572. starting_health+=(fgetc(fp)^xor)<<8;
  573. health_limit=fgetc(fp)^xor;
  574. health_limit+=(fgetc(fp)^xor)<<8;
  575. enemy_hurt_enemy=fgetc(fp)^xor;
  576. clear_on_exit=fgetc(fp)^xor;
  577. only_from_swap=fgetc(fp)^xor;
  578. #endif
  579. //Palette...
  580. for(t1=0;t1<16;t1++) {
  581. r=fgetc(fp)^xor;
  582. g=fgetc(fp)^xor;
  583. b=fgetc(fp)^xor;
  584. set_rgb(t1,r,g,b);
  585. }
  586. if(savegame) {
  587. for(t1=0;t1<16;t1++)
  588. set_color_intensity(t1,fgetc(fp));
  589. *faded=fgetc(fp);
  590. fread(&player_restart_x,2,1,fp);
  591. fread(&player_restart_y,2,1,fp);
  592. under_player_id=fgetc(fp);
  593. under_player_color=fgetc(fp);
  594. under_player_param=fgetc(fp);
  595. //Again, it's fixed so that it will read the whole integer
  596. // t2=fgetc(fp);
  597. fread(&t2, sizeof(int), 1, fp);
  598. for(t1=0;t1<t2;t1++)
  599. fread(&counters[t1],1,sizeof(Counter),fp);
  600. if(t1<NUM_COUNTERS)
  601. for(;t1<NUM_COUNTERS;t1++)
  602. counters[t1].counter_value=0;
  603. }
  604. update_palette();
  605. //Get position of global robot...
  606. fread(&gl_rob,4,1,fp);
  607. if(xor) mem_xor((char far *)&gl_rob,4,xor);
  608. //Get number of boards
  609. nmb=fgetc(fp)^xor;
  610. if(nmb==0) {
  611. //Sfx
  612. custom_sfx_on=1;
  613. fgetc(fp);//Skip size word
  614. fgetc(fp);
  615. //Read sfx
  616. for(t1=0;t1<NUM_SFX;t1++) {
  617. t2=fgetc(fp)^xor;
  618. fread(&custom_sfx[t1*69],1,t2,fp);
  619. }
  620. if(xor) mem_xor(custom_sfx,NUM_SFX*69,xor);
  621. nmb=fgetc(fp)^xor;
  622. }
  623. else custom_sfx_on=0;
  624. meter_target+=nmb;
  625. meter_interior(current_pg_seg,++meter_curr,meter_target);
  626. //Read board list
  627. fread(board_list,BOARD_NAME_SIZE,nmb,fp);
  628. if(xor) mem_xor(board_list,nmb*BOARD_NAME_SIZE,xor);
  629. //Per board- Read size. Read offset, jump there, read board.
  630. // Jump back, next board. temp remembers place within board
  631. // size/loc list.
  632. //Cycle through boards...
  633. for(t1=0;t1<nmb;t1++) {
  634. //Read board size...
  635. fread(&temp2,4,1,fp);
  636. if(xor) mem_xor((char far *)&temp2,4,xor);
  637. board_sizes[t1]=temp2;
  638. //Read offset
  639. fread(&temp2,4,1,fp);
  640. if(xor) mem_xor((char far *)&temp2,4,xor);
  641. //Is there a board?
  642. if(board_sizes[t1]) {
  643. //First try to allocate room
  644. if(allocate_board_space(board_sizes[t1],t1))
  645. error("Out of memory and/or disk space",2,4,current_pg_seg,0x0204);
  646. //Remember current place
  647. temp=ftell(fp);
  648. //Jump to the board
  649. fseek(fp,temp2,SEEK_SET);
  650. //and undisk it
  651. disk_board(t1,fp,1,xor);
  652. //Now return to within list
  653. fseek(fp,temp,SEEK_SET);
  654. }
  655. //Nope. Do nothing (no board, already clear)
  656. //Loop for next board
  657. meter_interior(current_pg_seg,++meter_curr,meter_target);
  658. }
  659. //Read global robot
  660. fseek(fp,gl_rob,SEEK_SET);
  661. //Struct... (save mem offset/size)
  662. t1=robots[GLOBAL_ROBOT].program_location;
  663. t2=robots[GLOBAL_ROBOT].program_length;
  664. fread(&robots[GLOBAL_ROBOT],sizeof(Robot),1,fp);
  665. if(xor) mem_xor((char far *)&robots[GLOBAL_ROBOT],sizeof(Robot),xor);
  666. robots[GLOBAL_ROBOT].program_location=t1;
  667. t1=robots[GLOBAL_ROBOT].program_length;
  668. robots[GLOBAL_ROBOT].program_length=t2;
  669. robots[GLOBAL_ROBOT].used=1;
  670. //Reallocate to t2 long
  671. if(reallocate_robot_mem(T_ROBOT,GLOBAL_ROBOT,t1)) {
  672. error("Out of robot memory",1,21,current_pg_seg,0x0504);
  673. //They chose fail... no loady loady... :)
  674. }
  675. else {
  676. //...then program.
  677. prepare_robot_mem(1);
  678. fread(&robot_mem[robots[GLOBAL_ROBOT].program_location],1,
  679. robots[GLOBAL_ROBOT].program_length,fp);
  680. if(xor) mem_xor((char far *)&robot_mem[robots[GLOBAL_ROBOT].program_location],
  681. robots[GLOBAL_ROBOT].program_length,xor);
  682. meter_interior(current_pg_seg,++meter_curr,meter_target);
  683. }
  684. //...All done!
  685. fclose(fp);
  686. restore_screen(current_pg_seg);
  687. return 0;
  688. }