saveload.cpp 21 KB

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