saveload.cpp 24 KB

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