saveload.cpp 22 KB

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