ver1to2.cpp 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110
  1. /* $Id$
  2. * MegaZeux
  3. *
  4. * Copyright (C) 1996 Greg Janson
  5. * Copyright (C) 1998 Matthew D. Williams - dbwilli@scsn.net
  6. *
  7. * This program is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU General Public License as
  9. * published by the Free Software Foundation; either version 2 of
  10. * the License, or (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, write to the Free Software
  19. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20. */
  21. /* Converts a version 1.0? .MZX or .MZB file to a version 2.00 file. */
  22. #include <stdio.h>
  23. #include <dir.h>
  24. #include <string.h>
  25. #include <alloc.h>
  26. void convert(char far *fn);
  27. void rle_to_rle2(unsigned char huge *&source,unsigned char huge *&dest);
  28. long convert_board(unsigned char huge *loc);//Returns size
  29. void convert_robot_line(unsigned char far *source,unsigned char far *dest);
  30. extern char far *cmd_formats[256];
  31. //Destination for board conversion
  32. unsigned char huge *newboard;//Must allocate 210000 bytes
  33. void main(int argc,char *argv[]) {
  34. int t1;
  35. printf("\n\n");
  36. newboard=(unsigned char huge *)farmalloc(210000L);
  37. if(newboard==NULL) {
  38. printf("ERROR: Out of memory\n\n\a");
  39. return;
  40. }
  41. if(argc<2) {
  42. printf("VER1TO2.EXE converts MegaZeux worlds (.MZX) and boards (.MZB) from version\n");
  43. printf("1.00g, 1.01, 1.02, or 1.03 of MegaZeux to version 2.00 of MegaZeux. It is\n");
  44. printf("run from the command line as follows:\n\n");
  45. printf("VER1TO2 file.ext [file.ext ...]\n\n");
  46. printf("VER1TO2 can accept multiple files and they may include wildcards. The files\n");
  47. printf("do not all have to be the same type. Corrupted files, non-board/non-world\n");
  48. printf("files, and version 2.00 files will all be skipped over with an error. Note\n");
  49. printf("that VER1TO2 verifies the extension of the file, so the file must have the\n");
  50. printf("proper extension of .MZX or .MZB.\n\n\a");
  51. return;
  52. }
  53. //Do files
  54. for(t1=1;t1<argc;t1++)
  55. convert(argv[t1]);
  56. //Done
  57. printf("\nAll files converted!\n\n");
  58. farfree(newboard);
  59. }
  60. unsigned char far magic_code[16]="æRëòmMJ·‡²’ˆÞ‘$";
  61. unsigned char far id_dmg[128]={
  62. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  63. 0,0,0,0,0,0,0,0,0,0,100,0,0,0,0,0,
  64. 0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,
  65. 0,0,0,0,0,0,0,0,0,0,0,10,0,10,5,5,
  66. 0,0,0,0,0,0,0,0,0,0,0,10,10,0,10,10,
  67. 10,0,0,10,10,10,10,10,10,10,10,10,0,0,10,10,
  68. 0,0,
  69. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  70. 0,0,0,0,0,0 };
  71. unsigned char far palette[48]={
  72. 0,0,0,0,0,42,0,42,0,0,42,42,
  73. 42,0,0,42,0,42,42,21,0,42,42,42,
  74. 21,21,21,21,21,63,21,63,21,21,63,63,
  75. 63,21,21,63,21,63,63,63,21,63,63,63 };
  76. unsigned char far global_robot[43]={
  77. 2,0,0,0,0,0,0,0,0,0,0,0,0,
  78. 0,0,0,0,0,0,0,1,0,0,1,
  79. 0,0,0,1,0,0,0,0,0,0,0,0,
  80. 0,0,1,0,0,255,0 };
  81. long orig_board_size[150];
  82. long orig_board_location[150];
  83. long new_board_stat_ptr[150];
  84. void convert(char far *fn) {
  85. int t1,t2;
  86. char type=1;//1=board, 0=world
  87. char temp_name[13];
  88. FILE *source;
  89. FILE *dest;
  90. unsigned char huge *cboard=NULL;
  91. //Verify extension
  92. t2=1;//Problem
  93. for(t1=0;t1<strlen(fn);t1++)
  94. if(fn[t1]=='.') break;
  95. if(t1<strlen(fn)) {
  96. if(!stricmp(&fn[++t1],"MZX")) type=t2=0;
  97. else if(!stricmp(&fn[t1],"MZB")) {
  98. type=1;
  99. t2=0;
  100. }
  101. }
  102. if(t2) {
  103. printf("ERROR: File is not a .MZB file or a .MZX file (%s)\n",fn);
  104. return;
  105. }
  106. //Make sure it exists
  107. source=fopen(fn,"rb+");
  108. if(source==NULL) {
  109. printf("ERROR: Non-existant file- %s\n",fn);
  110. return;
  111. }
  112. //Verify file type
  113. if(type) {
  114. //Verify board file
  115. fseek(source,0,SEEK_SET);
  116. t1=fgetc(source);
  117. if(t1==255) {
  118. fclose(source);
  119. printf("ERROR: File is already a version 2.00 or greater .MZB file (%s)\n",fn);
  120. return;
  121. }
  122. //Our only way of file type verification for older .MZB files-
  123. // Make sure x/y sizes are 1-100
  124. // Make sure next byte is NOT a 0
  125. if((t1>100)||(t1==0)) {
  126. fclose(source);
  127. printf("ERROR: File is not a .MZB file or a .MZX file (%s)\n",fn);
  128. return;
  129. }
  130. t1=fgetc(source);
  131. if((t1>100)||(t1==0)) {
  132. fclose(source);
  133. printf("ERROR: File is not a .MZB file or a .MZX file (%s)\n",fn);
  134. return;
  135. }
  136. if(fgetc(source)==0) {
  137. fclose(source);
  138. printf("ERROR: File is not a .MZB file or a .MZX file (%s)\n",fn);
  139. return;
  140. }
  141. }
  142. else {
  143. fseek(source,25,SEEK_SET);
  144. t1=fgetc(source);
  145. if(t1) fseek(source,16,SEEK_CUR);//Skip over pw
  146. if(fgetc(source)!='M') type=1;
  147. if(fgetc(source)!='Z') type=1;
  148. t1=fgetc(source);
  149. if(((t1>='2')&&(t1<='9'))) {
  150. printf("ERROR: File is already a version 2.00 or greater .MZX file (%s)\n",fn);
  151. fclose(source);
  152. return;
  153. }
  154. if(t1!='X') type=1;
  155. if(type) {
  156. fclose(source);
  157. printf("ERROR: File is not a .MZB file or a .MZX file (%s)\n",fn);
  158. return;
  159. }
  160. }
  161. //We now know whether it is a .MZB or .MZX file, and that it is the
  162. //right version.
  163. fclose(source);
  164. //Rename to a temp file
  165. strcpy(temp_name,"~V1TO2XXXXXX");
  166. mktemp(temp_name);
  167. rename(fn,temp_name);
  168. //Open both files
  169. dest=fopen(fn,"wb+");
  170. if(dest==NULL) {
  171. printf("ERROR: Error opening file for output (%s)\n",fn);
  172. rename(temp_name,fn);
  173. return;
  174. }
  175. source=fopen(temp_name,"rb");
  176. if(source==NULL) {
  177. fclose(dest);
  178. printf("ERROR: Error opening file for input (%s, originally %s)\n",
  179. temp_name,fn);
  180. rename(temp_name,fn);
  181. return;
  182. }
  183. //Everything is ready!
  184. printf("Converting %s file %s... ",type?"board":"world",fn);
  185. switch(type) {
  186. case 0:
  187. //World file conversion
  188. int _cpt;
  189. #define copy_bytes(num) { for(_cpt=0;_cpt<num;_cpt++) fputc(fgetc(source),dest); }
  190. int pro_method,pw_size;
  191. unsigned char password[16];
  192. copy_bytes(25);//Title
  193. fputc(pro_method=fgetc(source),dest);//Protection method
  194. if(pro_method) {//Password
  195. pw_size=fgetc(source);
  196. fread(password,1,15,source);
  197. //First, normalize password...
  198. for(t1=0;t1<15;t1++) {
  199. password[t1]^=magic_code[t1];
  200. password[t1]-=0x12+pro_method;
  201. password[t1]^=0x8D;
  202. }
  203. password[pw_size]=0;
  204. for(t1=strlen(password);t1<16;t1++)
  205. password[t1]=0;
  206. //Write the new password
  207. for(t1=0;t1<15;t1++) {
  208. t2=password[t1]^0x8D;
  209. t2+=pro_method+0x12;
  210. t2^=magic_code[t1];
  211. fputc(t2,dest);
  212. }
  213. }
  214. fseek(source,3,SEEK_CUR);
  215. fwrite("MZ2",1,3,dest);//Code
  216. copy_bytes(3584);//Character set
  217. copy_bytes(34);//Idchars, before goop
  218. fputc(176,dest);
  219. fgetc(source);//Idchars, goop
  220. copy_bytes(271);//Idchars, after goop
  221. //We WILL be writing the rest of the Idchars.
  222. //First, we need to read the entire remainder into variables.
  223. unsigned char status_counters[60];
  224. unsigned char bullet_chars[4];
  225. unsigned char player_char;
  226. unsigned char edge_color,player_color,bullet_color,missile_color;
  227. unsigned char first_board,eg_board,die_board;
  228. int eg_x,eg_y,die_x,die_y;
  229. int lives,lives_limit,health,health_limit;
  230. int nme_hurt_nme,gosfx;
  231. fread(status_counters,1,60,source);
  232. fread(bullet_chars,1,4,source);
  233. player_char=fgetc(source);
  234. fseek(source,3,SEEK_CUR);//Skip saved player position
  235. edge_color=fgetc(source);
  236. player_color=fgetc(source);
  237. bullet_color=fgetc(source);
  238. missile_color=fgetc(source);
  239. first_board=fgetc(source);
  240. eg_board=fgetc(source);
  241. die_board=fgetc(source);
  242. eg_x=fgetc(source);
  243. eg_y=fgetc(source);
  244. die_x=fgetc(source);
  245. die_y=fgetc(source);
  246. fread(&lives,2,1,source);
  247. fread(&lives_limit,2,1,source);
  248. fread(&health,2,1,source);
  249. fread(&health_limit,2,1,source);
  250. nme_hurt_nme=fgetc(source);
  251. gosfx=fgetc(source);
  252. fgetc(source);//Blank spot
  253. //Source is at # of boards. Now we complete the Idchars, inserting
  254. //proper info. Then spew remainder of info as well.
  255. for(t1=0;t1<3;t1++)
  256. fwrite(bullet_chars,1,4,dest);//Bullet char arrays x3
  257. for(t1=0;t1<4;t1++)
  258. fputc(player_char,dest);//Player char x4
  259. fputc(player_color,dest);
  260. fputc(missile_color,dest);
  261. for(t1=0;t1<3;t1++)
  262. fputc(bullet_color,dest);//Bullet color x3
  263. fwrite(id_dmg,1,128,dest);//Id dmg portion
  264. //Stuff after idchars...
  265. fwrite(status_counters,1,60,dest);
  266. for(t1=0;t1<30;t1++)
  267. fputc(0,dest);//Blank status counters x2
  268. fputc(edge_color,dest);
  269. fputc(first_board,dest);
  270. if(eg_board==128) eg_board=255;
  271. fputc(eg_board,dest);
  272. if(die_board>=128) die_board=383-die_board;//128 -> 255, 129 -> 254
  273. fputc(die_board,dest);
  274. fwrite(&eg_x,2,1,dest);
  275. fwrite(&eg_y,2,1,dest);
  276. fputc(gosfx,dest);
  277. fwrite(&die_x,2,1,dest);
  278. fwrite(&die_y,2,1,dest);
  279. fwrite(&lives,2,1,dest);
  280. fwrite(&lives_limit,2,1,dest);
  281. fwrite(&health,2,1,dest);
  282. fwrite(&health_limit,2,1,dest);
  283. fputc(nme_hurt_nme,dest);
  284. fputc(0,dest);//Clear projectiles (no)
  285. fputc(0,dest);//Only from swap world (no)
  286. fwrite(palette,1,48,dest);
  287. //Now we need to store the position of the global robot.
  288. //We'll reserve space, save the location, and wait...
  289. long glrob_pos_ptr=ftell(dest);
  290. fwrite("\0\0\0\0",1,4,dest);
  291. //Now get and copy number of boards...
  292. int num_boards=fgetc(source);
  293. fputc(num_boards,dest);
  294. //...copy names of boards...
  295. copy_bytes(num_boards*25);
  296. //...and get old board sizes and positions. Also reserve dest
  297. //space for the new stats at this time.
  298. for(t1=0;t1<num_boards;t1++) {
  299. fread(&orig_board_size[t1],4,1,source);
  300. fread(&orig_board_location[t1],4,1,source);
  301. new_board_stat_ptr[t1]=ftell(dest);
  302. fwrite("\0\0\0\0\0\0\0\0",1,8,dest);
  303. }
  304. //Global robot...
  305. long glrob_pos=ftell(dest);
  306. fseek(dest,glrob_pos_ptr,SEEK_SET);
  307. fwrite(&glrob_pos,4,1,dest);
  308. fseek(dest,glrob_pos,SEEK_SET);
  309. fwrite(global_robot,1,43,dest);
  310. //Do boards.
  311. for(t1=0;t1<num_boards;t1++) {
  312. printf("\n Board #%d... ",t1);
  313. //Empty board?
  314. if(!orig_board_size[t1]) {
  315. printf("(blank)");
  316. continue;
  317. }
  318. //Do board t1- Reserve space...
  319. cboard=(unsigned char huge *)farmalloc(orig_board_size[t1]);
  320. if(cboard==NULL) {
  321. printf("ERROR: Out of memory (board %d, file %s) Conversion aborted\n",t1,fn);
  322. goto abort;
  323. }
  324. //Seek to board
  325. fseek(source,orig_board_location[t1],SEEK_SET);
  326. //Read in board
  327. long done=0;
  328. unsigned char huge *tptr=cboard;
  329. do {
  330. if((orig_board_size[t1]-done)>65535U) {
  331. fread(tptr,65535U,1,source);
  332. tptr+=65535U;
  333. done+=65535U;
  334. }
  335. else {
  336. fread(tptr,orig_board_size[t1]-done,1,source);
  337. break;
  338. }
  339. } while(done<orig_board_size[t1]);
  340. //Convert board
  341. long new_size=convert_board(cboard);
  342. if(!new_size) {
  343. //Board was aborted- No need to change stats.
  344. farfree(cboard);
  345. continue;
  346. }
  347. //Remember location for new board
  348. long new_loc=ftell(dest);
  349. //Write new board
  350. done=0;
  351. tptr=newboard;
  352. do {
  353. if((new_size-done)>65535U) {
  354. fwrite(tptr,65535U,1,dest);
  355. tptr+=65535U;
  356. done+=65535U;
  357. }
  358. else {
  359. fwrite(tptr,new_size-done,1,dest);
  360. break;
  361. }
  362. } while(done<new_size);
  363. //Save stats of new board
  364. fseek(dest,new_board_stat_ptr[t1],SEEK_SET);
  365. fwrite(&new_size,4,1,dest);
  366. fwrite(&new_loc,4,1,dest);
  367. fseek(dest,0,SEEK_END);
  368. //Next board!
  369. farfree(cboard);
  370. }
  371. //Password convert file
  372. if(pro_method) {
  373. printf("\n Password encoding...");
  374. //Calculate xor code for file
  375. int xor=85;
  376. for(t1=0;t1<15;t1++) {
  377. //For each byte, roll once to the left and xor in pw byte if it
  378. //is an odd character, or add in pw byte if it is an even character.
  379. xor<<=1;
  380. if(xor>255) xor^=257;//Wraparound from roll
  381. if(t1&1) {
  382. xor+=password[t1];//Add (even byte)
  383. if(xor>255) xor^=257;//Wraparound from add
  384. }
  385. else xor^=password[t1];//XOR (odd byte);
  386. }
  387. //To factor in protection method, add it in and roll one last time
  388. xor+=pro_method;
  389. if(xor>255) xor^=257;
  390. xor<<=1;
  391. if(xor>255) xor^=257;
  392. //Can't be 0-
  393. if(xor==0) xor=86;//(01010110)
  394. //NOW convert entire dest file, after MZ2.
  395. long end=ftell(dest),cur;
  396. unsigned char bfr[512];
  397. int bfrsiz;
  398. fseek(dest,44,SEEK_SET);
  399. do {
  400. fseek(dest,0,SEEK_CUR);
  401. cur=ftell(dest);
  402. if((end-cur)<512) {
  403. bfrsiz=end-cur;
  404. fread(bfr,1,bfrsiz,dest);
  405. }
  406. else {
  407. fread(bfr,1,512,dest);
  408. bfrsiz=512;
  409. }
  410. for(t1=0;t1<512;t1++)
  411. bfr[t1]^=xor;
  412. fseek(dest,-bfrsiz,SEEK_CUR);
  413. fwrite(bfr,1,bfrsiz,dest);
  414. } while(end!=ftell(dest));
  415. }
  416. //Done!
  417. break;
  418. case 1:
  419. //Board file conversion
  420. //Header for new file
  421. fwrite("\xFFMB2",1,4,dest);
  422. //Get size of old board
  423. fseek(source,0,SEEK_END);
  424. long size=ftell(source)-25;
  425. fseek(source,0,SEEK_SET);
  426. //Allocate memory
  427. cboard=(unsigned char huge *)farmalloc(size);
  428. if(cboard==NULL) {
  429. printf("ERROR: Out of memory, conversion aborted (%s)\n",fn);
  430. goto abort;
  431. }
  432. //Read in board
  433. long done=0;
  434. unsigned char huge *tptr=cboard;
  435. do {
  436. if((size-done)>65535U) {
  437. fread(tptr,65535U,1,source);
  438. tptr+=65535U;
  439. done+=65535U;
  440. }
  441. else {
  442. fread(tptr,size-done,1,source);
  443. break;
  444. }
  445. } while(done<size);
  446. //Convert board
  447. long new_size=convert_board(cboard);
  448. if(!new_size) goto abort;//Board was aborted
  449. //Write new board
  450. done=0;
  451. tptr=newboard;
  452. do {
  453. if((new_size-done)>65535U) {
  454. fwrite(tptr,65535U,1,dest);
  455. tptr+=65535U;
  456. done+=65535U;
  457. }
  458. else {
  459. fwrite(tptr,new_size-done,1,dest);
  460. break;
  461. }
  462. } while(done<new_size);
  463. //Copy board title
  464. fseek(source,-25,SEEK_END);
  465. copy_bytes(25);
  466. farfree(cboard);
  467. break;
  468. }
  469. printf("\n Done!\n");
  470. fclose(source);
  471. fclose(dest);
  472. unlink(temp_name);
  473. return;
  474. abort:
  475. fclose(source);
  476. fclose(dest);
  477. unlink(fn);
  478. rename(temp_name,fn);
  479. }
  480. void rle_to_rle2(unsigned char huge *&source,unsigned char huge *&dest) {
  481. //Converts an rle compressed layer from source to an rle2 compressed
  482. //layer on dest.
  483. int xsiz,ysiz;
  484. int runs,runb;
  485. int size,done=0;
  486. //Check for lonely run of 0 from last rle
  487. if(*source==0) source=source+2;
  488. //Sizes
  489. xsiz=*source; source=source+1;
  490. ysiz=*source; source=source+1;
  491. *dest=xsiz; dest=dest+1;
  492. *dest=0; dest=dest+1;
  493. *dest=ysiz; dest=dest+1;
  494. *dest=0; dest=dest+1;
  495. size=xsiz*ysiz;
  496. //Convert. Source format- RUNSIZE, RUNBYTE, ...
  497. //Dest format- ( BYTE ) | ( RUNSIZE+128, RUNBYTE ), ...
  498. //Conversion method- Read RUNSIZE and RUNBYTE. If RUNSIZE is one,
  499. // write RUNBYTE unless it is >127, then instead write 129,RUNBYTE.
  500. // If RUNSIZE is from two to 127, write RUNSIZE+128,RUNBYTE. If
  501. // RUNSIZE is from 127 to 254, write 255,RUNBYTE,RUNSIZE+1,RUNBYTE.
  502. // If RUNSIZE is 255, write 255,RUNBYTE,255,RUNBYTE then write
  503. // RUNBYTE as if RUNSIZE were 1 (see above)
  504. do {
  505. runs=*source; source=source+1;
  506. runb=*source; source=source+1;
  507. if(!runs) continue;
  508. else if(runs==1) {
  509. single_byte:
  510. if(runb<128) {
  511. *dest=runb; dest=dest+1;
  512. }
  513. else {
  514. *dest=129; dest=dest+1;
  515. *dest=runb; dest=dest+1;
  516. }
  517. goto end_byte;
  518. }
  519. else if(runs<128) {
  520. *dest=runs|128; dest=dest+1;
  521. *dest=runb; dest=dest+1;
  522. }
  523. else if(runs<255) {
  524. *dest=255; dest=dest+1;
  525. *dest=runb; dest=dest+1;
  526. *dest=runs+1; dest=dest+1;
  527. *dest=runb; dest=dest+1;
  528. }
  529. else {
  530. *dest=255; dest=dest+1;
  531. *dest=runb; dest=dest+1;
  532. *dest=255; dest=dest+1;
  533. *dest=runb; dest=dest+1;
  534. goto single_byte;
  535. }
  536. end_byte:
  537. done+=runs;
  538. } while(done<size);
  539. //Done!
  540. }
  541. long convert_board(unsigned char huge *loc) {//Return size
  542. //Converts a stripped board (no header) in loc[] to newboard[].
  543. //Both are already allocated.
  544. int t1,t2,t3;
  545. unsigned char huge *brd=newboard;//use brd[] not newboard[]
  546. unsigned char huge *robptr;//Pointer to robot size storage
  547. int num_robots,num_scrolls,num_sensors;
  548. unsigned int item_size,new_isize,done;//Program/scroll size, position within
  549. unsigned char robold_line[256];
  550. unsigned char robnew_line[256];
  551. *brd=2; brd=brd+1;//2 for a 100x100 board
  552. //Translate all 6 layers
  553. printf("Layers");
  554. for(t1=0;t1<6;t1++) {
  555. printf(".");
  556. rle_to_rle2(loc,brd);
  557. }
  558. printf(" Misc... ");
  559. //Next 39 characters (up thru input_size) are copied exactly
  560. for(t1=0;t1<39;t1++) {
  561. *brd=*loc;
  562. brd=brd+1;
  563. loc=loc+1;
  564. }
  565. //Rememer next info
  566. unsigned char mod_vol=*loc; loc=loc+1;
  567. unsigned char pl_lock_ns=*loc; loc=loc+1;
  568. unsigned char pl_lock_ew=*loc; loc=loc+1;
  569. unsigned char pl_lock_att=*loc; loc=loc+1;
  570. //Copy input string
  571. for(t1=0;t1<81;t1++) {
  572. *brd=*loc;
  573. brd=brd+1;
  574. loc=loc+1;
  575. }
  576. //Skip 9 bytes (blanks and effect durations which are now global)
  577. loc=loc+9;
  578. //Copy last dir moved, adding in a faced dir of south (+16)
  579. *brd=(*loc)|16;
  580. brd=brd+1;
  581. loc=loc+1;
  582. //Copy bottom message
  583. for(t1=0;t1<81;t1++) {
  584. *brd=*loc;
  585. brd=brd+1;
  586. loc=loc+1;
  587. }
  588. //Copy bmesg cycle, lazer cycle, and mesg row
  589. *brd=*loc; brd=brd+1; loc=loc+1;
  590. *brd=*loc; brd=brd+1; loc=loc+1;
  591. *brd=*loc; brd=brd+1; loc=loc+1;
  592. //Copy bmesg column, changing 0 to 255
  593. unsigned char bmesg_col=*loc; loc=loc+1;
  594. if((bmesg_col==0)||(bmesg_col>79)) bmesg_col=255;
  595. *brd=bmesg_col; brd=brd+1;
  596. //Copy x and y scroll bytes, converting to words
  597. unsigned int scroll_x=(unsigned int)(signed char)*loc; loc=loc+1;
  598. unsigned int scroll_y=(unsigned int)(signed char)*loc; loc=loc+1;
  599. *brd=scroll_x&255; brd=brd+1;
  600. *brd=scroll_x>>8; brd=brd+1;
  601. *brd=scroll_y&255; brd=brd+1;
  602. *brd=scroll_y>>8; brd=brd+1;
  603. //Write misc. info and saved info
  604. for(t1=0;t1<4;t1++) {
  605. *brd=255;//Locked x/y info
  606. brd=brd+1;
  607. }
  608. *brd=pl_lock_ns; brd=brd+1;
  609. *brd=pl_lock_ew; brd=brd+1;
  610. *brd=pl_lock_att; brd=brd+1;
  611. *brd=mod_vol; brd=brd+1;
  612. *brd=0; brd=brd+1;//Volume increase (none)
  613. *brd=mod_vol; brd=brd+1;//Volume target (same as current vol)
  614. //Convert robots
  615. *brd=num_robots=*loc; loc=loc+1; brd=brd+1;
  616. printf("Robots... ");
  617. if(num_robots) {
  618. for(t1=0;t1<num_robots;t1++) {
  619. //Convert a robot
  620. //Copy and annotate structure, saving robot's size
  621. item_size=*loc; loc=loc+1;
  622. item_size+=(*loc)<<8; loc=loc+7;
  623. robptr=brd;//Pointer to robot size
  624. *brd=item_size&255; brd=brd+1;
  625. *brd=item_size>>8; brd=brd+3;
  626. if(item_size>31744) {
  627. printf("\n ERROR: Robot over 31k in length, board aborted %d",item_size);
  628. return 0;
  629. }
  630. //Name, char, first word of curr.line
  631. for(t2=0;t2<18;t2++) {
  632. *brd=*loc; brd=brd+1; loc=loc+1;
  633. }
  634. //Skip second word of curr.line
  635. loc=loc+2;
  636. //Copy remaining 9 bytes
  637. for(t2=0;t2<9;t2++) {
  638. *brd=*loc; brd=brd+1; loc=loc+1;
  639. }
  640. //Fill in remainder of v2.00 struct (x, y, future x3, used, loop)
  641. for(t2=0;t2<7;t2++) {
  642. *brd=0; brd=brd+1;
  643. }
  644. *brd=(item_size!=0); brd=brd+1;
  645. *brd=0; brd=brd+1;
  646. *brd=0; brd=brd+1;
  647. //Now convert program.
  648. if(item_size) {
  649. new_isize=done=0;
  650. do {
  651. t2=*loc; loc=loc+1; done++;//Cmd size
  652. if((!t2)||(t2==255)) {
  653. //Same thing
  654. *brd=t2;
  655. brd=brd+1;
  656. new_isize++;
  657. continue;
  658. }
  659. //Read in actual line
  660. robold_line[0]=t2;
  661. for(t3=0;t3<t2;) {
  662. robold_line[++t3]=*loc; loc=loc+1;
  663. }
  664. robold_line[++t3]=*loc; loc=loc+1;
  665. done+=t3;
  666. //Convert line
  667. convert_robot_line(robold_line,robnew_line);
  668. //Write line
  669. t2=robnew_line[0];
  670. for(t3=0;t3<t2+2;t3++) {
  671. *brd=robnew_line[t3]; brd=brd+1;
  672. }
  673. new_isize+=t2+2;
  674. //Loop
  675. } while(done<item_size);
  676. //Write new size
  677. robptr[0]=new_isize&255;
  678. robptr[1]=new_isize>>8;
  679. }
  680. }
  681. }
  682. //Convert scrolls
  683. printf("Scrolls... ");
  684. *brd=num_scrolls=*loc; loc=loc+1; brd=brd+1;
  685. if(num_scrolls) {
  686. for(t1=0;t1<num_scrolls;t1++) {
  687. //Convert a scroll
  688. //Copy and annotate structure, saving scroll's size
  689. *brd=*loc; brd=brd+1; loc=loc+1;
  690. *brd=*loc; brd=brd+3; loc=loc+5;
  691. item_size=*loc; loc=loc+1;
  692. item_size+=(*loc)<<8; loc=loc+3;
  693. *brd=item_size&255; brd=brd+1;
  694. *brd=item_size>>8; brd=brd+1;
  695. *brd=(item_size!=0); brd=brd+1;
  696. if(item_size>31744) {
  697. printf("\n ERROR: Scroll over 31k in length, board aborted");
  698. return 0;
  699. }
  700. //Now copy message, of length item_size
  701. if(item_size) {
  702. for(t2=0;t2<item_size;t2++) {
  703. *brd=*loc; brd=brd+1; loc=loc+1;
  704. if((loc[-1]=='\n')||(loc[-1]==1)) {
  705. //Check for '!' lines w/o \n or 0.
  706. if(*loc=='!') {
  707. if((loc[1]!='\n')&&(loc[1]!=0)) {
  708. *brd=' '; brd=brd+1; loc=loc+1;
  709. *brd=' '; brd=brd+1; loc=loc+1;
  710. t2+=2;
  711. }
  712. }
  713. }
  714. }
  715. }
  716. }
  717. }
  718. //Convert sensors
  719. printf("Sensors... ");
  720. *brd=num_sensors=*loc; loc=loc+1; brd=brd+1;
  721. if(num_sensors) {
  722. for(t1=0;t1<num_sensors;t1++) {
  723. //Convert a sensor
  724. //Copy and annotate structure
  725. for(t2=0;t2<31;t2++) {
  726. *brd=*loc; brd=brd+1; loc=loc+1;
  727. }
  728. *brd=1; brd=brd+1;
  729. }
  730. }
  731. //Return bytes used
  732. printf("Done!");
  733. return brd-newboard;
  734. }
  735. void convert_robot_line(unsigned char far *source,unsigned char far *dest) {
  736. int cmd=source[1];
  737. int sp=2,dp=2,cp=0;//Source/Dest/Cmd position ptr
  738. int t1,t2;
  739. dest[1]=cmd;
  740. //Format- LEN CMD PARAMS LEN
  741. //New param format- 0 then 2 byte number OR # then #-length string
  742. if(cmd_formats[cmd][0]=='O') {
  743. //Outdated
  744. if(cmd_formats[cmd][1]=='S') {
  745. //Special case- if player (not) [dir] [str]
  746. //Becomes- if (not) touching [dir] [str]
  747. dest[1]=cmd-46;//cmd 18 or 19
  748. dest[dp++]=0;
  749. dest[dp++]=3;//Condition of touching
  750. dest[dp++]=source[sp++];//Direction
  751. //Now we need to convert a string
  752. cp=2;//So we exit the loop afterwards
  753. goto str_conv;
  754. }
  755. else {
  756. //Change dest cmd, then use remainder of format
  757. cp=1;
  758. switch(cmd) {
  759. case 13:
  760. case 14:
  761. case 15:
  762. dest[1]=cmd-3;
  763. break;
  764. case 17:
  765. dest[1]=16;
  766. break;
  767. case 158:
  768. dest[1]=40;
  769. break;
  770. case 166:
  771. dest[1]=153;
  772. break;
  773. case 167:
  774. dest[1]=139;
  775. break;
  776. }
  777. goto normal_conv;
  778. }
  779. }
  780. else {
  781. normal_conv:
  782. //Normal conversion
  783. while(cmd_formats[cmd][cp]) {
  784. //Get type of parameter
  785. t1=cmd_formats[cmd][cp++];
  786. //Convert
  787. switch(t1) {
  788. case 1:
  789. case 10:
  790. //Two byte number conversion (also works for conditions)
  791. dest[dp++]=0;
  792. dest[dp++]=source[sp++];
  793. dest[dp++]=source[sp++];
  794. break;
  795. case 2:
  796. case 4:
  797. case 6:
  798. case 7:
  799. case 8:
  800. case 9:
  801. //One byte unsigned number conversion
  802. dest[dp++]=0;
  803. dest[dp++]=source[sp++];
  804. dest[dp++]=0;
  805. break;
  806. case 3:
  807. str_conv:
  808. //String conversion (old format- null terminated)
  809. t1=dp++;//Save location for size
  810. t2=0;//Size of string
  811. while(source[sp]) {
  812. if(source[sp]=='&') {//Replcae & with &&
  813. if((cmd==38)||(cmd==102)||(cmd==109)||(cmd==111)||
  814. (cmd==121)||(cmd==122)||(cmd==145)||(cmd==103)||
  815. (cmd==104)||(cmd==105)||(cmd==116)||(cmd==117)) {
  816. dest[dp++]='&';
  817. t2++;
  818. }
  819. }
  820. dest[dp++]=source[sp++];
  821. t2++;
  822. };
  823. dest[dp++]=source[sp++];
  824. dest[t1]=t2+1;
  825. break;
  826. case 5:
  827. //Color (next source byte holds bit 256)
  828. dest[dp++]=0;
  829. dest[dp++]=source[sp++];
  830. dest[dp++]=source[sp]>>7;
  831. break;
  832. case 11:
  833. //Thing conversion
  834. dest[dp++]=0;
  835. dest[dp++]=source[sp++]&127;
  836. dest[dp++]=0;
  837. break;
  838. case 12:
  839. //Parameter conversion
  840. dest[dp++]=0;
  841. t1=source[sp++];
  842. if(t1) {
  843. dest[dp++]=t1;
  844. dest[dp++]=0;
  845. }
  846. else {
  847. dest[dp++]=0;
  848. dest[dp++]=1;
  849. }
  850. break;
  851. case 13:
  852. //Missing parameter conversion
  853. dest[dp++]=0;
  854. dest[dp++]=0;
  855. dest[dp++]=1;
  856. break;
  857. case 14:
  858. //Signed number (1-byte) conversion
  859. dest[dp++]=0;
  860. t1=(signed int)(signed char)source[sp++];
  861. dest[dp++]=((unsigned int)t1)&255;
  862. dest[dp++]=((unsigned int)t1)>>8;
  863. break;
  864. }
  865. //Loop until done
  866. };
  867. }
  868. //Done with this line- store new size
  869. dest[0]=dp-1;
  870. dest[dp]=dp-1;
  871. }
  872. //New (and old, usually) command formats.
  873. //1- number
  874. //2- number (one-byte originally)
  875. //3- string
  876. //4- char
  877. //5- color (see thing for bit 256 originally)
  878. //6- color NOT with a thing
  879. //7- direction
  880. //8- item
  881. //9- conditional
  882. //A- condition
  883. //B- thing
  884. //C- param (convert 0 to 256)
  885. //D- param (originally not there, use a 256)
  886. //E- number (one-byte signed originally)
  887. //Only commands avail. in ver 1.03 are listed.
  888. char far *cmd_formats[256]={
  889. "",
  890. "",
  891. "\x02",
  892. "\x02",
  893. "\x07\x02",
  894. "\x07",
  895. "\x05\x0B\x0C",
  896. "\x04",
  897. "\x05",
  898. "\x0E\x0E",
  899. "\x03\x01",
  900. "\x03\x01",
  901. "\x03\x01",
  902. "O\x03\x03",//ODT
  903. "O\x03\x03",//ODT
  904. "O\x03\x03",//ODT
  905. "\x03\x09\x01\x03",
  906. "O\x03\x09\x03\x03",//ODT
  907. "\x0A\x03",
  908. "\x0A\x03",
  909. "\x05\x0B\x0D\x03",
  910. "\x05\x0B\x0D\x03",
  911. "\x05\x0B\x0D\x07\x03",
  912. "\x05\x0B\x0D\x07\x03",
  913. "\x05\x0B\x0D\x0E\x0E\x03",
  914. "\x0E\x0E\x03",
  915. "\x07\x05\x0B\x0D\x03",
  916. "\x03",
  917. "\x03",
  918. "\x03",
  919. "\x03\x03",
  920. "\x02",
  921. "\x05\x0B\x0C\x07",
  922. "\x01\x08",
  923. "\x01\x08",
  924. "\x01\x08\x03",
  925. "",
  926. "",
  927. "\x03",
  928. "\x01\x03",
  929. "\x02",
  930. "",
  931. "",
  932. "\x03",
  933. "",
  934. "\x03",
  935. "",
  936. "",//BLANK LINE
  937. "\x02",
  938. "\x03",
  939. "\x07",
  940. "",
  941. "",
  942. "\x07\x03",
  943. "\x03\x02",
  944. "\x03\x02",
  945. "",
  946. "",
  947. "",
  948. "",
  949. "",
  950. "\x07",
  951. "\x07\x03",
  952. "\x0E\x0E",
  953. "OS",//ODT SPECIAL
  954. "OS",//ODT SPECIAL
  955. "\x0E\x0E\x03",
  956. "\x07",
  957. "\x07\x03",
  958. "",
  959. "",
  960. "\x07\x07",
  961. "\x07",
  962. "\x07",
  963. "\x07",
  964. "\x07",
  965. "\x07",
  966. "\x07",
  967. "\x07\x02",
  968. "\x05\x0B\x0C\x0E\x0E",
  969. "",
  970. "\x0E\x0E\x03",
  971. "\x03",
  972. "\x0E\x0E",
  973. "\x07",
  974. "\x07",
  975. "\x0E\x0E",
  976. "\x04",
  977. "\x04",
  978. "\x04",
  979. "\x04",
  980. "\x05",
  981. "\x05\x03",
  982. "\x05",
  983. "\x05\x03",
  984. "\x03\x01\x01",
  985. "\x03\x01\x01",
  986. "\x03\x01\x01",
  987. "\x01\x08\x01\x08\x03",
  988. "\x07\x03",
  989. "\x05\x0B\x0C\x07",
  990. "\x03",
  991. "\x03",
  992. "\x03",
  993. "\x03\x03",
  994. "\x03\x03\x03",
  995. "\x03",
  996. "\x03",
  997. "\x03",
  998. "\x03\x0E\x0E",
  999. "\x07\x02",
  1000. "\x03",
  1001. "\x03\x03",
  1002. "\x03\x03",
  1003. "\x03\x03",
  1004. "\x04",
  1005. "\x03",
  1006. "\x03",
  1007. "\x05\x0B\x0D\x07",
  1008. "\x0E\x0E\x0E\x0E",
  1009. "\x05",
  1010. "\x07\x03",
  1011. "\x07",
  1012. "\x04\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02",
  1013. "",
  1014. "",
  1015. "\x02",
  1016. "\x02",
  1017. "\x02",
  1018. "\x02",
  1019. "\x02",
  1020. "",
  1021. "\x07\x07",
  1022. "",
  1023. "",
  1024. "\x05\x0B\x0D\x05\x0B\x0C",
  1025. "\x05",
  1026. "\x05",
  1027. "\x05",
  1028. "\x02",
  1029. "",
  1030. "",
  1031. "",
  1032. "\x01\x04",
  1033. "\x02",
  1034. "\x03",
  1035. "",
  1036. "\x07\x04",
  1037. "\x07\x04",
  1038. "\x01",
  1039. "",
  1040. "",
  1041. "",
  1042. "\x02",
  1043. "",
  1044. "",
  1045. "",
  1046. "\x01\x02",
  1047. "O\x03",//ODT
  1048. "\x05",
  1049. "\x05",
  1050. "\x05",
  1051. "\x05",
  1052. "\x05",
  1053. "\x02\x02",
  1054. "\x02\x02",
  1055. "O\x3",//ODT
  1056. "O\x3" };//ODT