ttpack.c 72 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225
  1. /******************************************************************************
  2. *
  3. * project name: TI-68k Developer Utilities
  4. * file name: ttpack.c
  5. * initial date: 14/08/2000
  6. * authors: albert@cs.tut.fi
  7. * thomas.nussbaumer@gmx.net
  8. * description: packing program
  9. *
  10. * -----------------------------------------------------------------------------
  11. *
  12. * Packing program using the PuCrunch algorithm.
  13. * Based on code from Pasi 'Albert' Ojala, albert@cs.tut.fi
  14. * Heavily reduced to fit to the needs by thomas.nussbaumer@gmx.net
  15. * Pucrunch 1997-2005 by Pasi 'Albert' Ojala, a1bert@iki.fi
  16. * See http://www.cs.tut.fi/~albert/Dev/pucrunch/ for details on the used algorithm
  17. * Pucrunch is under GNU LGPL:
  18. * See http://creativecommons.org/licenses/LGPL/2.1/ or
  19. * http://www.gnu.org/copyleft/lesser.html
  20. *
  21. *
  22. * The decompression code is distributed under the
  23. * WXWindows Library Licence:
  24. * See http://www.wxwidgets.org/licence3.txt
  25. *
  26. * In short: binary version of the decompression code can
  27. * accompany the compressed data or be used in decompression
  28. * programs.
  29. ******************************************************************************/
  30. #ifndef __TTPACK__
  31. #define __TTPACK__
  32. // if EMBEDDED_USE is defined, than we use this sourcefile from within another
  33. // sourcefile
  34. #ifndef EMBEDDED_USE
  35. #include <stdio.h>
  36. #include <stdlib.h>
  37. #include <string.h>
  38. #include <math.h>
  39. #include <ctype.h>
  40. #include <time.h>
  41. #include "tt.h" // generic defines
  42. #include "ttversion.h" // TI-68k Developer Utilities version info
  43. #include "revtools.h" // used for id displaying
  44. #include "packhead.h" // compressed header definition
  45. #ifdef FILE_REVISION
  46. #undef FILE_REVISION
  47. #endif
  48. #define FILE_REVISION "1.9"
  49. //=============================================================================
  50. // outputs usage information of this tool
  51. //=============================================================================
  52. void PrintUsage() {
  53. PRINT_ID("TTPack");
  54. fprintf(USAGE_OUT, "Usage: ttpack [-<flags>] <infile> <outfile>\n" \
  55. " -quiet don't output standard messages (unsets v)\n"\
  56. " -hti treat input as hex textinput\n" \
  57. " -hto generate hex textoutput\n" \
  58. " -fdelta use delta-lz77 -- shortens some files\n" \
  59. " e<val> force escape bits\n" \
  60. " r<val> restrict lz search range\n" \
  61. " n no RLE/LZ length optimization\n" \
  62. " s full statistics\n" \
  63. " v verbose (unsets -quiet)\n" \
  64. " p<val> force extralzposbits\n" \
  65. " m<val> max len 5..7 (2*2^5..2*2^7)\n");
  66. }
  67. #endif
  68. #define FIXF_MACHMASK 0xff
  69. #define FIXF_WRAP 256
  70. #define FIXF_DLZ 512
  71. #define F_VERBOSE (1<<0)
  72. #define F_STATS (1<<1)
  73. #define F_AUTO (1<<2)
  74. #define F_NOOPT (1<<3)
  75. #define F_AUTOEX (1<<4)
  76. #define F_TEXTINPUT (1<<5)
  77. #define F_TEXTOUTPUT (1<<6)
  78. #define F_NORLE (1<<9)
  79. #define F_ERROR (1<<15)
  80. #ifndef min
  81. #define min(a,b) ((a<b)?(a):(b))
  82. #endif
  83. #define LRANGE (((2<<maxGamma)-3)*256) /* 0..125, 126 -> 1..127 */
  84. #define MAXLZLEN (2<<maxGamma)
  85. #define MAXRLELEN (((2<<maxGamma)-2)*256) /* 0..126 -> 1..127 */
  86. #define DEFAULT_LZLEN LRANGE
  87. unsigned short *rle, *elr, *lzlen, *lzpos;
  88. unsigned short *lzlen2, *lzpos2;
  89. int *length, inlen;
  90. unsigned char *indata, *mode, *newesc;
  91. unsigned short *backSkip;
  92. enum MODE {
  93. LITERAL = 0,
  94. LZ77 = 1,
  95. RLE = 2,
  96. DLZ = 3,
  97. MMARK = 4
  98. };
  99. int lzopt = 0;
  100. int maxGamma = 7;
  101. int reservedBytes = 2;
  102. int escBits = 2;
  103. int escMask = 0xc0;
  104. int extraLZPosBits = 0;
  105. int rleUsed = 31;
  106. unsigned char rleLen[256];
  107. int lenValue[256];
  108. int lrange, maxlzlen, maxrlelen;
  109. int gainedEscaped = 0;
  110. int gainedRle = 0, gainedSRle = 0, gainedLRle = 0;
  111. int gainedLz = 0, gainedRlecode = 0;
  112. int gainedDLz = 0, timesDLz = 0;
  113. int timesEscaped = 0, timesNormal = 0;
  114. int timesRle = 0, timesSRle = 0, timesLRle = 0;
  115. int timesLz = 0;
  116. int lenStat[8][4];
  117. unsigned char rleValues[32] = {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  118. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
  119. int rleHist[256];
  120. #define OUT_SIZE 65536
  121. unsigned char outBuffer[OUT_SIZE];
  122. int outPointer = 0;
  123. int bitMask = 0x80;
  124. int quiet = 0;
  125. void TTPackInit(void) {
  126. int i;
  127. rleValues[0] = 1;
  128. for (i=1;i<32;i++) rleValues[i] = 0;
  129. for (i=0;i<256;i++) {
  130. rleLen[i] = 0;
  131. lenValue[i] = 0;
  132. rleHist[i] = 0;
  133. }
  134. for (i=0;i<OUT_SIZE;i++) outBuffer[i] = 0;
  135. lrange = 0, maxlzlen = 0, maxrlelen = 0;
  136. gainedEscaped = 0;
  137. gainedRle = 0, gainedSRle = 0, gainedLRle = 0;
  138. gainedLz = 0, gainedRlecode = 0;
  139. gainedDLz = 0, timesDLz = 0;
  140. timesEscaped = 0, timesNormal = 0;
  141. timesRle = 0, timesSRle = 0, timesLRle = 0;
  142. timesLz = 0;
  143. lrange = 0;
  144. maxlzlen = 0;
  145. maxrlelen = 0;
  146. outPointer = 0;
  147. bitMask = 0x80;
  148. lzopt = 0;
  149. maxGamma = 7;
  150. reservedBytes = 2;
  151. escBits = 2;
  152. escMask = 0xc0;
  153. extraLZPosBits = 0;
  154. rleUsed = 31;
  155. rle = NULL;
  156. elr = NULL;
  157. lzlen = NULL;
  158. lzpos = NULL;
  159. lzlen2 = NULL;
  160. lzpos2 = NULL;
  161. length = NULL;
  162. inlen = 0;
  163. indata = NULL;
  164. mode = NULL;
  165. newesc = NULL;
  166. backSkip = NULL;
  167. }
  168. //=============================================================================
  169. // the packing code
  170. //=============================================================================
  171. int SavePack(int flags,int type, unsigned char *data, int size, char *target,
  172. int start, int escape, unsigned char *rleValues,
  173. int endAddr, int extraLZPosBits,int memStart, int memEnd)
  174. {
  175. FILE *fp = NULL;
  176. int i;
  177. if (!data) return 10;
  178. if (!target) fp = stdout;
  179. if ((type & FIXF_MACHMASK) == 0) {
  180. /* Save without decompressor */
  181. if (fp || (fp = fopen(target, "wb"))) {
  182. PackedHeader cth;
  183. RLEEntries re;
  184. cth.origsize_lo = inlen & 0xff;
  185. cth.origsize_hi = (inlen >> 8);
  186. cth.magic1 = MAGIC_CHAR1;
  187. cth.magic2 = MAGIC_CHAR2;
  188. cth.compsize_lo = (size + rleUsed + sizeof(PackedHeader)) & 0xff;
  189. cth.compsize_hi = (size + rleUsed + sizeof(PackedHeader)) >> 8;
  190. cth.esc1 = (escape >> (8-escBits));
  191. cth.notused3 = 0; // just to make sure it has a defined value
  192. cth.notused4 = 0; // just to make sure it has a defined value
  193. cth.esc2 = escBits;
  194. cth.gamma1 = maxGamma + 1;
  195. cth.gamma2 = (1 << maxGamma);
  196. cth.extralz = extraLZPosBits;
  197. cth.notused1 = 0; // just to make sure it has a defined value
  198. cth.notused2 = 0; // just to make sure it has a defined value
  199. cth.rleentries = rleUsed;
  200. for(i=0; i<rleUsed; i++) re.value[i] = rleValues[i+1];
  201. if (flags & F_TEXTOUTPUT) {
  202. unsigned int loop;
  203. unsigned int written = 0;
  204. for (i=0;i<(int)sizeof(PackedHeader);i++,written++) {
  205. fprintf(fp,"0x%02x,",*(((unsigned char*)&cth)+i));
  206. if ((!(written % DEFAULT_ITEMS_PER_LINE)) && written) fputc('\n',fp);
  207. }
  208. for (i=0;i<cth.rleentries;i++,written++) {
  209. fprintf(fp,"0x%02x,",re.value[i]);
  210. if (!(written % DEFAULT_ITEMS_PER_LINE)) fputc('\n',fp);
  211. }
  212. for (loop=0;loop < (unsigned int)size;loop++,written++) {
  213. if (loop < (unsigned int)size - 1) fprintf(fp,"0x%02x,",data[loop]);
  214. else fprintf(fp,"0x%02x",data[loop]);
  215. if (!(written % DEFAULT_ITEMS_PER_LINE)) fputc('\n',fp);
  216. }
  217. }
  218. else {
  219. fwrite(&cth, 1, sizeof(PackedHeader), fp); // write header
  220. fwrite(&re, 1, cth.rleentries, fp); // write rle values
  221. fwrite(data, size, 1, fp); // write compressed data
  222. if(fp != stdout) fclose(fp);
  223. }
  224. return 0;
  225. }
  226. fprintf(stderr, "ERROR: Could not open %s for writing\n", target);
  227. return 10;
  228. }
  229. fprintf(stderr, "FATAL: invalid type!!\n");
  230. return 10;
  231. }
  232. //=============================================================================
  233. //
  234. //=============================================================================
  235. void FlushBits(void) {
  236. if (bitMask != 0x80) outPointer++;
  237. }
  238. //=============================================================================
  239. //
  240. //=============================================================================
  241. void PutBit(int bit) {
  242. if (bit && outPointer < OUT_SIZE) outBuffer[outPointer] |= bitMask;
  243. bitMask >>= 1;
  244. if (!bitMask) {
  245. bitMask = 0x80;
  246. outPointer++;
  247. }
  248. }
  249. //=============================================================================
  250. //
  251. //=============================================================================
  252. void PutValue(int value) {
  253. int bits = 0, count = 0;
  254. while (value>1) {
  255. bits = (bits<<1) | (value & 1); /* is reversed compared to value */
  256. value >>= 1;
  257. count++;
  258. PutBit(1);
  259. }
  260. if (count<maxGamma) PutBit(0);
  261. while (count--) {
  262. PutBit((bits & 1)); /* output is reversed again -> same as value */
  263. bits >>= 1;
  264. }
  265. }
  266. //--------------------------------------------
  267. // why not initializing value lenValue[0] ????
  268. //--------------------------------------------
  269. //=============================================================================
  270. //
  271. //=============================================================================
  272. void InitValueLen() {
  273. int i;
  274. // could be heavily optimized, but isn't necessary
  275. for (i=1; i<256; i++) {
  276. int count = 0;
  277. if (i<2) count = 0; /* 1 */
  278. else if (i<4) count = 1; /* 2-3 */
  279. else if (i<8) count = 2; /* 4-7 */
  280. else if (i<16) count = 3; /* 8-15 */
  281. else if (i<32) count = 4; /* 16-31 */
  282. else if (i<64) count = 5; /* 32-63 */
  283. else if (i<128) count = 6; /* 64-127 */
  284. else if (i<256) count = 7; /* 128-255 */
  285. lenValue[i] = 2*count;
  286. if (count<maxGamma) lenValue[i]++;
  287. }
  288. }
  289. #define LenValue(a) (lenValue[a])
  290. //=============================================================================
  291. //
  292. //=============================================================================
  293. void PutNBits(int byte, int bits) {
  294. while (bits--)
  295. PutBit((byte & (1<<bits)));
  296. }
  297. //=============================================================================
  298. //
  299. //=============================================================================
  300. int OutputNormal(int *esc, unsigned char *data, int newesc) {
  301. timesNormal++;
  302. if ((data[0] & escMask) == *esc) {
  303. PutNBits((*esc>>(8-escBits)), escBits); /* escBits>=0 */
  304. PutBit(0);
  305. PutBit(1);
  306. PutBit(0);
  307. *esc = newesc;
  308. PutNBits((*esc>>(8-escBits)), escBits); /* escBits>=0 */
  309. PutNBits(data[0], 8-escBits);
  310. gainedEscaped += escBits + 3;
  311. timesEscaped++;
  312. return 1;
  313. }
  314. PutNBits(data[0], 8);
  315. return 0;
  316. }
  317. //=============================================================================
  318. //
  319. //=============================================================================
  320. void OutputEof(int *esc) {
  321. /* EOF marker */
  322. PutNBits((*esc>>(8-escBits)), escBits); /* escBits>=0 */
  323. PutValue(3); /* >2 */
  324. PutValue((2<<maxGamma)-1); /* Maximum value */
  325. FlushBits();
  326. }
  327. //=============================================================================
  328. //
  329. //=============================================================================
  330. void PutRleByte(int data) {
  331. int index;
  332. for (index = 1; index < 32; index++) {
  333. if (data == rleValues[index]) {
  334. if (index==1) lenStat[0][3]++;
  335. else if (index<=3) lenStat[1][3]++;
  336. else if (index<=7) lenStat[2][3]++;
  337. else if (index<=15) lenStat[3][3]++;
  338. else if (index<=31) lenStat[4][3]++;
  339. gainedRlecode += 8 - LenValue(index);
  340. PutValue(index);
  341. return;
  342. }
  343. }
  344. PutValue(32 + (data>>3));
  345. gainedRlecode -= LenValue(32+(data>>3)) + 3;
  346. PutNBits(data, 3);
  347. lenStat[5][3]++;
  348. }
  349. //=============================================================================
  350. //
  351. //=============================================================================
  352. void InitRleLen() {
  353. int i;
  354. for (i=0; i<256; i++) rleLen[i] = LenValue(32 + 0) + 3;
  355. for (i=1; i<32; i++) rleLen[rleValues[i]] = LenValue(i);
  356. }
  357. #define LenRleByte(d) (rleLen[d])
  358. //=============================================================================
  359. //
  360. //=============================================================================
  361. int LenRle(int len, int data) {
  362. int out = 0;
  363. do {
  364. if (len == 1) {
  365. out += escBits + 3 + 8;
  366. len = 0;
  367. }
  368. else if (len <= (1<<maxGamma)) {
  369. out += escBits + 3 + LenValue(len-1) + LenRleByte(data);
  370. len = 0;
  371. }
  372. else {
  373. int tmp = min(len, maxrlelen);
  374. out += escBits + 3 + maxGamma + 8 +
  375. LenValue(((tmp-1)>>8)+1) + LenRleByte(data);
  376. len -= tmp;
  377. }
  378. } while (len);
  379. return out;
  380. }
  381. //=============================================================================
  382. //
  383. //=============================================================================
  384. int OutputRle(int *esc, unsigned char *data, int rlelen) {
  385. int len = rlelen, tmp;
  386. while (len) {
  387. if (len >= 2 && len <= (1<<maxGamma)) {
  388. /* Short RLE */
  389. if (len==2) lenStat[0][2]++;
  390. else if (len<=4) lenStat[1][2]++;
  391. else if (len<=8) lenStat[2][2]++;
  392. else if (len<=16) lenStat[3][2]++;
  393. else if (len<=32) lenStat[4][2]++;
  394. else if (len<=64) lenStat[5][2]++;
  395. else if (len<=128) lenStat[6][2]++;
  396. else if (len<=256) lenStat[6][2]++;
  397. PutNBits((*esc>>(8-escBits)), escBits); /* escBits>=0 */
  398. PutBit(0);
  399. PutBit(1);
  400. PutBit(1);
  401. PutValue(len-1);
  402. PutRleByte(*data);
  403. tmp = 8*len -escBits -3 -LenValue(len-1) -LenRleByte(*data);
  404. gainedRle += tmp;
  405. gainedSRle += tmp;
  406. timesRle++;
  407. timesSRle++;
  408. return 0;
  409. }
  410. if (len<3) {
  411. while (len--)
  412. OutputNormal(esc, data, *esc);
  413. return 0;
  414. }
  415. if (len <= maxrlelen) {
  416. /* Run-length encoding */
  417. PutNBits((*esc>>(8-escBits)), escBits); /* escBits>=0 */
  418. PutBit(0);
  419. PutBit(1);
  420. PutBit(1);
  421. PutValue((1<<maxGamma) + (((len-1)&0xff)>>(8-maxGamma)));
  422. PutNBits((len-1), 8-maxGamma);
  423. PutValue(((len-1)>>8) + 1);
  424. PutRleByte(*data);
  425. tmp = 8*len -escBits -3 -maxGamma -8 -LenValue(((len-1)>>8)+1)
  426. -LenRleByte(*data);
  427. gainedRle += tmp;
  428. gainedLRle += tmp;
  429. timesRle++;
  430. timesLRle++;
  431. return 0;
  432. }
  433. /* Run-length encoding */
  434. PutNBits((*esc>>(8-escBits)), escBits); /* escBits>=0 */
  435. PutBit(0);
  436. PutBit(1);
  437. PutBit(1);
  438. PutValue((1<<maxGamma) + (((maxrlelen-1)&0xff)>>(8-maxGamma)));
  439. PutNBits((maxrlelen-1) & 0xff, 8-maxGamma);
  440. PutValue(((maxrlelen-1)>>8)+1);
  441. PutRleByte(*data);
  442. tmp = 8*maxrlelen -escBits -3 -maxGamma -8
  443. -LenValue(((maxrlelen-1)>>8)+1) -LenRleByte(*data);
  444. gainedRle += tmp;
  445. gainedLRle += tmp;
  446. timesRle++;
  447. timesLRle++;
  448. len -= maxrlelen;
  449. data += maxrlelen;
  450. }
  451. return 0;
  452. }
  453. //=============================================================================
  454. //
  455. //=============================================================================
  456. int LenLz(int lzlen, int lzpos) {
  457. if (lzlen==2) {
  458. if (lzpos <= 256) return escBits + 2 + 8;
  459. else return 100000;
  460. }
  461. return escBits + 8 + extraLZPosBits +
  462. LenValue(((lzpos-1)>>(8+extraLZPosBits))+1) +
  463. LenValue(lzlen-1);
  464. }
  465. //=============================================================================
  466. //
  467. //=============================================================================
  468. int OutputLz(int *esc, int lzlen, int lzpos, char *data, int curpos) {
  469. if (lzlen==2) lenStat[0][1]++;
  470. else if (lzlen<=4) lenStat[1][1]++;
  471. else if (lzlen<=8) lenStat[2][1]++;
  472. else if (lzlen<=16) lenStat[3][1]++;
  473. else if (lzlen<=32) lenStat[4][1]++;
  474. else if (lzlen<=64) lenStat[5][1]++;
  475. else if (lzlen<=128) lenStat[6][1]++;
  476. else if (lzlen<=256) lenStat[7][1]++;
  477. if (lzlen >= 2 && lzlen <= maxlzlen) {
  478. int tmp;
  479. PutNBits((*esc>>(8-escBits)), escBits); /* escBits>=0 */
  480. tmp = ((lzpos-1)>>(8+extraLZPosBits))+2;
  481. if (tmp==2) lenStat[0][0]++;
  482. else if (tmp<=4) lenStat[1][0]++;
  483. else if (tmp<=8) lenStat[2][0]++;
  484. else if (tmp<=16) lenStat[3][0]++;
  485. else if (tmp<=32) lenStat[4][0]++;
  486. else if (tmp<=64) lenStat[5][0]++;
  487. else if (tmp<=128) lenStat[6][0]++;
  488. else if (tmp<=256) lenStat[6][0]++;
  489. if (lzlen==2) {
  490. PutValue(lzlen-1);
  491. PutBit(0);
  492. if (lzpos > 256) fprintf(stderr,"ERROR at %d: lzpos too long (%d) for lzlen==2\n",curpos, lzpos);
  493. }
  494. else {
  495. PutValue(lzlen-1);
  496. PutValue( ((lzpos-1) >> (8+extraLZPosBits)) +1);
  497. PutNBits( ((lzpos-1) >> 8), extraLZPosBits);
  498. }
  499. PutNBits(((lzpos-1) & 0xff) ^ 0xff, 8);
  500. gainedLz += 8*lzlen -LenLz(lzlen, lzpos);
  501. timesLz++;
  502. return 3;
  503. }
  504. fprintf(stderr, "ERROR: lzlen too short/long (%d)\n", lzlen);
  505. return lzlen;
  506. }
  507. /* Non-recursive version */
  508. /* NOTE! IMPORTANT! the "length" array length must be inlen+1 */
  509. //=============================================================================
  510. //
  511. //=============================================================================
  512. int OptimizeLength(int optimize) {
  513. int i;
  514. length[inlen] = 0; /* one off the end, our 'target' */
  515. for (i=inlen-1; i>=0; i--) {
  516. int r1 = 8 + length[i+1], r2, r3;
  517. if (!lzlen[i] && !rle[i] && (!lzlen2 || !lzlen2[i])) {
  518. length[i] = r1;
  519. mode[i] = LITERAL;
  520. continue;
  521. }
  522. /* If rle>maxlzlen, skip to the start of the rle-maxlzlen.. */
  523. if (rle[i] > maxlzlen && elr[i] > 1) {
  524. int z = elr[i];
  525. i -= elr[i];
  526. r2 = LenRle(rle[i], indata[i]) + length[i+ rle[i]];
  527. if (optimize) {
  528. int ii, mini = rle[i], minv = r2;
  529. int bot = rle[i] - (1<<maxGamma);
  530. if (bot < 2)
  531. bot = 2;
  532. for (ii=mini-1; ii>=bot; ii--) {
  533. int v = LenRle(ii, indata[i]) + length[i + ii];
  534. if (v < minv) {
  535. minv = v;
  536. mini = ii;
  537. }
  538. }
  539. if (minv != r2) {
  540. lzopt += r2 - minv;
  541. rle[i] = mini;
  542. r2 = minv;
  543. }
  544. }
  545. length[i] = r2;
  546. mode[i] = RLE;
  547. for (; z>=0; z--) {
  548. length[i+z] = r2;
  549. mode[i+z] = RLE;
  550. }
  551. continue;
  552. }
  553. r3 = r2 = r1 + 1000; /* r3 >= r2 > r1 */
  554. if (rle[i]) {
  555. r2 = LenRle(rle[i], indata[i]) + length[i+ rle[i]];
  556. if (optimize) {
  557. int ii, mini = rle[i], minv = r2;
  558. /* Check only the original length and all shorter
  559. lengths that are power of two.
  560. Does not really miss many 'minimums' this way,
  561. at least not globally..
  562. Makes the assumption that the Elias Gamma Code is
  563. used, i.e. values of the form 2^n are 'optimal' */
  564. ii = 2;
  565. while (rle[i] > ii) {
  566. int v = LenRle(ii, indata[i]) + length[i + ii];
  567. if (v < minv) {
  568. minv = v;
  569. mini = ii;
  570. }
  571. ii <<= 1;
  572. }
  573. if (minv != r2) {
  574. lzopt += r2 - minv;
  575. rle[i] = mini;
  576. r2 = minv;
  577. }
  578. }
  579. }
  580. if (lzlen[i]) {
  581. r3 = LenLz(lzlen[i], lzpos[i]) + length[i + lzlen[i]];
  582. if (optimize && lzlen[i]>2) {
  583. int ii, mini = lzlen[i], minv = r3;
  584. int topLen = LenLz(lzlen[i], lzpos[i])
  585. - LenValue(lzlen[i]-1);
  586. /* Check only the original length and all shorter
  587. lengths that are power of two.
  588. Does not really miss many 'minimums' this way,
  589. at least not globally..
  590. Makes the assumption that the Elias Gamma Code is
  591. used, i.e. values of the form 2^n are 'optimal' */
  592. ii = 4;
  593. while (lzlen[i] > ii) {
  594. int v = topLen + LenValue(ii-1) + length[i + ii];
  595. if (v < minv) {
  596. minv = v;
  597. mini = ii;
  598. }
  599. ii <<= 1;
  600. }
  601. /*
  602. Note:
  603. 2-byte optimization checks are no longer done
  604. with the rest, because the equation gives too long
  605. code lengths for 2-byte matches if extraLzPosBits>0.
  606. */
  607. /* Two-byte rescan/check */
  608. if (backSkip[i] && backSkip[i] <= 256) {
  609. /* There are previous occurrances (near enough) */
  610. int v = LenLz(2, (int)backSkip[i]) + length[i + 2];
  611. if (v < minv) {
  612. minv = v;
  613. mini = 2;
  614. lzlen[i] = mini;
  615. r3 = minv;
  616. lzpos[i] = (int)backSkip[i];
  617. }
  618. }
  619. if (minv != r3 && minv < r2) {
  620. lzopt += r3 - minv;
  621. lzlen[i] = mini;
  622. r3 = minv;
  623. }
  624. }
  625. }
  626. if (r2 <= r1) {
  627. if (r2 <= r3) {
  628. length[i] = r2;
  629. mode[i] = RLE;
  630. }
  631. else {
  632. length[i] = r3;
  633. mode[i] = LZ77;
  634. }
  635. }
  636. else {
  637. if (r3 <= r1) {
  638. length[i] = r3;
  639. mode[i] = LZ77;
  640. }
  641. else {
  642. length[i] = r1;
  643. mode[i] = LITERAL;
  644. }
  645. }
  646. if (lzlen2 && lzlen2[i] > 3) {
  647. r3 = escBits + 2*maxGamma + 16 + LenValue(lzlen2[i]-1) + length[i + lzlen2[i]];
  648. //r3 = LenDLz(lzlen2[i], lzpos2[i]) + length[i + lzlen2[i]];
  649. if (r3 < length[i]) {
  650. length[i] = r3;
  651. mode[i] = DLZ;
  652. }
  653. }
  654. }
  655. return length[0];
  656. }
  657. /*
  658. The algorithm in the OptimizeEscape() works as follows:
  659. 1) Only unpacked bytes are processed, they are marked
  660. with MMARK. We proceed from the end to the beginning.
  661. Variable A (old/new length) is updated.
  662. 2) At each unpacked byte, one and only one possible
  663. escape matches. A new escape code must be selected
  664. for this case. The optimal selection is the one which
  665. provides the shortest number of escapes to the end
  666. of the file,
  667. i.e. A[esc] = 1+min(A[0], A[1], .. A[states-1]).
  668. For other states A[esc] = A[esc];
  669. If we change escape in this byte, the new escape is
  670. the one with the smallest value in A.
  671. 3) The starting escape is selected from the possibilities
  672. and mode 0 is restored to all mode 3 locations.
  673. */
  674. //=============================================================================
  675. //
  676. //=============================================================================
  677. int OptimizeEscape(int *startEscape, int *nonNormal) {
  678. int i, j, states = (1<<escBits);
  679. long minp = 0, minv = 0, other = 0;
  680. long a[256]; /* needs int/long */
  681. long b[256]; /* Remembers the # of escaped for each */
  682. int esc8 = 8-escBits;
  683. for (i=0; i<256; i++) b[i] = a[i] = -1;
  684. if (states>256) {
  685. fprintf(stderr, "Escape optimize: only 256 states (%d)!\n",states);
  686. return 0;
  687. }
  688. /* Mark those bytes that are actually outputted */
  689. for (i=0; i<inlen; ) {
  690. switch (mode[i]) {
  691. case DLZ:
  692. other++;
  693. i += lzlen2[i];
  694. break;
  695. case LZ77:
  696. other++;
  697. i += lzlen[i];
  698. break;
  699. case RLE:
  700. other++;
  701. i += rle[i];
  702. break;
  703. /*case LITERAL:*/
  704. default:
  705. mode[i++] = MMARK; /* mark it used so we can identify it */
  706. break;
  707. }
  708. }
  709. for (i=inlen-1; i>=0; i--) {
  710. /* Using a table to skip non-normal bytes does not help.. */
  711. if (mode[i] == MMARK) {
  712. int k = (indata[i] >> esc8);
  713. /* Change the tag values back to normal */
  714. mode[i] = LITERAL;
  715. /*
  716. k are the matching bytes,
  717. minv is the minimum value,
  718. minp is the minimum index
  719. */
  720. newesc[i] = (minp << esc8);
  721. a[k] = minv + 1;
  722. b[k] = b[minp] + 1;
  723. if (k==minp) {
  724. /* Minimum changed -> need to find a new minimum */
  725. /* a[k] may still be the minimum */
  726. minv++;
  727. for (k=states-1; k>=0; k--) {
  728. if (a[k] < minv) {
  729. minv = a[k];
  730. minp = k;
  731. /*
  732. There may be others, but the first one that
  733. is smaller than the old minimum is equal to
  734. any other new minimum.
  735. */
  736. break;
  737. }
  738. }
  739. }
  740. }
  741. }
  742. /* Select the best value for the initial escape */
  743. if (startEscape) {
  744. i = inlen; /* make it big enough */
  745. for (j=states-1; j>=0; j--) {
  746. if (a[j] <= i) {
  747. *startEscape = (j << esc8);
  748. i = a[j];
  749. }
  750. }
  751. }
  752. if (nonNormal)
  753. *nonNormal = other;
  754. return b[startEscape ? (*startEscape>>esc8) : 0];
  755. }
  756. //=============================================================================
  757. // Initialize the RLE byte code table according to all RLE's found so far O(n)
  758. //=============================================================================
  759. void InitRle(int flags) {
  760. int p, mr, mv, i;
  761. for (i=1; i<32; i++) {
  762. mr = -1;
  763. mv = 0;
  764. for (p=0; p<256; p++) {
  765. if (rleHist[p] > mv) {
  766. mv = rleHist[p];
  767. mr = p;
  768. }
  769. }
  770. if (mv>0) {
  771. rleValues[i] = mr;
  772. rleHist[mr] = -1;
  773. } else
  774. break;
  775. }
  776. InitRleLen();
  777. }
  778. //=============================================================================
  779. // Initialize the RLE byte code table according to RLE's actually used O(n)
  780. //=============================================================================
  781. void OptimizeRle(int flags) {
  782. int p, mr, mv, i;
  783. if ((flags & F_NORLE)) {
  784. rleUsed = 0;
  785. return;
  786. }
  787. if (flags & F_STATS) fprintf(stderr, "RLE Byte Code Re-Tune, RLE Ranks:\n");
  788. for (p=0; p<256; p++) rleHist[p] = 0;
  789. for (p=0; p<inlen; ) {
  790. switch (mode[p]) {
  791. case DLZ:
  792. p += lzlen2[p];
  793. break;
  794. case LZ77:
  795. p += lzlen[p];
  796. break;
  797. case RLE:
  798. rleHist[indata[p]]++;
  799. p += rle[p];
  800. break;
  801. default:
  802. p++;
  803. break;
  804. }
  805. }
  806. for (i=1; i<32; i++) {
  807. mr = -1;
  808. mv = 0;
  809. for (p=0; p<256; p++) {
  810. if (rleHist[p] > mv) {
  811. mv = rleHist[p];
  812. mr = p;
  813. }
  814. }
  815. if (mv>0) {
  816. rleValues[i] = mr;
  817. if (flags & F_STATS) {
  818. fprintf(stderr, " %2d.0x%02x %-3d ", i, mr, mv);
  819. if (!((i - 1) % 6)) fprintf(stderr, "\n");
  820. }
  821. rleHist[mr] = -1;
  822. }
  823. else {
  824. break;
  825. }
  826. }
  827. rleUsed = i-1;
  828. if (flags & F_STATS)
  829. if (((i - 1) % 6)!=1) fprintf(stderr, "\n");
  830. InitRleLen();
  831. }
  832. //=============================================================================
  833. //
  834. //=============================================================================
  835. int PackLz77(int lzsz, int flags, int *startEscape,int endAddr, int memEnd, int type)
  836. {
  837. int i, j, outlen, p, headerSize;
  838. int escape;
  839. unsigned char *hashValue;
  840. unsigned char *a;
  841. int k;
  842. unsigned short *lastPair;
  843. unsigned short err_occured = 0;
  844. int rescan = 0;
  845. if (lzsz < 0 || lzsz > lrange) {
  846. fprintf(stderr, "LZ range must be from 0 to %d (was %d). Set to %d.\n",
  847. lrange, lzsz, lrange);
  848. lzsz = lrange;
  849. }
  850. if (lzsz > 65535) {
  851. fprintf(stderr,
  852. "LZ range must be from 0 to 65535 (was %d). Set to 65535.\n",
  853. lzsz);
  854. lzsz = 65535;
  855. }
  856. if (!lzsz) fprintf(stderr, "Warning: zero LZ range. Only RLE packing used.\n");
  857. InitRleLen();
  858. length = (int *)calloc(sizeof(int), inlen + 1);
  859. mode = (unsigned char *)calloc(sizeof(unsigned char), inlen);
  860. rle = (unsigned short *)calloc(sizeof(unsigned short), inlen);
  861. elr = (unsigned short *)calloc(sizeof(unsigned short), inlen);
  862. lzlen = (unsigned short *)calloc(sizeof(unsigned short), inlen);
  863. lzpos = (unsigned short *)calloc(sizeof(unsigned short), inlen);
  864. if ((type & FIXF_DLZ)) {
  865. lzlen2 = (unsigned short *)calloc(sizeof(unsigned short), inlen);
  866. lzpos2 = (unsigned short *)calloc(sizeof(unsigned short), inlen);
  867. }
  868. else {
  869. lzlen2 = lzpos2 = NULL;
  870. }
  871. newesc = (unsigned char *)calloc(sizeof(unsigned char), inlen);
  872. backSkip = (unsigned short *)calloc(sizeof(unsigned short), inlen);
  873. hashValue = (unsigned char *)malloc(inlen);
  874. lastPair = (unsigned short *)calloc(sizeof(unsigned short), 256*256);
  875. /* error checking */
  876. if (!length || !mode || !rle || !elr || !lzlen || !lzpos || !newesc ||
  877. !lastPair || !backSkip
  878. || ((type & FIXF_DLZ) && (!lzlen2 || !lzpos2))
  879. || !hashValue)
  880. {
  881. fprintf(stderr, "ERROR: Memory allocation failed!\n");
  882. err_occured = 1;
  883. goto errorexit;
  884. }
  885. i = 0;
  886. j = 0;
  887. a = indata + inlen;
  888. for (p=inlen-1; p>=0; p--) {
  889. k = j;
  890. j = i;
  891. i = *--a; /* Only one read per position */
  892. hashValue[p] = i*3 + j*5 + k*7; /* 7.95 % */
  893. }
  894. /* Detect all RLE and LZ77 jump possibilities */
  895. for (p=0; p<inlen; p++) {
  896. if (flags & F_VERBOSE) {
  897. if (!(p & 2047)) {
  898. fprintf(stderr, "\r%d ", p);
  899. fflush(stderr); /* for SAS/C */
  900. }
  901. }
  902. /* check run-length code - must be done, LZ77 search needs it! */
  903. if (rle[p] <= 0) {
  904. unsigned char *a = indata + p;
  905. int val = *a++; /* if this were uchar, it would go to stack..*/
  906. int top = inlen - p;
  907. int rlelen = 1;
  908. /* Loop for the whole RLE */
  909. while (rlelen<top && *a++ == (unsigned char)val) rlelen++;
  910. if (rlelen>=2) {
  911. rleHist[indata[p]]++;
  912. for (i=rlelen-1; i>=0; i--) {
  913. rle[p+i] = rlelen-i;
  914. elr[p+i] = i; /* For RLE backward skipping */
  915. }
  916. }
  917. }
  918. /* check LZ77 code */
  919. if (p+rle[p]+1<inlen) {
  920. int bot = p - lzsz, maxval, maxpos, rlep = rle[p];
  921. unsigned char hashCompare = hashValue[p];
  922. /*
  923. There's always 1 equal byte, although it may
  924. not be marked as RLE.
  925. */
  926. if (rlep <= 0)
  927. rlep = 1;
  928. if (bot < 0)
  929. bot = 0;
  930. bot += (rlep-1);
  931. /*
  932. First get the shortest possible match (if any).
  933. If there is no 2-byte match, don't look further,
  934. because there can't be a longer match.
  935. */
  936. i = (int)lastPair[ (indata[p]<<8) | indata[p+1] ] -1;
  937. if (i>=0 && i>=bot) {
  938. /* Got a 2-byte match at least */
  939. maxval = 2;
  940. maxpos = p-i;
  941. /*
  942. A..AB rlep # of A's, B is something else..
  943. Search for bytes that are in p + (rlep-1), i.e.
  944. the last rle byte ('A') and the non-matching one
  945. ('B'). When found, check if the rle in the compare
  946. position (i) is long enough (i.e. the same number
  947. of A's at p and i-rlep+1).
  948. There are dramatically less matches for AB than for
  949. AA, so we get a huge speedup with this approach.
  950. We are still guaranteed to find the most recent
  951. longest match there is.
  952. */
  953. i = (int)lastPair[(indata[p+(rlep-1)]<<8) | indata[p+rlep]] -1;
  954. while (i>=bot /* && i>=rlep-1 */) { /* bot>=rlep-1, i>=bot ==> i>=rlep-1 */
  955. /* Equal number of A's ? */
  956. if (!(rlep-1) || rle[i-(rlep-1)]==rlep) { /* 'head' matches */
  957. /* rlep==1 ==> (rlep-1)==0 */
  958. /* ivanova.run: 443517 rlep==1,
  959. 709846 rle[i+1-rlep]==rlep */
  960. /*
  961. Check the hash values corresponding to the last
  962. two bytes of the currently longest match and
  963. the first new matching(?) byte. If the hash
  964. values don't match, don't bother to check the
  965. data itself.
  966. */
  967. if (
  968. hashValue[i+maxval-rlep-1] == hashCompare
  969. ) {
  970. unsigned char *a = indata + i+2; /* match */
  971. unsigned char *b = indata + p+rlep-1+2;/* curpos */
  972. int topindex = inlen-(p+rlep-1);
  973. /* the 2 first bytes ARE the same.. */
  974. j = 2;
  975. while (j < topindex && *a++==*b++)
  976. j++;
  977. if (j + rlep-1 > maxval) {
  978. int tmplen = j+rlep-1, tmppos = p-i+rlep-1;
  979. if (tmplen > maxlzlen)
  980. tmplen = maxlzlen;
  981. /* Accept only versions that really are shorter */
  982. if (tmplen*8 - LenLz(tmplen, tmppos) >
  983. maxval*8 - LenLz(maxval, maxpos)) {
  984. maxval = tmplen;
  985. maxpos = tmppos;
  986. hashCompare = hashValue[p+maxval-2];
  987. }
  988. if (maxval == maxlzlen)
  989. break;
  990. }
  991. }
  992. }
  993. if (!backSkip[i])
  994. break; /* No previous occurrances (near enough) */
  995. i -= (int)backSkip[i];
  996. }
  997. /*
  998. If there is 'A' in the previous position also,
  999. RLE-like LZ77 is possible, although rarely
  1000. shorter than real RLE.
  1001. */
  1002. if (p && rle[p-1] > maxval) {
  1003. maxval = rle[p-1] - 1;
  1004. maxpos = 1;
  1005. }
  1006. /*
  1007. Last, try to find as long as possible match
  1008. for the RLE part only.
  1009. */
  1010. if (maxval < maxlzlen && rlep > maxval) {
  1011. bot = p - lzsz;
  1012. if (bot < 0)
  1013. bot = 0;
  1014. /* Note: indata[p] == indata[p+1] */
  1015. i = (int)lastPair[indata[p]*257] -1;
  1016. while (/* i>= rlep-2 &&*/ i>=bot) {
  1017. if (elr[i] + 2 > maxval) {
  1018. maxval = min(elr[i] + 2, rlep);
  1019. maxpos = p - i + (maxval-2);
  1020. if(maxval == rlep)
  1021. break; /* Got enough */
  1022. }
  1023. i -= elr[i];
  1024. if (!backSkip[i])
  1025. break; /* No previous occurrances (near enough) */
  1026. i -= (int)backSkip[i];
  1027. }
  1028. }
  1029. if (p+maxval > inlen) {
  1030. fprintf(stderr,"Error @ %d, lzlen %d, pos %d - exceeds inlen\n",p, maxval, maxpos);
  1031. maxval = inlen - p;
  1032. }
  1033. if (maxpos<=256 || maxval > 2) {
  1034. if (maxpos < 0) fprintf(stderr, "Error @ %d, lzlen %d, pos %d\n",p, maxval, maxpos);
  1035. lzlen[p] = (maxval<maxlzlen)?maxval:maxlzlen;
  1036. lzpos[p] = maxpos;
  1037. }
  1038. }
  1039. }
  1040. /* check LZ77 code again, ROT1..255 */
  1041. if ((type & FIXF_DLZ) && p+rle[p]+1<inlen) {
  1042. int rot;
  1043. for (rot = 1; rot < 255; rot++) {
  1044. int bot = p - /*lzsz*/256, maxval, maxpos, rlep = rle[p];
  1045. unsigned char valueCompare = (indata[p+2] + rot) & 0xff;
  1046. if (rlep <= 0) rlep = 1;
  1047. if (bot < 0) bot = 0;
  1048. bot += (rlep-1);
  1049. i = (int)lastPair[ (((indata[p] + rot) & 0xff)<<8) |
  1050. ((indata[p+1] + rot) & 0xff) ] -1;
  1051. if (i>=0 && i>=bot) {
  1052. maxval = 2;
  1053. maxpos = p-i;
  1054. /*
  1055. A..AB rlep # of A's, B is something else..
  1056. Search for bytes that are in p + (rlep-1), i.e.
  1057. the last rle byte ('A') and the non-matching one
  1058. ('B'). When found, check if the rle in the compare
  1059. position (i) is long enough (i.e. the same number
  1060. of A's at p and i-rlep+1).
  1061. There are dramatically less matches for AB than for
  1062. AA, so we get a huge speedup with this approach.
  1063. We are still guaranteed to find the most recent
  1064. longest match there is.
  1065. */
  1066. i = (int)lastPair[(((indata[p+(rlep-1)] + rot) & 0xff)<<8) |
  1067. ((indata[p+rlep] + rot) & 0xff)] -1;
  1068. while (i>=bot /* && i>=rlep-1 */) { /* bot>=rlep-1, i>=bot ==> i>=rlep-1 */
  1069. /* Equal number of A's ? */
  1070. if (!(rlep-1) || rle[i-(rlep-1)]==rlep) { /* 'head' matches */
  1071. /* rlep==1 ==> (rlep-1)==0 */
  1072. /* ivanova.run: 443517 rlep==1,
  1073. 709846 rle[i+1-rlep]==rlep */
  1074. /*
  1075. Check the hash values corresponding to the last
  1076. two bytes of the currently longest match and
  1077. the first new matching(?) byte. If the hash
  1078. values don't match, don't bother to check the
  1079. data itself.
  1080. */
  1081. if (indata[i+maxval-rlep+1] == valueCompare) {
  1082. unsigned char *a = indata + i+2; /* match */
  1083. unsigned char *b = indata + p+rlep-1+2;/* curpos */
  1084. int topindex = inlen-(p+rlep-1);
  1085. /* the 2 first bytes ARE the same.. */
  1086. j = 2;
  1087. while (j < topindex && *a++==((*b++ + rot) & 0xff))
  1088. j++;
  1089. if (j + rlep-1 > maxval) {
  1090. int tmplen = j+rlep-1, tmppos = p-i+rlep-1;
  1091. if (tmplen > maxlzlen)
  1092. tmplen = maxlzlen;
  1093. /* Accept only versions that really are shorter */
  1094. if (tmplen*8 - LenLz(tmplen, tmppos) >
  1095. maxval*8 - LenLz(maxval, maxpos)) {
  1096. maxval = tmplen;
  1097. maxpos = tmppos;
  1098. valueCompare = (indata[p+maxval] + rot) & 0xff;
  1099. }
  1100. if (maxval == maxlzlen)
  1101. break;
  1102. }
  1103. }
  1104. }
  1105. if (!backSkip[i])
  1106. break; /* No previous occurrances (near enough) */
  1107. i -= (int)backSkip[i];
  1108. }
  1109. if (p+maxval > inlen) {
  1110. fprintf(stderr,"Error @ %d, lzlen %d, pos %d - exceeds inlen\n",p, maxval, maxpos);
  1111. maxval = inlen - p;
  1112. }
  1113. if (maxval > 3 && maxpos <= 256 &&
  1114. (maxval > lzlen2[p] ||
  1115. (maxval == lzlen2[p] && maxpos < lzpos2[p]))) {
  1116. if (maxpos < 0)
  1117. fprintf(stderr, "Error @ %d, lzlen %d, pos %d\n",p, maxval, maxpos);
  1118. lzlen2[p] = (maxval<maxlzlen)?maxval:maxlzlen;
  1119. lzpos2[p] = maxpos;
  1120. }
  1121. }
  1122. }
  1123. if (lzlen2[p] <= lzlen[p] || lzlen2[p] <= rle[p]) {
  1124. lzlen2[p] = lzpos2[p] = 0;
  1125. }
  1126. }
  1127. /* Update the two-byte history ('hash table') &
  1128. backSkip ('linked list') */
  1129. if (p+1<inlen) {
  1130. int index = (indata[p]<<8) | indata[p+1];
  1131. int ptr = p - (lastPair[index]-1);
  1132. if (ptr > p || ptr > 0xffff)
  1133. ptr = 0;
  1134. backSkip[p] = ptr;
  1135. lastPair[index] = p+1;
  1136. }
  1137. }
  1138. if ((flags & F_NORLE)) {
  1139. for (p=1; p<inlen; p++) {
  1140. if (rle[p-1]-1 > lzlen[p]) {
  1141. lzlen[p] = (rle[p]<maxlzlen)?rle[p]:maxlzlen;
  1142. lzpos[p] = 1;
  1143. }
  1144. }
  1145. for (p=0; p<inlen; p++) {
  1146. rle[p] = 0;
  1147. }
  1148. }
  1149. if (flags & F_VERBOSE) {
  1150. fprintf(stderr, "\rChecked: %d \n", p);
  1151. fflush(stderr);
  1152. }
  1153. /* Initialize the RLE selections */
  1154. InitRle(flags);
  1155. /* Check the normal bytes / all ratio */
  1156. if ((flags & F_AUTO)) {
  1157. int mb, mv;
  1158. if (flags & F_VERBOSE) {
  1159. fprintf(stderr, "Selecting the number of escape bits.. ");
  1160. fflush(stderr);
  1161. }
  1162. /*
  1163. Absolute maximum number of escaped bytes with
  1164. the escape optimize is 2^-n, where n is the
  1165. number of escape bits used.
  1166. This worst case happens only on equal-
  1167. distributed normal bytes (01230123..).
  1168. This is why the typical values are so much smaller.
  1169. */
  1170. mb = 0;
  1171. mv = 8*OUT_SIZE;
  1172. for (escBits=1; escBits<9; escBits++) {
  1173. int escaped, other = 0, c;
  1174. escMask = (0xff00>>escBits) & 0xff;
  1175. /* Find the optimum path for selected escape bits (no optimize) */
  1176. OptimizeLength(0);
  1177. /* Optimize the escape selections for this path & escBits */
  1178. escaped = OptimizeEscape(&escape, &other);
  1179. /* Compare value: bits lost for escaping -- bits lost for prefix */
  1180. c = (escBits+3)*escaped + other*escBits;
  1181. if (flags & F_STATS) {
  1182. fprintf(stderr, " %d:%d", escBits, c);
  1183. fflush(stderr); /* for SAS/C */
  1184. }
  1185. if (c < mv) {
  1186. mb = escBits;
  1187. mv = c;
  1188. } else {
  1189. /* minimum found */
  1190. break;
  1191. }
  1192. if (escBits==4 && (flags & F_STATS)) fprintf(stderr, "\n");
  1193. }
  1194. if (mb==1) { /* Minimum was 1, check 0 */
  1195. int escaped;
  1196. escBits = 0;
  1197. escMask = 0;
  1198. /* Find the optimum path for selected escape bits (no optimize) */
  1199. OptimizeLength(0);
  1200. /* Optimize the escape selections for this path & escBits */
  1201. escaped = OptimizeEscape(&escape, NULL);
  1202. if ((flags & F_STATS)) {
  1203. fprintf(stderr, " %d:%d", escBits, 3*escaped);
  1204. fflush(stderr); /* for SAS/C */
  1205. }
  1206. if (3*escaped < mv) {
  1207. mb = 0;
  1208. /* mv = 3*escaped; */
  1209. }
  1210. }
  1211. if ((flags & F_STATS)) fprintf(stderr, "\n");
  1212. if (flags & F_VERBOSE) fprintf(stderr, "Selected %d-bit escapes\n", mb);
  1213. escBits = mb;
  1214. escMask = (0xff00>>escBits) & 0xff;
  1215. }
  1216. if (!(flags & F_NOOPT)) {
  1217. if (flags & F_VERBOSE) {
  1218. fprintf(stderr, "Optimizing LZ77 and RLE lengths...");
  1219. fflush(stderr);
  1220. }
  1221. }
  1222. /* Find the optimum path (optimize) */
  1223. OptimizeLength((flags & F_NOOPT)?0:1);
  1224. if (flags & F_STATS) {
  1225. if (!(flags & F_NOOPT)) fprintf(stderr, " gained %d units.\n", lzopt/8);
  1226. }
  1227. else {
  1228. if (flags & F_VERBOSE) fprintf(stderr, "\n");
  1229. }
  1230. if (1 || (flags & F_AUTOEX)) {
  1231. long lzstat[5] = {0,0,0,0,0}, i, cur = 0, old = extraLZPosBits;
  1232. if (flags & F_VERBOSE) {
  1233. fprintf(stderr, "Selecting LZPOS LO length.. ");
  1234. fflush(stderr);
  1235. }
  1236. for (p=0; p<inlen; ) {
  1237. switch (mode[p]) {
  1238. case LZ77:
  1239. extraLZPosBits = 0;
  1240. lzstat[0] += LenLz(lzlen[p], lzpos[p]);
  1241. extraLZPosBits = 1;
  1242. lzstat[1] += LenLz(lzlen[p], lzpos[p]);
  1243. extraLZPosBits = 2;
  1244. lzstat[2] += LenLz(lzlen[p], lzpos[p]);
  1245. extraLZPosBits = 3;
  1246. lzstat[3] += LenLz(lzlen[p], lzpos[p]);
  1247. extraLZPosBits = 4;
  1248. lzstat[4] += LenLz(lzlen[p], lzpos[p]);
  1249. p += lzlen[p];
  1250. break;
  1251. case DLZ:
  1252. p += lzlen2[p];
  1253. break;
  1254. case RLE:
  1255. p += rle[p];
  1256. break;
  1257. default:
  1258. p++;
  1259. break;
  1260. }
  1261. }
  1262. for (i=0; i<5; i++) {
  1263. if (flags & F_STATS) fprintf(stderr, " %ld:%ld", i + 8, lzstat[i]);
  1264. if (lzstat[i] < lzstat[cur]) cur = i;
  1265. }
  1266. extraLZPosBits = (flags & F_AUTOEX)?cur:old;
  1267. if (flags & F_STATS) fprintf(stderr, "\n");
  1268. if (flags & F_VERBOSE) {
  1269. fprintf(stderr, "Selected %d-bit LZPOS LO part\n",extraLZPosBits + 8);
  1270. if (cur != old) fprintf(stderr,"Note: Using option -p%ld you may get better results.\n",cur);
  1271. }
  1272. /* Find the optimum path (optimize) */
  1273. if (extraLZPosBits != old) OptimizeLength((flags & F_NOOPT)?0:1);
  1274. }
  1275. if (1) {
  1276. long stat[4] = {0,0,0,0};
  1277. for (p=0; p<inlen; ) {
  1278. switch (mode[p]) {
  1279. case LZ77:
  1280. if ((lzpos[p] >> 8)+1 > (1<<maxGamma))
  1281. stat[3]++;
  1282. if (lzlen[p] > (1<<maxGamma))
  1283. stat[0]++;
  1284. p += lzlen[p];
  1285. break;
  1286. case RLE:
  1287. if (rle[p] > (1<<(maxGamma-1))) {
  1288. if (rle[p] <= (1<<maxGamma))
  1289. stat[1]++;
  1290. }
  1291. p += rle[p];
  1292. break;
  1293. case DLZ:
  1294. p += lzlen2[p];
  1295. break;
  1296. default:
  1297. p++;
  1298. break;
  1299. }
  1300. }
  1301. /* TODO: better formula.. */
  1302. if (maxGamma < 7 && stat[0] + stat[1] + stat[3] > 10) {
  1303. if (flags & F_VERBOSE) fprintf(stderr,"Note: Using option -m%d you may get better results.\n",maxGamma+1);
  1304. }
  1305. if (maxGamma > 5 && stat[0] + stat[1] + stat[3] < 4) {
  1306. if (flags & F_VERBOSE) fprintf(stderr,"Note: Using option -m%d you may get better results.\n",maxGamma-1);
  1307. }
  1308. }
  1309. /* Optimize the escape selections */
  1310. OptimizeEscape(&escape, NULL);
  1311. if (startEscape) *startEscape = escape;
  1312. OptimizeRle(flags); /* Retune the RLE selections */
  1313. if (flags & F_VERBOSE) {
  1314. int oldEscape = escape;
  1315. if (flags & F_VERBOSE) printf("normal RLE LZLEN LZPOS(absolute)\n\n");
  1316. for (p=0; p<inlen; ) {
  1317. switch (mode[p]) {
  1318. case LZ77:
  1319. mode[p - lzpos[p]] |= MMARK; /* Was referred to by lz77 */
  1320. p += lzlen[p];
  1321. break;
  1322. case RLE:
  1323. p += rle[p];
  1324. break;
  1325. case DLZ:
  1326. mode[p - lzpos2[p]] |= MMARK; /* Was referred to by lz77 */
  1327. p += lzlen2[p];
  1328. break;
  1329. /* case LITERAL:
  1330. case MMARK:*/
  1331. default:
  1332. p++;
  1333. break;
  1334. }
  1335. }
  1336. j = 0;
  1337. for (p=0; p<inlen; p++) {
  1338. switch (mode[p]) {
  1339. case MMARK | DLZ:
  1340. case DLZ:
  1341. if (j==p) {
  1342. if (flags & F_VERBOSE) printf(">");
  1343. j += lzlen2[p];
  1344. } else
  1345. printf(" ");
  1346. if (lzpos2) {
  1347. if (flags & F_VERBOSE) printf(" %04x*%03d*+%02x", lzpos2[p], lzlen2[p],(indata[p] - indata[p-lzpos2[p]]) & 0xff);
  1348. }
  1349. if (flags & F_VERBOSE) printf(" 001 %03d %03d %04x(%04x) %02x %s\n",
  1350. rle[p],lzlen[p],lzpos[p],p-lzpos[p],indata[p],
  1351. (mode[p] & MMARK)?"#":" ");
  1352. break;
  1353. case MMARK | LITERAL:
  1354. case LITERAL:
  1355. if (flags & F_VERBOSE) {
  1356. if (j==p) printf(">");
  1357. else printf(" ");
  1358. if (lzpos2) {
  1359. printf(" %04x %03d +%02x", lzpos2[p], lzlen2[p],
  1360. (indata[p] - indata[p-lzpos2[p]]) & 0xff);
  1361. }
  1362. }
  1363. if (j==p) {
  1364. if (flags & F_VERBOSE) {
  1365. printf("*001* %03d %03d %04x(%04x) %02x %s %02x",
  1366. rle[p], lzlen[p], lzpos[p], p-lzpos[p], indata[p],
  1367. (mode[p] & MMARK)?"#":" ", newesc[p]);
  1368. }
  1369. if ((indata[p] & escMask) == escape) {
  1370. escape = newesc[p];
  1371. if (flags & F_VERBOSE) printf("«");
  1372. }
  1373. if (flags & F_VERBOSE) printf("\n");
  1374. j += 1;
  1375. } else {
  1376. if (flags & F_VERBOSE) printf("*001* %03d %03d %04x(%04x) %02x %s %02x\n",
  1377. rle[p], lzlen[p], lzpos[p], p-lzpos[p], indata[p],
  1378. (mode[p] & MMARK)?"#":" ", newesc[p]);
  1379. }
  1380. break;
  1381. case MMARK | LZ77:
  1382. case LZ77:
  1383. if (j==p) {
  1384. if (flags & F_VERBOSE) printf(">");
  1385. j += lzlen[p];
  1386. } else
  1387. if (flags & F_VERBOSE) printf(" ");
  1388. if (lzpos2) {
  1389. if (flags & F_VERBOSE) printf(" %04x %03d +%02x", lzpos2[p], lzlen2[p],
  1390. (indata[p] - indata[p-lzpos2[p]]) & 0xff);
  1391. }
  1392. if (flags & F_VERBOSE) printf(" 001 %03d *%03d* %04x(%04x) %02x %s\n",
  1393. rle[p], lzlen[p], lzpos[p], p-lzpos[p], indata[p],
  1394. (mode[p] & MMARK)?"#":" ");
  1395. break;
  1396. case MMARK | RLE:
  1397. case RLE:
  1398. if (j==p) {
  1399. if (flags & F_VERBOSE) printf(">");
  1400. j += rle[p];
  1401. } else
  1402. if (flags & F_VERBOSE) printf(" ");
  1403. if (lzpos2) {
  1404. if (flags & F_VERBOSE) printf(" %04x %03d +%02x", lzpos2[p], lzlen2[p],
  1405. (indata[p] - indata[p-lzpos2[p]]) & 0xff);
  1406. }
  1407. if (flags & F_VERBOSE) printf(" 001 *%03d* %03d %04x(%04x) %02x %s\n",
  1408. rle[p], lzlen[p], lzpos[p], p-lzpos[p], indata[p],
  1409. (mode[p] & MMARK)?"#":" ");
  1410. break;
  1411. default:
  1412. j++;
  1413. break;
  1414. }
  1415. mode[p] &= ~MMARK;
  1416. }
  1417. escape = oldEscape;
  1418. }
  1419. for (p=0; p<inlen; ) {
  1420. switch (mode[p]) {
  1421. case LITERAL: /* normal */
  1422. length[p] = outPointer;
  1423. OutputNormal(&escape, indata+p, newesc[p]);
  1424. p++;
  1425. break;
  1426. case DLZ:
  1427. for (i=0; i<lzlen2[p]; i++) length[p+i] = outPointer;
  1428. PutNBits((escape>>(8-escBits)), escBits);
  1429. PutValue(lzlen2[p]-1);
  1430. PutValue((2<<maxGamma)-1);
  1431. PutNBits((indata[p] - indata[p-lzpos2[p]]) & 0xff, 8);
  1432. PutNBits(((lzpos2[p]-1) & 0xff) ^ 0xff, 8);
  1433. gainedDLz += 8*lzlen2[p] -(escBits + LenValue(lzlen2[p]-1) + 2*maxGamma + 16);
  1434. timesDLz++;
  1435. p += lzlen2[p];
  1436. break;
  1437. case LZ77: /* lz77 */
  1438. /* Not possible for smaller backSkip table
  1439. (the table is overwritten during previous use) */
  1440. /* Re-search matches to get the closest one */
  1441. if (lzopt && lzlen[p] > 2 && lzlen[p] > rle[p]) {
  1442. int bot = p - lzpos[p] + 1, i;
  1443. unsigned short rlep = rle[p];
  1444. if (!rlep)
  1445. rlep = 1;
  1446. if (bot < 0)
  1447. bot = 0;
  1448. bot += (rlep-1);
  1449. i = p - (int)backSkip[p];
  1450. while (i>=bot /* && i>=rlep-1 */) {
  1451. /* Equal number of A's ? */
  1452. if (rlep==1 || rle[i-rlep+1]==rlep) { /* 'head' matches */
  1453. unsigned char *a = indata + i+1; /* match */
  1454. unsigned char *b = indata + p+rlep-1+1; /* curpos */
  1455. int topindex = inlen-(p+rlep-1);
  1456. j = 1;
  1457. while (j < topindex && *a++==*b++)
  1458. j++;
  1459. if (j + rlep-1 >= lzlen[p]) {
  1460. int tmppos = p-i+rlep-1;
  1461. rescan +=
  1462. LenLz(lzlen[p], lzpos[p]) -
  1463. LenLz(lzlen[p], tmppos);
  1464. lzpos[p] = tmppos;
  1465. break;
  1466. }
  1467. }
  1468. if (!backSkip[i])
  1469. break; /* No previous occurrances (near enough) */
  1470. i -= (int)backSkip[i];
  1471. }
  1472. }
  1473. for (i=0; i<lzlen[p]; i++)
  1474. length[p+i] = outPointer;
  1475. OutputLz(&escape, lzlen[p], lzpos[p], (char *)(indata+p-lzpos[p]), p);
  1476. p += lzlen[p];
  1477. break;
  1478. case RLE: /* rle */
  1479. for (i=0; i<rle[p]; i++)
  1480. length[p+i] = outPointer;
  1481. OutputRle(&escape, indata+p, rle[p]);
  1482. p += rle[p];
  1483. break;
  1484. default: /* Error Flynn :-) */
  1485. p++;
  1486. fprintf(stderr, "Internal error: mode %d\n", mode[p]);
  1487. break;
  1488. }
  1489. }
  1490. OutputEof(&escape);
  1491. i = inlen;
  1492. for (p=0; p<inlen; p++) {
  1493. int pos = (inlen - outPointer) + (int)length[p] - p;
  1494. i = min(i, pos);
  1495. }
  1496. if (i<0)
  1497. reservedBytes = -i + 2;
  1498. else
  1499. reservedBytes = 0;
  1500. // TOMTOM !!!
  1501. if ((type & FIXF_MACHMASK) == 0) {
  1502. headerSize = 16 + rleUsed;
  1503. } else
  1504. {
  1505. if (endAddr + reservedBytes + 3 > memEnd) {
  1506. type |= FIXF_WRAP;
  1507. } else {
  1508. type &= ~FIXF_WRAP;
  1509. }
  1510. headerSize = 47 + rleUsed - 31;
  1511. }
  1512. outlen = outPointer + headerSize; /* unpack code */
  1513. if (flags & F_VERBOSE) fprintf(stderr, "In: %d, out: %d, ratio: %5.2f%% (%4.2f[%4.2f] b/B)"
  1514. ", gained: %5.2f%%\n",
  1515. inlen, outlen, (double)outlen*100.0/(double)inlen + 0.005,
  1516. 8.0*(double)outlen/(double)inlen + 0.005,
  1517. 8.0*(double)(outlen-headerSize+rleUsed+4)/(double)inlen + 0.005,
  1518. 100.0 - (double)outlen*100.0/(double)inlen + 0.005);
  1519. if ((type & FIXF_DLZ)) {
  1520. if (flags & F_VERBOSE) {
  1521. fprintf(stderr, "Gained RLE: %d (S+L:%d+%d), DLZ: %d, LZ: %d, Esc: %d"
  1522. ", Decompressor: %d\n",
  1523. gainedRle/8, gainedSRle/8, gainedLRle/8, gainedDLz/8,
  1524. gainedLz/8, -gainedEscaped/8, -headerSize);
  1525. fprintf(stderr, "Times RLE: %d (%d+%d), DLZ: %d, LZ: %d, Esc: %d (normal: %d)"
  1526. ", %d escape bit%s\n",
  1527. timesRle, timesSRle, timesLRle, timesDLz,
  1528. timesLz, timesEscaped, timesNormal,
  1529. escBits, (escBits==1)?"":"s" );
  1530. }
  1531. }
  1532. else {
  1533. if (flags & F_VERBOSE) {
  1534. fprintf(stderr, "Gained RLE: %d (S+L:%d+%d), LZ: %d, Esc: %d"
  1535. ", Decompressor: %d\n",
  1536. gainedRle/8, gainedSRle/8, gainedLRle/8,
  1537. gainedLz/8, -gainedEscaped/8, -headerSize);
  1538. fprintf(stderr, "Times RLE: %d (%d+%d), LZ: %d, Esc: %d (normal: %d)"
  1539. ", %d escape bit%s\n",
  1540. timesRle, timesSRle, timesLRle,
  1541. timesLz, timesEscaped, timesNormal,
  1542. escBits, (escBits==1)?"":"s" );
  1543. }
  1544. }
  1545. if ((flags & F_STATS)) {
  1546. char *ll[] = {"2", "3-4", "5-8", "9-16", "17-32", "33-64",
  1547. "65-128", "129-256"};
  1548. fprintf(stderr, "(Gained by RLE Code: %d, LZPOS LO Bits %d"
  1549. ", maxLen: %d, tag bit/prim. %4.2f)\n",
  1550. gainedRlecode/8 - rleUsed,
  1551. extraLZPosBits + 8,
  1552. (2<<maxGamma),
  1553. (double)((timesRle+timesLz)*escBits +
  1554. timesEscaped*(escBits + 3))/
  1555. (double)(timesRle+timesLz+timesNormal) + 0.0049);
  1556. fprintf(stderr, " LZPOS HI+2 LZLEN S-RLE RLEcode\n");
  1557. fprintf(stderr, " ------------------------------\n");
  1558. for (i=0; i<=maxGamma; i++) {
  1559. fprintf(stderr, "%-7s %5d %5d", ll[i],
  1560. lenStat[i][0], lenStat[i][1]);
  1561. if (i<maxGamma)
  1562. fprintf(stderr, " %5d", lenStat[i][2]);
  1563. else
  1564. fprintf(stderr, " -");
  1565. if (i<6)
  1566. fprintf(stderr, " %5d%s\n", lenStat[i][3], (i==5)?"*":"");
  1567. else
  1568. fprintf(stderr, " -\n");
  1569. }
  1570. fprintf(stderr, "LZ77 rescan gained %d bytes\n", rescan/8);
  1571. }
  1572. errorexit:
  1573. if (rle) free(rle);
  1574. if (elr) free(elr);
  1575. if (lzlen) free(lzlen);
  1576. if (lzpos) free(lzpos);
  1577. if (length) free(length);
  1578. if (mode) free(mode);
  1579. if (newesc) free(newesc);
  1580. if (lastPair) free(lastPair);
  1581. if (backSkip) free(backSkip);
  1582. if (hashValue) free(hashValue);
  1583. return err_occured;
  1584. }
  1585. #define NO_HEX_CHARACTER 255
  1586. //=============================================================================
  1587. // converts hexdigit to number
  1588. //=============================================================================
  1589. unsigned char hex2int(unsigned char c) {
  1590. c = tolower(c);
  1591. if (c >= 'a' && c <= 'f') return c - 'a' + 10;
  1592. if (c >= '0' && c <= '9') return c - '0';
  1593. return NO_HEX_CHARACTER;
  1594. }
  1595. //=============================================================================
  1596. // converts hex text into binary
  1597. //=============================================================================
  1598. int ConvertText2Bin(unsigned char* ib,int origlen) {
  1599. int pos;
  1600. int cnt = 0;
  1601. int searchforendofline = 0;
  1602. int len_after_convert = 0;
  1603. unsigned char val = 0;
  1604. unsigned char actual;
  1605. len_after_convert = 0;
  1606. for (pos = 0; pos < origlen;pos++) {
  1607. if (searchforendofline) {
  1608. if (ib[pos] == '\n') searchforendofline = 0;
  1609. continue;
  1610. }
  1611. if (ib[pos] == '/') {
  1612. cnt = 0;
  1613. if (pos < origlen-1 && ib[pos+1] == '/') searchforendofline = 1;
  1614. continue;
  1615. }
  1616. actual = hex2int(ib[pos]);
  1617. if (actual == NO_HEX_CHARACTER) {
  1618. cnt = 0;
  1619. continue;
  1620. }
  1621. if (cnt == 0) {
  1622. val = actual*16;
  1623. cnt++;
  1624. }
  1625. else {
  1626. val += actual;
  1627. cnt=0;
  1628. ib[len_after_convert++] = val;
  1629. }
  1630. }
  1631. return(len_after_convert);
  1632. }
  1633. //=============================================================================
  1634. // as usual: the main, but a long one ...
  1635. //=============================================================================
  1636. #ifndef EMBEDDED_USE
  1637. int main(int argc, char *argv[]) {
  1638. #else
  1639. int TTPack(int argc,char *argv[]) {
  1640. #endif
  1641. int startAddr = 0x258;
  1642. int flags = F_AUTO | F_AUTOEX;
  1643. int lzlen = -1;
  1644. int buflen;
  1645. int newlen;
  1646. int startEscape;
  1647. int n;
  1648. char *fileIn = NULL;
  1649. char *fileOut = NULL;
  1650. FILE *infp;
  1651. unsigned long timeused = clock();
  1652. int memStart = 0x801;
  1653. int memEnd = 0x10000;
  1654. int type = 0;
  1655. quiet = 0;
  1656. TTPackInit();
  1657. lrange = LRANGE;
  1658. maxlzlen = MAXLZLEN;
  1659. maxrlelen = MAXRLELEN;
  1660. InitValueLen();
  1661. for (n=1; n<argc; n++) {
  1662. if (!strcmp(argv[n], "-fnorle")) flags |= F_NORLE;
  1663. else if (!strcmp(argv[n], "-fdelta")) type |= FIXF_DLZ;
  1664. else if (!strcmp(argv[n], "-hti")) flags |= F_TEXTINPUT;
  1665. else if (!strcmp(argv[n], "-hto")) flags |= F_TEXTOUTPUT;
  1666. else if (!strcmp(argv[n], "-quiet")) flags &= ~F_VERBOSE, quiet = 1;
  1667. else if (argv[n][0]=='-' || argv[n][0]=='/') {
  1668. int i = 1;
  1669. char *val, *tmp, c;
  1670. long tmpval;
  1671. while (argv[n][i]) {
  1672. switch (argv[n][i]) {
  1673. case 'n': /* noopt, no rle/lzlen optimization */
  1674. flags |= F_NOOPT;
  1675. break;
  1676. case 's':
  1677. flags |= F_STATS;
  1678. break;
  1679. case 'v':
  1680. flags |= F_VERBOSE;
  1681. quiet = 0;
  1682. break;
  1683. case 'h':
  1684. case '?':
  1685. flags |= F_ERROR;
  1686. break;
  1687. case 'r':
  1688. case 'm':
  1689. case 'e':
  1690. case 'p':
  1691. c = argv[n][i]; /* Remember the option */
  1692. if (argv[n][i+1]) {
  1693. val = argv[n]+i+1;
  1694. } else if (n+1 < argc) {
  1695. val = argv[n+1];
  1696. n++;
  1697. } else {
  1698. flags |= F_ERROR;
  1699. break;
  1700. }
  1701. i = strlen(argv[n])-1;
  1702. if (*val=='$') tmpval = strtol(val+1, &tmp, 16);
  1703. else tmpval = strtol(val, &tmp, 0);
  1704. if (*tmp) {
  1705. fprintf(stderr,"ERROR: invalid number: \"%s\"\n", val);
  1706. flags |= F_ERROR;
  1707. break;
  1708. }
  1709. switch (c) {
  1710. case 'r':
  1711. lzlen = tmpval;
  1712. break;
  1713. case 'm':
  1714. maxGamma = tmpval;
  1715. if (maxGamma < 5 || maxGamma > 7) {
  1716. fprintf(stderr, "ERROR: Max length must be 5..7!\n");
  1717. flags |= F_ERROR;
  1718. maxGamma = 7;
  1719. }
  1720. lrange = LRANGE;
  1721. maxlzlen = MAXLZLEN;
  1722. maxrlelen = MAXRLELEN;
  1723. InitValueLen();
  1724. break;
  1725. case 'e':
  1726. escBits = tmpval;
  1727. if (escBits < 0 || escBits > 8) {
  1728. fprintf(stderr, "ERROR: Escape bits must be 0..8!\n");
  1729. flags |= F_ERROR;
  1730. }
  1731. else flags &= ~F_AUTO;
  1732. escMask = (0xff00>>escBits) & 0xff;
  1733. break;
  1734. case 'p':
  1735. extraLZPosBits = tmpval;
  1736. if (extraLZPosBits < 0 || extraLZPosBits > 4) {
  1737. fprintf(stderr,"ERROR: Extra LZ-pos bits must be 0..4!\n");
  1738. flags |= F_ERROR;
  1739. }
  1740. else flags &= ~F_AUTOEX;
  1741. break;
  1742. }
  1743. break;
  1744. default:
  1745. fprintf(stderr, "ERROR: Unknown option \"%c\"\n",argv[n][i]);
  1746. flags |= F_ERROR;
  1747. }
  1748. i++;
  1749. }
  1750. } else {
  1751. if (!fileIn) {
  1752. fileIn = argv[n];
  1753. }
  1754. else if (!fileOut) {
  1755. fileOut = argv[n];
  1756. }
  1757. else {
  1758. fprintf(stderr, "ERROR: Only two filenames wanted!\n");
  1759. flags |= F_ERROR;
  1760. }
  1761. }
  1762. }
  1763. // input and output file
  1764. if ((flags & F_ERROR) || !fileIn || !fileOut) {
  1765. #ifndef EMBEDDED_USE
  1766. PrintUsage();
  1767. #endif
  1768. return 1;
  1769. }
  1770. #ifndef EMBEDDED_USE
  1771. if (!quiet) PRINT_ID("TTPack");
  1772. #endif
  1773. if (lzlen == -1) lzlen = DEFAULT_LZLEN;
  1774. if (fileIn) {
  1775. if (!(infp = fopen(fileIn, "rb"))) {
  1776. fprintf(stderr, "ERROR: Could not open %s for reading!\n", fileIn);
  1777. return 1;
  1778. }
  1779. }
  1780. else {
  1781. fprintf(stderr, "assuming stdin as text input.\nCtrl-C to abort, Ctrl-Z for EOF.\n");
  1782. infp = stdin;
  1783. }
  1784. /* Read in the data */
  1785. inlen = 0;
  1786. buflen = 0;
  1787. indata = NULL;
  1788. while (1) {
  1789. if (buflen < inlen + lrange) {
  1790. unsigned char *tmp = realloc(indata, buflen + lrange);
  1791. if (!tmp) {
  1792. free(indata);
  1793. fprintf(stderr, "ERROR: realloc failed!\n");
  1794. return 1;
  1795. }
  1796. indata = tmp;
  1797. buflen += lrange;
  1798. }
  1799. newlen = fread(indata + inlen, 1, lrange, infp);
  1800. if (newlen <= 0) break;
  1801. inlen += newlen;
  1802. }
  1803. //-----------------------------------------------------------
  1804. // convert the input buffer from hex text to binary
  1805. // if the user asks for it
  1806. //-----------------------------------------------------------
  1807. if (flags & F_TEXTINPUT) inlen = ConvertText2Bin(indata,inlen);
  1808. if (infp != stdin) fclose(infp);
  1809. if (startAddr + inlen -1 > 0xffff) {
  1810. fprintf(stderr,"ERROR: File is too large to handle (>64936 Bytes)");
  1811. if (indata) free(indata);
  1812. return 1;
  1813. }
  1814. if (flags & F_VERBOSE) {
  1815. fprintf(stderr, "Load address 0x%04x=%d, Last byte 0x%04x=%d\n",
  1816. startAddr, startAddr, startAddr+inlen-1, startAddr+inlen-1);
  1817. fprintf(stderr, "New load address 0x%04x=%d\n", memStart, memStart);
  1818. }
  1819. n = PackLz77(lzlen, flags, &startEscape, startAddr + inlen, memEnd, type);
  1820. if (!n) {
  1821. int endAddr = startAddr + inlen; /* end for uncompressed data */
  1822. if (endAddr - ((outPointer + 255) & ~255) < memStart + 3) {
  1823. /* would overwrite the decompressor, move a bit upwards */
  1824. if (flags & F_VERBOSE) fprintf(stderr,"$%x < $%x, decompressor overwrite possible, moving upwards\n",
  1825. endAddr - ((outPointer + 255) & ~255), memStart + 3);
  1826. endAddr = memStart + 3 + ((outPointer + 255) & ~255);
  1827. }
  1828. /* 3 bytes reserved for EOF */
  1829. /* bytes reserved for temporary data expansion (escaped chars) */
  1830. endAddr += 3 + reservedBytes;
  1831. if (!timesDLz) type &= ~FIXF_DLZ;
  1832. // type ... may vary
  1833. // outBuffer ... static global array (65536 Bytes)
  1834. SavePack(flags,type, outBuffer, outPointer, fileOut,
  1835. startAddr, startEscape, rleValues,
  1836. endAddr, extraLZPosBits,
  1837. memStart, memEnd);
  1838. timeused = clock()-timeused;
  1839. if (!timeused) timeused++;
  1840. if (flags & F_VERBOSE) fprintf(stderr,
  1841. "Compressed %d bytes in %4.2f seconds (%4.2f kB/sec)\n",
  1842. inlen,
  1843. (double)timeused/CLOCKS_PER_SEC,
  1844. (double)CLOCKS_PER_SEC*inlen/timeused/1024.0);
  1845. return 0;
  1846. }
  1847. if (indata) free(indata);
  1848. return n;
  1849. }
  1850. #endif
  1851. //#############################################################################
  1852. //###################### NO MORE FAKES BEYOND THIS LINE #######################
  1853. //#############################################################################
  1854. //
  1855. //=============================================================================
  1856. // Revision History
  1857. //=============================================================================
  1858. //
  1859. // Revision 1.9 2009/01/25 Lionel Debroux
  1860. // Changes by Romain Liévin and/or me for 64-bit compatibility.
  1861. // Adapt to new version display (revtools.h).
  1862. //
  1863. // Revision 1.8 2002/03/14 10:47:41 tnussb
  1864. // (1) new flag "-quiet" added (suppress standard messages)
  1865. // (2) some error messages rewritten
  1866. //
  1867. // Revision 1.7 2002/03/04 14:32:42 tnussb
  1868. // now tool can be used as embedded version from within other tools
  1869. // by defining EMBEDDED_VERSION before including the sourcefile
  1870. //
  1871. // Revision 1.6 2002/02/07 09:49:37 tnussb
  1872. // all local includes changed, because header files are now located in pctools folder
  1873. //
  1874. // Revision 1.5 2000/11/28 00:07:32 Thomas Nussbaumer
  1875. // using now USAGE_OUT stream for usage info
  1876. //
  1877. // Revision 1.4 2000/08/23 20:10:56 Thomas Nussbaumer
  1878. // header corrected
  1879. //
  1880. // Revision 1.3 2000/08/23 20:10:17 Thomas Nussbaumer
  1881. // adapted to automatic version display (revtools.h)
  1882. //
  1883. // Revision 1.2 2000/08/20 15:30:11 Thomas Nussbaumer
  1884. // minor correction of header
  1885. //
  1886. // Revision 1.1 2000/08/16 23:05:59 Thomas Nussbaumer
  1887. // initial version
  1888. //
  1889. //