sdd1emu.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451
  1. #ifdef SDD1_CPP
  2. /************************************************************************
  3. S-DD1'algorithm emulation code
  4. ------------------------------
  5. Author: Andreas Naive
  6. Date: August 2003
  7. Last update: October 2004
  8. This code is Public Domain. There is no copyright holded by the author.
  9. Said this, the author wish to explicitly emphasize his inalienable moral rights
  10. over this piece of intelectual work and the previous research that made it
  11. possible, as recognized by most of the copyright laws around the world.
  12. This code is provided 'as-is', with no warranty, expressed or implied.
  13. No responsability is assumed by the author in connection with it.
  14. The author is greatly indebted with The Dumper, without whose help and
  15. patience providing him with real S-DD1 data the research would have never been
  16. possible. He also wish to note that in the very beggining of his research,
  17. Neviksti had done some steps in the right direction. By last, the author is
  18. indirectly indebted to all the people that worked and contributed in the
  19. S-DD1 issue in the past.
  20. An algorithm's documentation is available as a separate document.
  21. The implementation is obvious when the algorithm is
  22. understood.
  23. ************************************************************************/
  24. #define SDD1_read(__addr) (sdd1.read(__addr))
  25. ////////////////////////////////////////////////////
  26. void SDD1_IM::prepareDecomp(uint32 in_buf) {
  27. byte_ptr=in_buf;
  28. bit_count=4;
  29. }
  30. ////////////////////////////////////////////////////
  31. uint8 SDD1_IM::getCodeword(uint8 code_len) {
  32. uint8 codeword;
  33. uint8 comp_count;
  34. codeword = (SDD1_read(byte_ptr))<<bit_count;
  35. ++bit_count;
  36. if (codeword & 0x80) {
  37. codeword |= SDD1_read(byte_ptr+1)>>(9-bit_count);
  38. bit_count+=code_len;
  39. }
  40. if (bit_count & 0x08) {
  41. byte_ptr++;
  42. bit_count&=0x07;
  43. }
  44. return codeword;
  45. }
  46. //////////////////////////////////////////////////////
  47. SDD1_GCD::SDD1_GCD(SDD1_IM *associatedIM) :
  48. IM(associatedIM)
  49. {
  50. }
  51. //////////////////////////////////////////////////////
  52. void SDD1_GCD::getRunCount(uint8 code_num, uint8 *MPScount, bool8 *LPSind) {
  53. const uint8 run_count[] = {
  54. 0x00, 0x00, 0x01, 0x00, 0x03, 0x01, 0x02, 0x00,
  55. 0x07, 0x03, 0x05, 0x01, 0x06, 0x02, 0x04, 0x00,
  56. 0x0f, 0x07, 0x0b, 0x03, 0x0d, 0x05, 0x09, 0x01,
  57. 0x0e, 0x06, 0x0a, 0x02, 0x0c, 0x04, 0x08, 0x00,
  58. 0x1f, 0x0f, 0x17, 0x07, 0x1b, 0x0b, 0x13, 0x03,
  59. 0x1d, 0x0d, 0x15, 0x05, 0x19, 0x09, 0x11, 0x01,
  60. 0x1e, 0x0e, 0x16, 0x06, 0x1a, 0x0a, 0x12, 0x02,
  61. 0x1c, 0x0c, 0x14, 0x04, 0x18, 0x08, 0x10, 0x00,
  62. 0x3f, 0x1f, 0x2f, 0x0f, 0x37, 0x17, 0x27, 0x07,
  63. 0x3b, 0x1b, 0x2b, 0x0b, 0x33, 0x13, 0x23, 0x03,
  64. 0x3d, 0x1d, 0x2d, 0x0d, 0x35, 0x15, 0x25, 0x05,
  65. 0x39, 0x19, 0x29, 0x09, 0x31, 0x11, 0x21, 0x01,
  66. 0x3e, 0x1e, 0x2e, 0x0e, 0x36, 0x16, 0x26, 0x06,
  67. 0x3a, 0x1a, 0x2a, 0x0a, 0x32, 0x12, 0x22, 0x02,
  68. 0x3c, 0x1c, 0x2c, 0x0c, 0x34, 0x14, 0x24, 0x04,
  69. 0x38, 0x18, 0x28, 0x08, 0x30, 0x10, 0x20, 0x00,
  70. 0x7f, 0x3f, 0x5f, 0x1f, 0x6f, 0x2f, 0x4f, 0x0f,
  71. 0x77, 0x37, 0x57, 0x17, 0x67, 0x27, 0x47, 0x07,
  72. 0x7b, 0x3b, 0x5b, 0x1b, 0x6b, 0x2b, 0x4b, 0x0b,
  73. 0x73, 0x33, 0x53, 0x13, 0x63, 0x23, 0x43, 0x03,
  74. 0x7d, 0x3d, 0x5d, 0x1d, 0x6d, 0x2d, 0x4d, 0x0d,
  75. 0x75, 0x35, 0x55, 0x15, 0x65, 0x25, 0x45, 0x05,
  76. 0x79, 0x39, 0x59, 0x19, 0x69, 0x29, 0x49, 0x09,
  77. 0x71, 0x31, 0x51, 0x11, 0x61, 0x21, 0x41, 0x01,
  78. 0x7e, 0x3e, 0x5e, 0x1e, 0x6e, 0x2e, 0x4e, 0x0e,
  79. 0x76, 0x36, 0x56, 0x16, 0x66, 0x26, 0x46, 0x06,
  80. 0x7a, 0x3a, 0x5a, 0x1a, 0x6a, 0x2a, 0x4a, 0x0a,
  81. 0x72, 0x32, 0x52, 0x12, 0x62, 0x22, 0x42, 0x02,
  82. 0x7c, 0x3c, 0x5c, 0x1c, 0x6c, 0x2c, 0x4c, 0x0c,
  83. 0x74, 0x34, 0x54, 0x14, 0x64, 0x24, 0x44, 0x04,
  84. 0x78, 0x38, 0x58, 0x18, 0x68, 0x28, 0x48, 0x08,
  85. 0x70, 0x30, 0x50, 0x10, 0x60, 0x20, 0x40, 0x00,
  86. };
  87. uint8 codeword=IM->getCodeword(code_num);
  88. if (codeword & 0x80) {
  89. *LPSind=1;
  90. *MPScount=run_count[codeword>>(code_num^0x07)];
  91. }
  92. else {
  93. *MPScount=(1<<code_num);
  94. }
  95. }
  96. ///////////////////////////////////////////////////////
  97. SDD1_BG::SDD1_BG(SDD1_GCD *associatedGCD, uint8 code) :
  98. GCD(associatedGCD), code_num(code)
  99. {
  100. }
  101. ///////////////////////////////////////////////
  102. void SDD1_BG::prepareDecomp(void) {
  103. MPScount=0;
  104. LPSind=0;
  105. }
  106. //////////////////////////////////////////////
  107. uint8 SDD1_BG::getBit(bool8 *endOfRun) {
  108. uint8 bit;
  109. if (!(MPScount || LPSind)) GCD->getRunCount(code_num, &MPScount, &LPSind);
  110. if (MPScount) {
  111. bit=0;
  112. MPScount--;
  113. }
  114. else {
  115. bit=1;
  116. LPSind=0;
  117. }
  118. if (MPScount || LPSind) (*endOfRun)=0;
  119. else (*endOfRun)=1;
  120. return bit;
  121. }
  122. /////////////////////////////////////////////////
  123. SDD1_PEM::SDD1_PEM(SDD1_BG *associatedBG0, SDD1_BG *associatedBG1,
  124. SDD1_BG *associatedBG2, SDD1_BG *associatedBG3,
  125. SDD1_BG *associatedBG4, SDD1_BG *associatedBG5,
  126. SDD1_BG *associatedBG6, SDD1_BG *associatedBG7) {
  127. BG[0]=associatedBG0;
  128. BG[1]=associatedBG1;
  129. BG[2]=associatedBG2;
  130. BG[3]=associatedBG3;
  131. BG[4]=associatedBG4;
  132. BG[5]=associatedBG5;
  133. BG[6]=associatedBG6;
  134. BG[7]=associatedBG7;
  135. }
  136. /////////////////////////////////////////////////////////
  137. const SDD1_PEM::state SDD1_PEM::evolution_table[]={
  138. { 0,25,25},
  139. { 0, 2, 1},
  140. { 0, 3, 1},
  141. { 0, 4, 2},
  142. { 0, 5, 3},
  143. { 1, 6, 4},
  144. { 1, 7, 5},
  145. { 1, 8, 6},
  146. { 1, 9, 7},
  147. { 2,10, 8},
  148. { 2,11, 9},
  149. { 2,12,10},
  150. { 2,13,11},
  151. { 3,14,12},
  152. { 3,15,13},
  153. { 3,16,14},
  154. { 3,17,15},
  155. { 4,18,16},
  156. { 4,19,17},
  157. { 5,20,18},
  158. { 5,21,19},
  159. { 6,22,20},
  160. { 6,23,21},
  161. { 7,24,22},
  162. { 7,24,23},
  163. { 0,26, 1},
  164. { 1,27, 2},
  165. { 2,28, 4},
  166. { 3,29, 8},
  167. { 4,30,12},
  168. { 5,31,16},
  169. { 6,32,18},
  170. { 7,24,22}
  171. };
  172. //////////////////////////////////////////////////////
  173. void SDD1_PEM::prepareDecomp(void) {
  174. for (uint8 i=0; i<32; i++) {
  175. contextInfo[i].status=0;
  176. contextInfo[i].MPS=0;
  177. }
  178. }
  179. /////////////////////////////////////////////////////////
  180. uint8 SDD1_PEM::getBit(uint8 context) {
  181. bool8 endOfRun;
  182. uint8 bit;
  183. SDD1_ContextInfo *pContInfo=&contextInfo[context];
  184. uint8 currStatus = pContInfo->status;
  185. const state *pState=&SDD1_PEM::evolution_table[currStatus];
  186. uint8 currentMPS=pContInfo->MPS;
  187. bit=(BG[pState->code_num])->getBit(&endOfRun);
  188. if (endOfRun)
  189. if (bit) {
  190. if (!(currStatus & 0xfe)) (pContInfo->MPS)^=0x01;
  191. (pContInfo->status)=pState->nextIfLPS;
  192. }
  193. else
  194. (pContInfo->status)=pState->nextIfMPS;
  195. return bit^currentMPS;
  196. }
  197. //////////////////////////////////////////////////////////////
  198. SDD1_CM::SDD1_CM(SDD1_PEM *associatedPEM) :
  199. PEM(associatedPEM)
  200. {
  201. }
  202. //////////////////////////////////////////////////////////////
  203. void SDD1_CM::prepareDecomp(uint32 first_byte) {
  204. bitplanesInfo = SDD1_read(first_byte) & 0xc0;
  205. contextBitsInfo = SDD1_read(first_byte) & 0x30;
  206. bit_number=0;
  207. for (int i=0; i<8; i++) prevBitplaneBits[i]=0;
  208. switch (bitplanesInfo) {
  209. case 0x00:
  210. currBitplane = 1;
  211. break;
  212. case 0x40:
  213. currBitplane = 7;
  214. break;
  215. case 0x80:
  216. currBitplane = 3;
  217. }
  218. }
  219. /////////////////////////////////////////////////////////////
  220. uint8 SDD1_CM::getBit(void) {
  221. uint8 currContext;
  222. uint16 *context_bits;
  223. switch (bitplanesInfo) {
  224. case 0x00:
  225. currBitplane ^= 0x01;
  226. break;
  227. case 0x40:
  228. currBitplane ^= 0x01;
  229. if (!(bit_number & 0x7f)) currBitplane = ((currBitplane+2) & 0x07);
  230. break;
  231. case 0x80:
  232. currBitplane ^= 0x01;
  233. if (!(bit_number & 0x7f)) currBitplane ^= 0x02;
  234. break;
  235. case 0xc0:
  236. currBitplane = bit_number & 0x07;
  237. }
  238. context_bits = &prevBitplaneBits[currBitplane];
  239. currContext=(currBitplane & 0x01)<<4;
  240. switch (contextBitsInfo) {
  241. case 0x00:
  242. currContext|=((*context_bits & 0x01c0)>>5)|(*context_bits & 0x0001);
  243. break;
  244. case 0x10:
  245. currContext|=((*context_bits & 0x0180)>>5)|(*context_bits & 0x0001);
  246. break;
  247. case 0x20:
  248. currContext|=((*context_bits & 0x00c0)>>5)|(*context_bits & 0x0001);
  249. break;
  250. case 0x30:
  251. currContext|=((*context_bits & 0x0180)>>5)|(*context_bits & 0x0003);
  252. }
  253. uint8 bit=PEM->getBit(currContext);
  254. *context_bits <<= 1;
  255. *context_bits |= bit;
  256. bit_number++;
  257. return bit;
  258. }
  259. //////////////////////////////////////////////////
  260. SDD1_OL::SDD1_OL(SDD1_CM *associatedCM) :
  261. CM(associatedCM)
  262. {
  263. }
  264. ///////////////////////////////////////////////////
  265. void SDD1_OL::prepareDecomp(uint32 first_byte, uint16 out_len, uint8 *out_buf) {
  266. bitplanesInfo = SDD1_read(first_byte) & 0xc0;
  267. length=out_len;
  268. buffer=out_buf;
  269. }
  270. ///////////////////////////////////////////////////
  271. void SDD1_OL::launch(void) {
  272. uint8 i;
  273. uint8 register1, register2;
  274. switch (bitplanesInfo) {
  275. case 0x00:
  276. case 0x40:
  277. case 0x80:
  278. i=1;
  279. do { //if length==0, we output 2^16 bytes
  280. if (!i) {
  281. *(buffer++)=register2;
  282. i=~i;
  283. }
  284. else {
  285. for (register1=register2=0, i=0x80; i; i>>=1) {
  286. if (CM->getBit()) register1 |= i;
  287. if (CM->getBit()) register2 |= i;
  288. }
  289. *(buffer++)=register1;
  290. }
  291. } while (--length);
  292. break;
  293. case 0xc0:
  294. do {
  295. for (register1=0, i=0x01; i; i<<=1) {
  296. if (CM->getBit()) register1 |= i;
  297. }
  298. *(buffer++)=register1;
  299. } while (--length);
  300. }
  301. }
  302. ///////////////////////////////////////////////////////
  303. void SDD1emu::decompress(uint32 in_buf, uint16 out_len, uint8 *out_buf) {
  304. IM.prepareDecomp(in_buf);
  305. BG0.prepareDecomp();
  306. BG1.prepareDecomp();
  307. BG2.prepareDecomp();
  308. BG3.prepareDecomp();
  309. BG4.prepareDecomp();
  310. BG5.prepareDecomp();
  311. BG6.prepareDecomp();
  312. BG7.prepareDecomp();
  313. PEM.prepareDecomp();
  314. CM.prepareDecomp(in_buf);
  315. OL.prepareDecomp(in_buf, out_len, out_buf);
  316. OL.launch();
  317. }
  318. ////////////////////////////////////////////////////////////
  319. SDD1emu::SDD1emu() :
  320. GCD(&IM),
  321. BG0(&GCD, 0), BG1(&GCD, 1), BG2(&GCD, 2), BG3(&GCD, 3),
  322. BG4(&GCD, 4), BG5(&GCD, 5), BG6(&GCD, 6), BG7(&GCD, 7),
  323. PEM(&BG0, &BG1, &BG2, &BG3, &BG4, &BG5, &BG6, &BG7),
  324. CM(&PEM),
  325. OL(&CM)
  326. {
  327. }
  328. ///////////////////////////////////////////////////////////
  329. #endif