tttiler.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592
  1. /******************************************************************************
  2. *
  3. * project name: TI-68k Developer Utilities
  4. * file name: tttiler.c
  5. * initial date: 24/11/2000
  6. * authors: thomas.nussbaumer@gmx.net
  7. * description: splits a binary image file (ImageStudio) into tiles
  8. *
  9. ******************************************************************************/
  10. /*
  11. This file is part of TI-68k Developer Utilities.
  12. This file is free software; you can redistribute it and/or
  13. modify it under the terms of the GNU Lesser General Public
  14. License as published by the Free Software Foundation; either
  15. version 2.1 of the License, or (at your option) any later version.
  16. As a special exception, UNMODIFIED copies of tttiler may also be
  17. redistributed or sold without source code, for any purpose. (The Lesser
  18. General Public License restrictions do apply in other respects; for example,
  19. they cover modification of the program.) This exception notice must be
  20. removed on modified copies of this file.
  21. This program is distributed in the hope that it will be useful,
  22. but WITHOUT ANY WARRANTY; without even the implied warranty of
  23. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  24. Lesser General Public License for more details.
  25. You should have received a copy of the GNU Lesser General Public
  26. License along with this library; if not, write to the Free Software
  27. Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  28. */
  29. #include <stdio.h>
  30. #include <stdlib.h>
  31. #include <string.h>
  32. #include <ctype.h>
  33. #include "tt.h" // generic defines
  34. #include "ttversion.h" // TI-68k Developer Utilities version info
  35. #include "revtools.h"
  36. #ifdef FILE_REVISION
  37. #undef FILE_REVISION
  38. #endif
  39. #define FILE_REVISION "1.7"
  40. //=============================================================================
  41. // outputs usage information of this tool
  42. //=============================================================================
  43. void PrintUsage() {
  44. fprintf(USAGE_OUT, "Usage: tttiler [-h|-v|-ht|-vt] <infile> <width> <height> <t_width> <t_height> <entries> <outfile> (array_name)\n"\
  45. " -h ... tile from left to right and up to down\n"\
  46. " -v ... tile from up to down and left to right\n"\
  47. " -ht ... like -h, but generates complete test program\n"\
  48. " -vt ... like -v, but generates complete test program\n"\
  49. " infile ... binary image file generated with ImageStudio\n"\
  50. " width ... width of infile in pixel\n"\
  51. " height ... height of infile in pixel\n"\
  52. " t_width ... width of one tile in pixel (<=32)\n"\
  53. " t_height ... height of one tile in pixel\n"\
  54. " entries ... number of data fields per line (0<entries<=20)\n"\
  55. " outfile ... output filename (use - as name for output to stdout)\n"\
  56. " array_name ... optional name of array to generate\n\n"\
  57. " splits binary image file generated with ImageStudio in single\n"\
  58. " sprites (tiles) and generates C source code\n"\
  59. " including the necessary macros to access them.\n\n"\
  60. "NOTE: only 8, 16 and 32 pixel wide tiles are generated.\n"\
  61. " If the tilewidth is not exactly one of these widths,\n"\
  62. " the sprites are filled up to the right with empty pixels\n"\
  63. "NOTE2: the width of the input file have to be a multiple of 8\n"\
  64. " otherwise ImageStudio and tttiler will not treat it correctly\n\n");
  65. }
  66. #define DIR_HORIZONTAL 0
  67. #define DIR_VERTICAL 1
  68. #define MODE_MONO 0
  69. #define MODE_GRAY4 1
  70. #define TESTPRG_ON 0
  71. #define TESTPRG_OFF 1
  72. //-----------------------------------------------------------------------------
  73. // globals
  74. //
  75. // to reduce the function parameters we are using almost only globals
  76. // (bad idea in general, but perfect for rapid prototyping)
  77. //-----------------------------------------------------------------------------
  78. FILE* outfp;
  79. int width;
  80. int height;
  81. int tilewidth;
  82. int tileheight;
  83. int direction;
  84. int mode;
  85. int hcount;
  86. int vcount;
  87. long insize;
  88. unsigned char* buffer;
  89. int dest_width;
  90. int padding;
  91. int entries;
  92. int padding_mask;
  93. char* arrayname;
  94. char str_height[255];
  95. char str_nr[255];
  96. char str_macro[255];
  97. //=============================================================================
  98. // converts given string into uppercase
  99. //=============================================================================
  100. void ToUppercase(char* str) {
  101. while (*str) {
  102. *str = (char)toupper(*str);
  103. str++;
  104. }
  105. }
  106. //=============================================================================
  107. // extract a single tile
  108. //=============================================================================
  109. void WriteTile(long offset,int x,int y) {
  110. int h;
  111. int bytes_per_line = width/8;
  112. unsigned char* addr = buffer + offset + y*bytes_per_line + x/8;
  113. unsigned int data1 = 0;
  114. //unsigned int data2 = 0;
  115. unsigned int shift = x % 8;
  116. for (h=0;h<tileheight;h++) {
  117. switch(dest_width) {
  118. case 8:
  119. data1 = (*addr & 0xff) << 8;
  120. data1 |= (*(addr+1) & 0xff);
  121. data1 = (data1 >> (8-shift)) & padding_mask;
  122. fprintf(outfp,"0x%02x",data1);
  123. break;
  124. case 16:
  125. data1 = (*addr & 0xff) << 16;
  126. data1 |= (*(addr+1) & 0xff) << 8;
  127. data1 |= (*(addr+2) & 0xff);
  128. data1 = (data1 >> (8-shift)) & padding_mask;
  129. fprintf(outfp,"0x%04x",data1);
  130. break;
  131. default:
  132. data1 = (*addr & 0xff) << 24;
  133. data1 |= (*(addr+1) & 0xff) << 16;
  134. data1 |= (*(addr+2) & 0xff) << 8;
  135. data1 |= (*(addr+3) & 0xff);
  136. if (shift) {
  137. data1 = (data1 << shift) & padding_mask;
  138. data1 |= (*(addr+4) & 0xff) >> (8-shift);
  139. }
  140. data1 &= padding_mask;
  141. fprintf(outfp,"0x%08x",data1);
  142. break;
  143. }
  144. if (h == tileheight-1) {}//fprintf(outfp,"");
  145. else if (!((h+1) % entries)) fprintf(outfp,",\n");
  146. else fprintf(outfp,",");
  147. addr += bytes_per_line;
  148. }
  149. }
  150. //=============================================================================
  151. // process a complete plane starting at given offset
  152. //=============================================================================
  153. void ProcessPlane(long offset) {
  154. int x;
  155. int y;
  156. if (direction == DIR_HORIZONTAL) {
  157. for (y=0;y<vcount;y++) {
  158. for (x=0;x<hcount;x++) {
  159. fprintf(outfp,"// tile %d\n",y*hcount+x);
  160. WriteTile(offset,x*tilewidth,y*tileheight);
  161. if ((x == hcount - 1) && (y == vcount - 1)) {
  162. fprintf(outfp,"\n");
  163. }
  164. else {
  165. fprintf(outfp,",\n");
  166. }
  167. }
  168. }
  169. }
  170. else {
  171. for (x=0;x<hcount;x++) {
  172. for (y=0;y<vcount;y++) {
  173. fprintf(outfp,"// tile %d\n",x*vcount+y);
  174. WriteTile(offset,x*tilewidth,y*tileheight);
  175. if ((x == hcount - 1) && (y == vcount - 1)) {
  176. fprintf(outfp,"\n");
  177. }
  178. else {
  179. fprintf(outfp,",\n");
  180. }
  181. }
  182. }
  183. }
  184. }
  185. //=============================================================================
  186. // write test program - part 1
  187. //=============================================================================
  188. void WriteTestProgram1() {
  189. fprintf(outfp,"#define SAVE_SCREEN\n");
  190. fprintf(outfp,"#include <tigcclib.h>\n");
  191. fprintf(outfp,"short _ti89,_ti92plus;\n\n\n");
  192. }
  193. //=============================================================================
  194. // write test program - part 2
  195. //=============================================================================
  196. void WriteTestProgram2() {
  197. fprintf(outfp,"\n\nvoid _main(void) {\n");
  198. fprintf(outfp," short x,y;\n");
  199. fprintf(outfp," short tilewidth = %d;\n",tilewidth);
  200. fprintf(outfp," short vcount = %d;\n",vcount);
  201. fprintf(outfp," short hcount = %d;\n",hcount);
  202. if (mode == MODE_GRAY4) {
  203. fprintf(outfp," short i;\n");
  204. fprintf(outfp," if (!GrayOn()) return;\n");
  205. fprintf(outfp," memset(GetPlane(0),0,LCD_SIZE);\n");
  206. fprintf(outfp," memset(GetPlane(1),0,LCD_SIZE);\n");
  207. }
  208. else {
  209. fprintf(outfp," memset(LCD_MEM,0,LCD_SIZE);\n");
  210. }
  211. if (direction == DIR_HORIZONTAL) {
  212. fprintf(outfp," for (y=0;y<vcount;y++) {\n");
  213. fprintf(outfp," for (x=0;x<hcount;x++) { \n");
  214. fprintf(outfp," short nr = y*hcount+x;\n");
  215. }
  216. else {
  217. fprintf(outfp," for (x=0;x<hcount;y++) {\n");
  218. fprintf(outfp," for (y=0;y<vcount;y++) { \n");
  219. fprintf(outfp," short nr = x*vcount+y);\n");
  220. }
  221. if (mode == MODE_GRAY4) {
  222. fprintf(outfp," for (i=0;i<2;i++) {\n");
  223. fprintf(outfp," Sprite%d(x*tilewidth,y*%s,%s,%s(i,nr),GetPlane(i),SPRT_OR);\n",dest_width,str_height,str_height,str_macro);
  224. fprintf(outfp," }\n");
  225. }
  226. else {
  227. fprintf(outfp," Sprite%d(x*tilewidth,y*%s,%s,%s(nr),LCD_MEM,SPRT_OR);\n",dest_width,str_height,str_height,str_macro);
  228. }
  229. fprintf(outfp," }\n");
  230. fprintf(outfp," }\n");
  231. fprintf(outfp," ngetchx();\n");
  232. if (mode == MODE_GRAY4) fprintf(outfp," GrayOff();\n");
  233. fprintf(outfp,"}\n\n");
  234. }
  235. //=============================================================================
  236. // nomen omen est
  237. //=============================================================================
  238. int main(int argc, char* argv[]) {
  239. FILE* infp;
  240. int i;
  241. int testprg;
  242. // write it only when not in "output to stdout" mode !!!
  243. if (!(argc >= 9 && !strcmp(argv[8],"-"))) {
  244. PRINT_ID("TTTiler");
  245. }
  246. if (argc == 1) {
  247. PrintUsage();
  248. return 1;
  249. }
  250. if (argc != 9 && argc != 10) {
  251. fprintf(stderr,"ERROR: invalid number of parameters\n");
  252. PrintUsage();
  253. return 1;
  254. }
  255. //-------------------------------------------------------------------------
  256. // parse direction flag
  257. //-------------------------------------------------------------------------
  258. if (!strcmp(argv[1], "-h")) direction = DIR_HORIZONTAL, testprg = TESTPRG_OFF;
  259. else if (!strcmp(argv[1], "-v")) direction = DIR_VERTICAL, testprg = TESTPRG_OFF;
  260. else if (!strcmp(argv[1], "-ht")) direction = DIR_HORIZONTAL, testprg = TESTPRG_ON;
  261. else if (!strcmp(argv[1], "-vt")) direction = DIR_VERTICAL, testprg = TESTPRG_ON;
  262. else {
  263. fprintf(stderr,"ERROR: neither -h nor -v and neither -ht nor -vt specified\n");
  264. PrintUsage();
  265. return 1;
  266. }
  267. //-------------------------------------------------------------------------
  268. // parse width/height/tilewidth/tileheight/entries
  269. //-------------------------------------------------------------------------
  270. if (sscanf(argv[3],"%d",&width) != 1) {
  271. fprintf(stderr,"ERROR: cannot parse width=%s\n",argv[3]);
  272. PrintUsage();
  273. return 1;
  274. }
  275. if (width % 8) {
  276. fprintf(stderr,"ERROR: width not multiple of 8 (width=%d)\n",width);
  277. PrintUsage();
  278. return 1;
  279. }
  280. if (width <= 0) {
  281. fprintf(stderr,"ERROR: negative or zero width not allowed (width=%d)\n",width);
  282. PrintUsage();
  283. return 1;
  284. }
  285. if (sscanf(argv[4],"%d",&height) != 1) {
  286. fprintf(stderr,"ERROR: cannot parse height=%s\n",argv[4]);
  287. PrintUsage();
  288. return 1;
  289. }
  290. if (height <= 0) {
  291. fprintf(stderr,"ERROR: negative or zero height not allowed (height=%d)\n",height);
  292. PrintUsage();
  293. return 1;
  294. }
  295. if (sscanf(argv[5],"%d",&tilewidth) != 1) {
  296. fprintf(stderr,"ERROR: cannot parse tilewidth=%s\n",argv[5]);
  297. PrintUsage();
  298. return 1;
  299. }
  300. if (tilewidth <= 0) {
  301. fprintf(stderr,"ERROR: negative or zero tilewidth not allowed (tilewidth=%d)\n",tilewidth);
  302. PrintUsage();
  303. return 1;
  304. }
  305. if (tilewidth > 32) {
  306. fprintf(stderr,"ERROR: tilewidth larger than 32 not allowed (tilewidth=%d)\n",tilewidth);
  307. PrintUsage();
  308. return 1;
  309. }
  310. if (tilewidth <= 8) dest_width = 8;
  311. else if (tilewidth <= 16) dest_width = 16;
  312. else dest_width = 32;
  313. padding = dest_width - tilewidth;
  314. padding_mask = 0;
  315. for (i=0;i<padding;i++) padding_mask |= 1 << i;
  316. padding_mask = ~padding_mask;
  317. if (tilewidth <= 8) padding_mask &= 0xff;
  318. else if (tilewidth <= 16) padding_mask &= 0xffff;
  319. if (tilewidth > width) {
  320. fprintf(stderr,"ERROR: tilewidth larger than width\n");
  321. PrintUsage();
  322. return 1;
  323. }
  324. if (sscanf(argv[6],"%d",&tileheight) != 1) {
  325. fprintf(stderr,"ERROR: cannot parse tileheight=%s\n",argv[6]);
  326. PrintUsage();
  327. return 1;
  328. }
  329. if (tileheight <= 0) {
  330. fprintf(stderr,"ERROR: negative or zero tileheight not allowed (tileheight=%d)\n",tileheight);
  331. PrintUsage();
  332. return 1;
  333. }
  334. if (tileheight > height) {
  335. fprintf(stderr,"ERROR: tileheight larger than height\n");
  336. PrintUsage();
  337. return 1;
  338. }
  339. if (sscanf(argv[7],"%d",&entries) != 1) {
  340. fprintf(stderr,"ERROR: cannot parse entries=%s\n",argv[7]);
  341. PrintUsage();
  342. return 1;
  343. }
  344. if (entries <= 0 || entries > 20) {
  345. fprintf(stderr,"ERROR: invalid value for entries (entries=%d)\n",entries);
  346. PrintUsage();
  347. return 1;
  348. }
  349. hcount = width / tilewidth;
  350. vcount = height / tileheight;
  351. //-------------------------------------------------------------------------
  352. // open inputfile
  353. //-------------------------------------------------------------------------
  354. if (!(infp = fopen(argv[2],"rb"))) {
  355. fprintf(stderr,"ERROR: cannot open inputfile %s\n",argv[2]);
  356. PrintUsage();
  357. return 1;
  358. }
  359. //-------------------------------------------------------------------------
  360. // get and check input size
  361. //-------------------------------------------------------------------------
  362. if (fseek(infp,0,SEEK_END)) {
  363. fprintf(stderr,"ERROR: cannot find end of inputfile %s\n",argv[2]);
  364. PrintUsage();
  365. fclose(infp);
  366. return 1;
  367. }
  368. insize = ftell(infp);
  369. if (insize == -1L) {
  370. fprintf(stderr,"ERROR: cannot evaluate size of inputfile %s\n",argv[2]);
  371. PrintUsage();
  372. fclose(infp);
  373. return 1;
  374. }
  375. rewind(infp);
  376. if (insize == (long)height*(long)width/8) {
  377. mode = MODE_MONO;
  378. }
  379. else if (insize == (long)height*(long)width/4) {
  380. mode = MODE_GRAY4;
  381. }
  382. else {
  383. fprintf(stderr,"ERROR: filesize (%ld) doesn't correspond with height/width\n",insize);
  384. PrintUsage();
  385. fclose(infp);
  386. return 1;
  387. }
  388. //-------------------------------------------------------------------------
  389. // allocate buffer, read in all bytes and close input file
  390. //-------------------------------------------------------------------------
  391. if (!(buffer = malloc(insize))) {
  392. fprintf(stderr,"ERROR: cannot allocate %ld bytes for input data\n",insize);
  393. PrintUsage();
  394. fclose(infp);
  395. return 1;
  396. }
  397. if (fread(buffer,insize,1,infp) != 1) {
  398. fprintf(stderr,"ERROR: cannot read %ld bytes from inputfile %s\n",insize,argv[2]);
  399. PrintUsage();
  400. fclose(infp);
  401. free(buffer);
  402. return 1;
  403. }
  404. fclose(infp);
  405. //-------------------------------------------------------------------------
  406. // open outputfile
  407. //-------------------------------------------------------------------------
  408. if (!strcmp(argv[8],"-")) {
  409. outfp = stdout;
  410. }
  411. else if (!(outfp = fopen(argv[8],"w"))) {
  412. fprintf(stderr,"ERROR: cannot open outputfile %s\n",argv[8]);
  413. PrintUsage();
  414. free(buffer);
  415. return 1;
  416. }
  417. if (argc == 10) arrayname = argv[9];
  418. else arrayname = "data";
  419. if (outfp != stdout) {
  420. printf("infile = %s\n",argv[2]);
  421. printf("filesize = %ld\n",insize);
  422. printf("direction = %s\n",((direction==DIR_HORIZONTAL) ? "HORIZONTAL":"VERTICAL"));
  423. printf("mode = %s\n",((mode==MODE_MONO) ? "MONO":"GRAY4"));
  424. printf("width = %d\n",width);
  425. printf("height = %d\n",height);
  426. printf("tilewidth = %d\n",tilewidth);
  427. printf("tileheight = %d\n",tileheight);
  428. printf("hcount = %d\n",hcount);
  429. printf("vcount = %d\n",vcount);
  430. printf("tilecount = %d\n",hcount * vcount);
  431. printf("destwidth = %d\n",dest_width);
  432. printf("padding = %d\n",padding);
  433. printf("paddmask = 0x%08x\n",padding_mask);
  434. printf("outfile = %s\n",argv[8]);
  435. printf("arrayname = %s\n",arrayname);
  436. }
  437. sprintf(str_nr,"TILENUMBER_%s",arrayname);
  438. ToUppercase(str_nr);
  439. sprintf(str_height,"TILEHEIGHT_%s",arrayname);
  440. ToUppercase(str_height);
  441. sprintf(str_macro,"TILEADDR_%s",arrayname);
  442. ToUppercase(str_macro);
  443. if (testprg == TESTPRG_ON) WriteTestProgram1();
  444. //-------------------------------------------------------------------------
  445. // write header
  446. //-------------------------------------------------------------------------
  447. fprintf(outfp,"// number of tiles in array %s\n",arrayname);
  448. fprintf(outfp,"#define %s %d\n\n",str_nr,hcount*vcount);
  449. fprintf(outfp,"// height of one tile in array %s\n",arrayname);
  450. fprintf(outfp,"#define %s %d\n\n",str_height,tileheight);
  451. if (mode == MODE_GRAY4) {
  452. fprintf(outfp,"// macro returns the address of tile nr of plane p from array %s\n",arrayname);
  453. fprintf(outfp,"#define %s(p,nr) &(%s[p][%s*nr])\n\n",str_macro,arrayname,str_height);
  454. }
  455. else {
  456. fprintf(outfp,"// macro returns the address of tile nr from array %s\n",arrayname);
  457. fprintf(outfp,"#define %s(nr) &(%s[%s*nr])\n\n",str_macro,arrayname,str_height);
  458. }
  459. switch(dest_width) {
  460. case 8: fprintf(outfp,"unsigned char %s",arrayname); break;
  461. case 16: fprintf(outfp,"unsigned short %s",arrayname); break;
  462. default: fprintf(outfp,"unsigned long %s",arrayname); break;
  463. }
  464. if (mode == MODE_GRAY4) fprintf(outfp,"[2][%s*%s] = {{\n",str_nr,str_height);
  465. else fprintf(outfp,"[%s*%s] = {\n",str_nr,str_height);
  466. ProcessPlane(0);
  467. if (mode == MODE_GRAY4) {
  468. fprintf(outfp,"},\n// ---- plane 2 ----\n{\n"/*,hcount*vcount*tileheight*/);
  469. ProcessPlane(insize/2);
  470. fprintf(outfp,"}");
  471. }
  472. fprintf(outfp,"};\n");
  473. if (testprg == TESTPRG_ON) WriteTestProgram2();
  474. if (outfp != stdout) fclose(outfp);
  475. free(buffer);
  476. return 0;
  477. }
  478. //#############################################################################
  479. //###################### NO MORE FAKES BEYOND THIS LINE #######################
  480. //#############################################################################
  481. //
  482. //=============================================================================
  483. // Revision History
  484. //=============================================================================
  485. //
  486. // Revision 1.7 2009/01/25 Lionel Debroux
  487. // Changes by Romain Liévin and/or me for 64-bit compatibility.
  488. // Adapt to new version display (revtools.h).
  489. //
  490. // Revision 1.6 2002/02/07 09:49:38 tnussb
  491. // all local includes changed, because header files are now located in pctools folder
  492. //
  493. // Revision 1.5 2001/06/20 13:05:41 Thomas Nussbaumer
  494. // (1) tilenumber output corrected
  495. // (2) suppressing following comma after the last tile of a plane
  496. // (3) writing now macros to access the tiles
  497. // (4) handling of output redirection to stdout (outfilename == "-")
  498. // (5) customizable arrayname (commandline parameter)
  499. // (6) test program output adapted to TIGCC 0.90 (int -> short)
  500. //
  501. // Revision 1.4 2000/11/28 00:08:29 Thomas Nussbaumer
  502. // using now USAGE_OUT stream for usage info
  503. //
  504. // Revision 1.3 2000/11/27 23:25:46 Thomas Nussbaumer
  505. // bug fix: generating now correct test program for monochrome tiles, too
  506. //
  507. // Revision 1.2 2000/11/26 21:35:02 Thomas Nussbaumer
  508. // (1) some debug outputs removed
  509. // (2) 16 pixel-wide sprites mode fixed
  510. //
  511. // Revision 1.1 2000/11/26 20:01:02 Thomas Nussbaumer
  512. // initial version
  513. //
  514. //
  515. //