saveload.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696
  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. fwrite(id_chars,1,455,fp);
  182. if(xor) mem_xor((char far *)id_chars,455,xor);
  183. //Status counters...
  184. if(xor) mem_xor(status_shown_counters,NUM_STATUS_CNTRS*COUNTER_NAME_SIZE,
  185. xor);
  186. fwrite(status_shown_counters,COUNTER_NAME_SIZE,NUM_STATUS_CNTRS,fp);
  187. if(xor) mem_xor(status_shown_counters,NUM_STATUS_CNTRS*COUNTER_NAME_SIZE,
  188. xor);
  189. //DATA.ASM info... (define SAVE_INDIVIDUAL to save individually...)
  190. #ifndef SAVE_INDIVIDUAL
  191. if(savegame) {
  192. fwrite(keys,1,54+NUM_KEYS,fp);
  193. fputc(scroll_base_color,fp);
  194. fputc(scroll_corner_color,fp);
  195. fputc(scroll_pointer_color,fp);
  196. fputc(scroll_title_color,fp);
  197. fputc(scroll_arrow_color,fp);
  198. fwrite(real_mod_playing,1,FILENAME_SIZE,fp);
  199. }
  200. if(xor) mem_xor((char far *)&edge_color,24,xor);
  201. fwrite(&edge_color,1,24,fp);
  202. if(xor) mem_xor((char far *)&edge_color,24,xor);
  203. #else
  204. if(savegame) {
  205. fwrite(keys,1,NUM_KEYS,fp);
  206. fwrite(&score,4,1,fp);
  207. fputc(blind_dur,fp);
  208. fputc(firewalker_dur,fp);
  209. fputc(freeze_time_dur,fp);
  210. fputc(slow_time_dur,fp);
  211. fputc(wind_dur,fp);
  212. fwrite(pl_saved_x,2,8,fp);
  213. fwrite(pl_saved_y,2,8,fp);
  214. fwrite(pl_saved_board,1,8,fp);
  215. fputc(saved_pl_color,fp);
  216. fputc(under_player_id,fp);
  217. fputc(under_player_color,fp);
  218. fputc(under_player_param,fp);
  219. fputc(mesg_edges,fp);
  220. fputc(scroll_base_color,fp);
  221. fputc(scroll_corner_color,fp);
  222. fputc(scroll_pointer_color,fp);
  223. fputc(scroll_title_color,fp);
  224. fputc(scroll_arrow_color,fp);
  225. fwrite(real_mod_playing,1,FILENAME_SIZE,fp);
  226. }
  227. fputc(edge_color^xor,fp);
  228. fputc(first_board^xor,fp);
  229. fputc(endgame_board^xor,fp);
  230. fputc(death_board^xor,fp);
  231. fputc((endgame_x&255)^xor,fp);
  232. fputc((endgame_x>>8)^xor,fp);
  233. fputc((endgame_y&255)^xor,fp);
  234. fputc((endgame_y>>8)^xor,fp);
  235. fputc(game_over_sfx^xor,fp);
  236. fputc((death_x&255)^xor,fp);
  237. fputc((death_x>>8)^xor,fp);
  238. fputc((death_y&255)^xor,fp);
  239. fputc((death_y>>8)^xor,fp);
  240. fputc((starting_lives&255)^xor,fp);
  241. fputc((starting_lives>>8)^xor,fp);
  242. fputc((lives_limit&255)^xor,fp);
  243. fputc((lives_limit>>8)^xor,fp);
  244. fputc((starting_health&255)^xor,fp);
  245. fputc((starting_health>>8)^xor,fp);
  246. fputc((health_limit&255)^xor,fp);
  247. fputc((health_limit>>8)^xor,fp);
  248. fputc(enemy_hurt_enemy^xor,fp);
  249. fputc(clear_on_exit^xor,fp);
  250. fputc(only_from_swap^xor,fp);
  251. #endif
  252. //Palette...
  253. for(t1=0;t1<16;t1++) {
  254. get_rgb(t1,r,g,b);
  255. if(xor) {
  256. r^=xor;
  257. g^=xor;
  258. b^=xor;
  259. }
  260. fputc(r,fp);
  261. fputc(g,fp);
  262. fputc(b,fp);
  263. }
  264. if(savegame) {
  265. //Intensity palette
  266. for(t1=0;t1<16;t1++)
  267. fputc(get_color_intensity(t1),fp);
  268. fputc(faded,fp);
  269. fwrite(&player_restart_x,2,1,fp);
  270. fwrite(&player_restart_y,2,1,fp);
  271. fputc(under_player_id,fp);
  272. fputc(under_player_param,fp);
  273. fputc(under_player_color,fp);
  274. //Counters
  275. // Here I took out all the old stuff + just made megazeux save all
  276. // 17k of the 1000 counters, ha ha ha. Spid
  277. // Actually, the above is wrong :), I just fixed it so that the fputc(t2,fp) is now a
  278. // fwrite(), and it will write out the # of counters properly (thanx ment&Kev!) Spid
  279. t2=0;
  280. for(t1=0;t1<NUM_COUNTERS;t1++)
  281. if((counters[t1].counter_value)>0) t2=t1+1;
  282. // fputc(t2,fp);
  283. // fprintf(fp, "%d", t2);
  284. fwrite(&t2, sizeof(int), 1, fp); //THIS is the # of counters, as an int. Spid
  285. for(t1=0;t1<t2;t1++)
  286. fwrite(&counters[t1],1,sizeof(Counter),fp);
  287. // for (t1=0;t1<NUM_COUNTERS;t1++) //Write out every last counter Spid
  288. // fwrite(&counters[t1],1,sizeof(Counter),fp);
  289. }
  290. //Save space for global robot pos.
  291. temp3=ftell(fp);
  292. fputc(0,fp);
  293. fputc(0,fp);
  294. fputc(0,fp);
  295. fputc(0,fp);
  296. //Sfx
  297. if(custom_sfx_on) {
  298. fputc(xor,fp);
  299. temp=ftell(fp);//Save pos to store word
  300. fputc(0,fp);
  301. fputc(0,fp);
  302. //Write ea. sfx
  303. for(t3=t1=0;t1<NUM_SFX;t1++) {
  304. fputc((t2=(str_len(&custom_sfx[t1*69])+1))^xor,fp);
  305. if(xor) mem_xor(&custom_sfx[t1*69],t2,xor);
  306. fwrite(&custom_sfx[t1*69],1,t2,fp);
  307. if(xor) mem_xor(&custom_sfx[t1*69],t2,xor);
  308. t3+=t2+1;
  309. }
  310. //Go back and write word
  311. temp2=ftell(fp);
  312. fseek(fp,temp,SEEK_SET);
  313. fputc((t3&255)^xor,fp);
  314. fputc((t3>>8)^xor,fp);
  315. fseek(fp,temp2,SEEK_SET);
  316. }
  317. //Write number of boards
  318. fputc(nmb^xor,fp);
  319. //Write position of global robot... (right after board position info)
  320. temp=ftell(fp);
  321. temp2=temp+(BOARD_NAME_SIZE+8)*nmb;
  322. if(xor) mem_xor((char far *)&temp2,4,xor);
  323. fseek(fp,temp3,SEEK_SET);
  324. fwrite(&temp2,4,1,fp);
  325. fseek(fp,temp,SEEK_SET);
  326. //Write board list
  327. if(xor) mem_xor(board_list,nmb*BOARD_NAME_SIZE,xor);
  328. fwrite(board_list,BOARD_NAME_SIZE,nmb,fp);
  329. if(xor) mem_xor(board_list,nmb*BOARD_NAME_SIZE,xor);
  330. //Write board offsets/lengths (temp keeps track of where to put info)
  331. //First we need to reserve room for the global robot's struct and program,
  332. //then place them after it...
  333. temp=ftell(fp);
  334. temp+=nmb*8;
  335. temp+=sizeof(Robot)+robots[GLOBAL_ROBOT].program_length;
  336. //Cycle through boards...
  337. for(t1=0;t1<nmb;t1++) {
  338. if(board_where[t1]==W_NOWHERE) {
  339. temp2=0;
  340. if(xor) mem_xor((char far *)&temp2,4,xor);
  341. fwrite(&temp2,4,1,fp);
  342. fwrite(&temp2,4,1,fp);
  343. }
  344. else {
  345. //Write board size...
  346. temp2=board_sizes[t1];
  347. if(xor) mem_xor((char far *)&temp2,4,xor);
  348. fwrite(&temp2,4,1,fp);
  349. //Write current offset...
  350. temp2=temp;
  351. if(xor) mem_xor((char far *)&temp2,4,xor);
  352. fwrite(&temp2,4,1,fp);
  353. //Increase offest.
  354. temp+=board_sizes[t1];
  355. }
  356. }
  357. meter_interior(current_pg_seg,++meter_curr,meter_target);
  358. //Write global robot- struct...
  359. robots[GLOBAL_ROBOT].used=1;
  360. if(xor) mem_xor((char far *)&robots[GLOBAL_ROBOT],sizeof(Robot),xor);
  361. fwrite(&robots[GLOBAL_ROBOT],sizeof(Robot),1,fp);
  362. if(xor) mem_xor((char far *)&robots[GLOBAL_ROBOT],sizeof(Robot),xor);
  363. //...then program.
  364. prepare_robot_mem(1);
  365. if(xor) mem_xor((char far *)&robot_mem[robots[GLOBAL_ROBOT].program_location],
  366. robots[GLOBAL_ROBOT].program_length,xor);
  367. fwrite(&robot_mem[robots[GLOBAL_ROBOT].program_location],1,
  368. robots[GLOBAL_ROBOT].program_length,fp);
  369. if(xor) mem_xor((char far *)&robot_mem[robots[GLOBAL_ROBOT].program_location],
  370. robots[GLOBAL_ROBOT].program_length,xor);
  371. meter_interior(current_pg_seg,++meter_curr,meter_target);
  372. //Now write boards.
  373. for(t1=0;t1<nmb;t1++) {
  374. if(board_where[t1]!=W_NOWHERE)
  375. disk_board(t1,fp,0,xor);
  376. meter_interior(current_pg_seg,++meter_curr,meter_target);
  377. }
  378. //...All done!
  379. fclose(fp);
  380. restore_screen(current_pg_seg);
  381. }
  382. //Loads the world from an edit file (current board should be stored first)
  383. //Clears all prev. board mem and global robot for storing.
  384. //Set edit to 1 to mean this is in the editor (IE stricter pw controls)
  385. //Set edit to 2 or higher to load the file no matter what.
  386. //Returns non-0 if error
  387. //Set savegame to 1 for a .SAV file, then modifys *faded
  388. //set edit to -1 to mean swap world; ie for a game but ignore password if
  389. //it is the same as the current.
  390. char load_world(char far *file,char edit,char savegame,char *faded) {
  391. int version;
  392. int t1,t2,nmb;
  393. unsigned char xor;
  394. unsigned long temp,temp2,gl_rob;
  395. char tempstr[16];
  396. int p_m;
  397. char r,g,b;
  398. int meter_target=2,meter_curr=0;//Percent meter-
  399. // 1 for global robot
  400. // 1 per board
  401. // 1 for other info
  402. FILE *fp=fopen(file,"rb");
  403. if(fp==NULL) {
  404. error("Error loading world",1,24,current_pg_seg,0x0D01);
  405. return 1;
  406. }
  407. //Load it...
  408. save_screen(current_pg_seg);
  409. meter("Loading...",current_pg_seg,meter_curr,meter_target);
  410. if(savegame) {
  411. fread(tempstr,1,5,fp);
  412. version = save_magic(tempstr);
  413. if ( version != 0x0209 ) {
  414. restore_screen(current_pg_seg);
  415. if (!version) {
  416. error(".SAV files from other versions of MZX are not supported",1,24,current_pg_seg,0x2101);
  417. } else {
  418. error("Unrecognized magic: file may not be .SAV file",1,24,current_pg_seg,0x2101);
  419. }
  420. fclose(fp);
  421. return 1;
  422. }
  423. curr_board=fgetc(fp);
  424. xor=0;
  425. refresh_mod_playing = 1;
  426. } else {
  427. //Name of game- skip it.
  428. fseek(fp,BOARD_NAME_SIZE,SEEK_CUR);
  429. //Pw info- Save current...
  430. p_m=protection_method;
  431. str_cpy(tempstr,password);
  432. //...get new...
  433. read_password(fp);
  434. if((edit==-1)&&(!str_cmp(tempstr,password))) goto pw_okay;
  435. //...pw check if needed...
  436. if(edit<2) {
  437. if((protection_method==NO_PLAYING)||((protection_method==NO_EDITING)&&(edit==1))) {
  438. if(check_pw()) {
  439. //Invalid- restore old info...
  440. protection_method=p_m;
  441. str_cpy(password,tempstr);
  442. //...close file...
  443. fclose(fp);
  444. //...and exit.
  445. restore_screen(current_pg_seg);
  446. return 1;
  447. }
  448. //Correct password, continue. Forget about old pw info.
  449. }
  450. }
  451. pw_okay:
  452. {
  453. char magic[3];
  454. char error_string[80];
  455. fread(magic,1,3,fp);
  456. version = world_magic(magic);
  457. if ( version < 0x0205 ) {
  458. sprintf(error_string, "World is from old version (%d.%d); use converter", ( version & 0xff00 ) >> 8, version & 0xff);
  459. version = 0;
  460. } else if ( version > 0x0209 ) {
  461. sprintf(error_string, "World is from more recent version (%d.%d)", ( version & 0xff00 ) >> 8, version & 0xff);
  462. version = 0;
  463. } else if ( version == 0 ) {
  464. sprintf(error_string, "Unrecognized magic; file may not be MZX world");
  465. }
  466. if (!version) {
  467. restore_screen(current_pg_seg);
  468. error(error_string,1,24,current_pg_seg,0x0D02);
  469. protection_method=p_m;
  470. str_cpy(password,tempstr);
  471. fclose(fp);
  472. restore_screen(current_pg_seg);
  473. return 1;
  474. }
  475. }
  476. //Get xor code...
  477. xor=get_pw_xor_code();
  478. }
  479. //Version 2.00
  480. //Clear gl robot...
  481. clear_robot(GLOBAL_ROBOT);
  482. //Clear boards...
  483. for(t1=0;t1<NUM_BOARDS;t1++) {
  484. deallocate_board_space(t1);
  485. board_sizes[t1]=0;
  486. board_list[t1*BOARD_NAME_SIZE]=0;
  487. }
  488. //Rest of file is xor encoded. Read character set...
  489. fread(curr_set,1,3584,fp);
  490. if(xor) mem_xor((char far *)curr_set,3584,xor);
  491. ec_update_set();
  492. //Idchars array...
  493. fread(id_chars,1,455,fp);
  494. if(xor) mem_xor((char far *)id_chars,455,xor);
  495. bullet_color[0] = id_chars[323];
  496. bullet_color[1] = id_chars[324];
  497. bullet_color[2] = id_chars[325];
  498. //Status counters...
  499. fread(status_shown_counters,COUNTER_NAME_SIZE,NUM_STATUS_CNTRS,fp);
  500. if(xor) mem_xor(status_shown_counters,NUM_STATUS_CNTRS*COUNTER_NAME_SIZE,
  501. xor);
  502. //DATA.ASM info... (define SAVE_INDIVIDUAL to load individually...)
  503. #ifndef SAVE_INDIVIDUAL
  504. if(savegame) {
  505. fread(keys,1,54+NUM_KEYS,fp);
  506. scroll_base_color=fgetc(fp);
  507. scroll_corner_color=fgetc(fp);
  508. scroll_pointer_color=fgetc(fp);
  509. scroll_title_color=fgetc(fp);
  510. scroll_arrow_color=fgetc(fp);
  511. fread(real_mod_playing,1,FILENAME_SIZE,fp);
  512. }
  513. fread(&edge_color,1,24,fp);
  514. if(xor) mem_xor((char far *)&edge_color,24,xor);
  515. #else
  516. if(savegame) {
  517. fread(keys,1,NUM_KEYS,fp);
  518. fread(&score,4,1,fp);
  519. blind_dur=fgetc(fp);
  520. firewalker_dur=fgetc(fp);
  521. freeze_time_dur=fgetc(fp);
  522. slow_time_dur=fgetc(fp);
  523. wind_dur=fgetc(fp);
  524. fread(pl_saved_x,2,8,fp);
  525. fread(pl_saved_y,2,8,fp);
  526. fread(pl_saved_board,1,8,fp);
  527. saved_pl_color=fgetc(fp);
  528. under_player_id=fgetc(fp);
  529. under_player_color=fgetc(fp);
  530. under_player_param=fgetc(fp);
  531. mesg_edges=fgetc(fp);
  532. scroll_base_color=fgetc(fp);
  533. scroll_corner_color=fgetc(fp);
  534. scroll_pointer_color=fgetc(fp);
  535. scroll_title_color=fgetc(fp);
  536. scroll_arrow_color=fgetc(fp);
  537. fread(real_mod_playing,1,FILENAME_SIZE,fp);
  538. }
  539. edge_color=fgetc(fp)^xor;
  540. first_board=fgetc(fp)^xor;
  541. endgame_board=fgetc(fp)^xor;
  542. death_board=fgetc(fp)^xor;
  543. endgame_x=fgetc(fp)^xor;
  544. endgame_x+=(fgetc(fp)^xor)<<8;
  545. endgame_y=fgetc(fp)^xor;
  546. endgame_y+=(fgetc(fp)^xor)<<8;
  547. game_over_sfx=fgetc(fp)^xor;
  548. death_x=fgetc(fp)^xor;
  549. death_x+=(fgetc(fp)^xor)<<8;
  550. death_y=fgetc(fp)^xor;
  551. death_y+=(fgetc(fp)^xor)<<8;
  552. starting_lives=fgetc(fp)^xor;
  553. starting_lives+=(fgetc(fp)^xor)<<8;
  554. lives_limit=fgetc(fp)^xor;
  555. lives_limit+=(fgetc(fp)^xor)<<8;
  556. starting_health=fgetc(fp)^xor;
  557. starting_health+=(fgetc(fp)^xor)<<8;
  558. health_limit=fgetc(fp)^xor;
  559. health_limit+=(fgetc(fp)^xor)<<8;
  560. enemy_hurt_enemy=fgetc(fp)^xor;
  561. clear_on_exit=fgetc(fp)^xor;
  562. only_from_swap=fgetc(fp)^xor;
  563. #endif
  564. //Palette...
  565. for(t1=0;t1<16;t1++) {
  566. r=fgetc(fp)^xor;
  567. g=fgetc(fp)^xor;
  568. b=fgetc(fp)^xor;
  569. set_rgb(t1,r,g,b);
  570. }
  571. if(savegame) {
  572. for(t1=0;t1<16;t1++)
  573. set_color_intensity(t1,fgetc(fp));
  574. *faded=fgetc(fp);
  575. fread(&player_restart_x,2,1,fp);
  576. fread(&player_restart_y,2,1,fp);
  577. under_player_id=fgetc(fp);
  578. under_player_color=fgetc(fp);
  579. under_player_param=fgetc(fp);
  580. //Again, it's fixed so that it will read the whole integer
  581. // t2=fgetc(fp);
  582. fread(&t2, sizeof(int), 1, fp);
  583. for(t1=0;t1<t2;t1++)
  584. fread(&counters[t1],1,sizeof(Counter),fp);
  585. if(t1<NUM_COUNTERS)
  586. for(;t1<NUM_COUNTERS;t1++)
  587. counters[t1].counter_value=0;
  588. }
  589. update_palette();
  590. //Get position of global robot...
  591. fread(&gl_rob,4,1,fp);
  592. if(xor) mem_xor((char far *)&gl_rob,4,xor);
  593. //Get number of boards
  594. nmb=fgetc(fp)^xor;
  595. if(nmb==0) {
  596. //Sfx
  597. custom_sfx_on=1;
  598. fgetc(fp);//Skip size word
  599. fgetc(fp);
  600. //Read sfx
  601. for(t1=0;t1<NUM_SFX;t1++) {
  602. t2=fgetc(fp)^xor;
  603. fread(&custom_sfx[t1*69],1,t2,fp);
  604. }
  605. if(xor) mem_xor(custom_sfx,NUM_SFX*69,xor);
  606. nmb=fgetc(fp)^xor;
  607. }
  608. else custom_sfx_on=0;
  609. meter_target+=nmb;
  610. meter_interior(current_pg_seg,++meter_curr,meter_target);
  611. //Read board list
  612. fread(board_list,BOARD_NAME_SIZE,nmb,fp);
  613. if(xor) mem_xor(board_list,nmb*BOARD_NAME_SIZE,xor);
  614. //Per board- Read size. Read offset, jump there, read board.
  615. // Jump back, next board. temp remembers place within board
  616. // size/loc list.
  617. //Cycle through boards...
  618. for(t1=0;t1<nmb;t1++) {
  619. //Read board size...
  620. fread(&temp2,4,1,fp);
  621. if(xor) mem_xor((char far *)&temp2,4,xor);
  622. board_sizes[t1]=temp2;
  623. //Read offset
  624. fread(&temp2,4,1,fp);
  625. if(xor) mem_xor((char far *)&temp2,4,xor);
  626. //Is there a board?
  627. if(board_sizes[t1]) {
  628. //First try to allocate room
  629. if(allocate_board_space(board_sizes[t1],t1))
  630. error("Out of memory and/or disk space",2,4,current_pg_seg,0x0204);
  631. //Remember current place
  632. temp=ftell(fp);
  633. //Jump to the board
  634. fseek(fp,temp2,SEEK_SET);
  635. //and undisk it
  636. disk_board(t1,fp,1,xor);
  637. //Now return to within list
  638. fseek(fp,temp,SEEK_SET);
  639. }
  640. //Nope. Do nothing (no board, already clear)
  641. //Loop for next board
  642. meter_interior(current_pg_seg,++meter_curr,meter_target);
  643. }
  644. //Read global robot
  645. fseek(fp,gl_rob,SEEK_SET);
  646. //Struct... (save mem offset/size)
  647. t1=robots[GLOBAL_ROBOT].program_location;
  648. t2=robots[GLOBAL_ROBOT].program_length;
  649. fread(&robots[GLOBAL_ROBOT],sizeof(Robot),1,fp);
  650. if(xor) mem_xor((char far *)&robots[GLOBAL_ROBOT],sizeof(Robot),xor);
  651. robots[GLOBAL_ROBOT].program_location=t1;
  652. t1=robots[GLOBAL_ROBOT].program_length;
  653. robots[GLOBAL_ROBOT].program_length=t2;
  654. robots[GLOBAL_ROBOT].used=1;
  655. //Reallocate to t2 long
  656. if(reallocate_robot_mem(T_ROBOT,GLOBAL_ROBOT,t1)) {
  657. error("Out of robot memory",1,21,current_pg_seg,0x0504);
  658. //They chose fail... no loady loady... :)
  659. }
  660. else {
  661. //...then program.
  662. prepare_robot_mem(1);
  663. fread(&robot_mem[robots[GLOBAL_ROBOT].program_location],1,
  664. robots[GLOBAL_ROBOT].program_length,fp);
  665. if(xor) mem_xor((char far *)&robot_mem[robots[GLOBAL_ROBOT].program_location],
  666. robots[GLOBAL_ROBOT].program_length,xor);
  667. meter_interior(current_pg_seg,++meter_curr,meter_target);
  668. }
  669. //...All done!
  670. fclose(fp);
  671. restore_screen(current_pg_seg);
  672. return 0;
  673. }