ttunarchive.c 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. /******************************************************************************
  2. *
  3. * project name: TI-68k Developer Utilities
  4. * file name: ttunarchive.c
  5. * initial date: 29/01/2002
  6. * authors: thomas.nussbaumer@gmx.net
  7. * description: unpacks files generated by ttarchive
  8. *
  9. * -----------------------------------------------------------------------------
  10. *
  11. * based on code from Pasi 'Albert' Ojala, albert@cs.tut.fi
  12. *
  13. * heavily reduced to fit to the needs by thomas.nussbaumer@gmx.net
  14. *
  15. *
  16. * NOTE: this tool is quite a hack done in 30 minutes by taking ttunebk.c as
  17. * base code ... don't expect "wonders" here ... ;-)
  18. *
  19. *
  20. ******************************************************************************/
  21. /*
  22. This file is part of TI-68k Developer Utilities.
  23. This file is free software; you can redistribute it and/or
  24. modify it under the terms of the GNU Lesser General Public
  25. License as published by the Free Software Foundation; either
  26. version 2.1 of the License, or (at your option) any later version.
  27. As a special exception, UNMODIFIED copies of ttunarchive may also be
  28. redistributed or sold without source code, for any purpose. (The Lesser
  29. General Public License restrictions do apply in other respects; for example,
  30. they cover modification of the program.) This exception notice must be
  31. removed on modified copies of this file.
  32. This program is distributed in the hope that it will be useful,
  33. but WITHOUT ANY WARRANTY; without even the implied warranty of
  34. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  35. Lesser General Public License for more details.
  36. You should have received a copy of the GNU Lesser General Public
  37. License along with this library; if not, write to the Free Software
  38. Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  39. */
  40. #include <stdio.h>
  41. #include <stdlib.h>
  42. #include <string.h>
  43. #include <ctype.h>
  44. #include "unpack.c"
  45. #include "tt.h" // generic defines
  46. #include "ttversion.h" // TI-68k Developer Utilities version info
  47. #include "revtools.h"
  48. #include "ttunpack.h" // errorcodes definition
  49. #include "packhead.h" // compressed header definition
  50. #include "ttarchive.h" // ttarchive definitions
  51. #ifdef FILE_REVISION
  52. #undef FILE_REVISION
  53. #endif
  54. #define FILE_REVISION "1.3"
  55. //=============================================================================
  56. // outputs usage information of this tool
  57. //=============================================================================
  58. void PrintUsage() {
  59. fprintf(USAGE_OUT, "Usage: ttunarchive <infile> [<entry_number> <outfile>]\n\n"\
  60. " extracts one entry of an TTArchive into a file\n"\
  61. " (entry_number starts with 0). If no entry number\n"\
  62. " and outfile are given, ttunarchive lists only\n"\
  63. " the contents of the TTArchive\n\n");
  64. }
  65. //=============================================================================
  66. // our main reason why we are here ...
  67. //=============================================================================
  68. int main(int argc, char* argv[]) {
  69. unsigned char* src;
  70. FILE* fp;
  71. char* infilename = NULL;
  72. char* outfilename = NULL;
  73. char* entrynumber = NULL;
  74. long insize;
  75. short nr_entries;
  76. short i;
  77. short extract_idx = 0; // 1.40: default initialization, hope it is correct.
  78. unsigned short origsize;
  79. short show_content = 0;
  80. PRINT_ID("TTUnArchive");
  81. for (i=1;i<argc;i++) {
  82. if (!infilename) infilename = argv[i];
  83. else if (!entrynumber) entrynumber = argv[i];
  84. else if (!outfilename) outfilename = argv[i];
  85. else {
  86. PrintUsage();
  87. return 1;
  88. }
  89. }
  90. if (infilename && !entrynumber && !outfilename) {
  91. show_content = 1;
  92. }
  93. else if (!infilename || !entrynumber || !outfilename) {
  94. PrintUsage();
  95. return 1;
  96. }
  97. //-------------------------------------------
  98. // convert entrynumber string into short
  99. //-------------------------------------------
  100. if (!show_content) {
  101. extract_idx = atoi(entrynumber);
  102. if (extract_idx < 0) {
  103. fprintf(stderr, "ERROR: negative entry numbers are not valid (%s)\n", entrynumber);
  104. return 1;
  105. }
  106. }
  107. if (!(fp = fopen(infilename, "rb"))) {
  108. fprintf(stderr, "ERROR: cannot open input file %s\n", infilename);
  109. return 1;
  110. }
  111. fseek(fp,0,SEEK_END);
  112. insize = ftell(fp);
  113. rewind(fp);
  114. // treatment of PC header ...
  115. insize -= 88;
  116. fseek(fp,86,SEEK_SET);
  117. if (!(src = (unsigned char*)malloc(insize))) {
  118. fprintf(stderr, "ERROR: cannot allocate buffer\n");
  119. fclose(fp);
  120. return 1;
  121. }
  122. if ((long)fread(src, 1, insize, fp) != insize) {
  123. fprintf(stderr, "ERROR: cannot read %ld bytes from %s\n",insize,infilename);
  124. fclose(fp);
  125. free(src);
  126. return 1;
  127. }
  128. fclose(fp);
  129. if (!IsTTArchive(src+2)) {
  130. fprintf(stderr, "ERROR: %s is not a valid archive\n",infilename);
  131. free(src);
  132. return 1;
  133. }
  134. nr_entries = GetNrEntries(src+2);
  135. if (show_content) {
  136. printf("Archive: %s\n",infilename);
  137. printf("Entries: %d\n",nr_entries);
  138. for (i=0;i<nr_entries;i++) {
  139. TTAEntry* entry = GetEntryInfo(src+2,i);
  140. unsigned char* data = GetEntryStart(src+2,entry);
  141. PackedHeader* ch = (PackedHeader*)data;
  142. unsigned short size = GetEntrySize(entry);
  143. if (ch->magic1 != MAGIC_CHAR1 || ch->magic2 != MAGIC_CHAR2) {
  144. origsize = size;
  145. }
  146. else {
  147. origsize = ch->origsize_lo | (ch->origsize_hi << 8);
  148. }
  149. printf("Entry[%02d]: archive_size=%05u orig_size=%05u\n",i,size,origsize);
  150. }
  151. free(src);
  152. return 0;
  153. }
  154. if (nr_entries <= extract_idx) {
  155. fprintf(stderr, "ERROR: entry number (%d) too large (nr_entries=%d)\n",extract_idx,nr_entries);
  156. free(src);
  157. return 1;
  158. }
  159. if (!(fp = fopen(outfilename, "wb"))) {
  160. fprintf(stderr, "ERROR: cannot open output file %s\n", outfilename);
  161. return 1;
  162. }
  163. {
  164. TTAEntry* entry = GetEntryInfo(src+2,extract_idx);
  165. unsigned char* data = GetEntryStart(src+2,entry);
  166. PackedHeader* ch = (PackedHeader*)data;
  167. unsigned char* dest;
  168. int result;
  169. if (ch->magic1 != MAGIC_CHAR1 || ch->magic2 != MAGIC_CHAR2) {
  170. // handle uncompressed entry
  171. printf("processing uncompressed entry %d ...\n",extract_idx);
  172. origsize = GetEntrySize(entry);
  173. if (fwrite(data,1,origsize,fp) != origsize) {
  174. fprintf(stderr,"ERROR: cannot write uncompressed entry to file\n");
  175. free(src);
  176. fclose(fp);
  177. return 1;
  178. }
  179. }
  180. else {
  181. // handle a compressed entry
  182. printf("processing compressed entry %d ...\n",extract_idx);
  183. origsize = ch->origsize_lo | (ch->origsize_hi << 8);
  184. if (!(dest = (unsigned char*)malloc(origsize))) {
  185. fprintf(stderr,"ERROR: cannot allocate %d bytes for output buffer\n",origsize);
  186. free(src);
  187. fclose(fp);
  188. return 1;
  189. }
  190. result=UnPack(data,dest);
  191. if (result) {
  192. fprintf(stderr,"ERROR: cannot decompress (code %03d)\n",result);
  193. free(src);
  194. free(dest);
  195. fclose(fp);
  196. return 1;
  197. }
  198. if (fwrite(dest,1,origsize,fp) != origsize) {
  199. fprintf(stderr,"ERROR: cannot decompress (code %03d)\n",result);
  200. free(src);
  201. free(dest);
  202. fclose(fp);
  203. return 1;
  204. }
  205. free(dest);
  206. }
  207. }
  208. printf("%d bytes written to %s\n",origsize,outfilename);
  209. free(src);
  210. fclose(fp);
  211. return 0;
  212. }
  213. //#############################################################################
  214. //###################### NO MORE FAKES BEYOND THIS LINE #######################
  215. //#############################################################################
  216. //
  217. //=============================================================================
  218. // Revision History
  219. //=============================================================================
  220. //
  221. // Revision 1.3 2009/01/25 Lionel Debroux
  222. // Changes by Romain Liévin and/or me for 64-bit compatibility.
  223. // Adapt to new version display (revtools.h).
  224. //
  225. // Revision 1.2 2002/02/07 09:49:38 tnussb
  226. // all local includes changed, because header files are now located in pctools folder
  227. //
  228. // Revision 1.1 2002/02/07 09:12:12 tnussb
  229. // initial version
  230. //
  231. //
  232. //