Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

212 lines
4.7 KiB

  1. /*
  2. * io.c
  3. */
  4. #include "encoder.h"
  5. /*
  6. * Similar to the optimisation we have for the decoder.
  7. *
  8. * Allow the encoder to "overrun" output buffer by up to X bytes
  9. * so that we don't have to check for the end of the buffer every
  10. * single time we call outbits() in encdata.c
  11. */
  12. #define OUTPUT_EXTRA_BYTES 64
  13. static void encoder_translate_e8(t_encoder_context *context, byte *mem, long bytes);
  14. void output_bits(t_encoder_context *context, int n, ulong x)
  15. {
  16. context->enc_bitbuf |= (((ulong) x) << (context->enc_bitcount - n));
  17. context->enc_bitcount -= (signed char) n;
  18. while (context->enc_bitcount <= 16)
  19. {
  20. if (context->enc_output_buffer_curpos >= context->enc_output_buffer_end)
  21. {
  22. context->enc_output_overflow = true;
  23. context->enc_output_buffer_curpos = context->enc_output_buffer_start;
  24. }
  25. *context->enc_output_buffer_curpos++ = (byte) ((context->enc_bitbuf >> 16) & 255);
  26. *context->enc_output_buffer_curpos++ = (byte) (context->enc_bitbuf >> 24);
  27. context->enc_bitbuf <<= 16;
  28. context->enc_bitcount += 16;
  29. }
  30. }
  31. /*
  32. * Initialises output buffering
  33. */
  34. bool init_compressed_output_buffer(t_encoder_context *context)
  35. {
  36. if (!(context->enc_output_buffer_start = (byte *) context->enc_malloc(OUTPUT_BUFFER_SIZE)))
  37. return false;
  38. context->enc_output_buffer_curpos = context->enc_output_buffer_start;
  39. context->enc_output_buffer_end =
  40. context->enc_output_buffer_start+(OUTPUT_BUFFER_SIZE-OUTPUT_EXTRA_BYTES);
  41. return true;
  42. }
  43. void free_compressed_output_buffer(t_encoder_context *context)
  44. {
  45. if (context->enc_output_buffer_start)
  46. {
  47. context->enc_free(context->enc_output_buffer_start);
  48. context->enc_output_buffer_start = NULL;
  49. }
  50. }
  51. void reset_translation(t_encoder_context *context)
  52. {
  53. context->enc_instr_pos = 0;
  54. }
  55. static long read_input_data(t_encoder_context *context, byte *mem, long amount)
  56. {
  57. if (amount <= context->enc_input_left)
  58. {
  59. memcpy(mem, context->enc_input_ptr, amount);
  60. context->enc_input_left -= amount;
  61. context->enc_input_ptr += amount;
  62. return amount;
  63. }
  64. else
  65. {
  66. long bytes_read;
  67. if (context->enc_input_left <= 0)
  68. return 0;
  69. bytes_read = context->enc_input_left;
  70. memcpy(mem, context->enc_input_ptr, context->enc_input_left);
  71. context->enc_input_ptr += context->enc_input_left;
  72. context->enc_input_left = 0;
  73. return bytes_read;
  74. }
  75. }
  76. long comp_read_input(t_encoder_context *context, ulong BufPos, long Size)
  77. {
  78. long bytes_read;
  79. if (Size <= 0)
  80. return 0;
  81. bytes_read = read_input_data(
  82. context,
  83. &context->enc_RealMemWindow[BufPos],
  84. Size
  85. );
  86. if (bytes_read < 0)
  87. return 0;
  88. /*
  89. * If no translation being performed for this file
  90. */
  91. if (context->enc_file_size_for_translation == 0 ||
  92. context->enc_num_cfdata_frames >= E8_CFDATA_FRAME_THRESHOLD)
  93. {
  94. context->enc_num_cfdata_frames++;
  95. return bytes_read;
  96. }
  97. encoder_translate_e8(
  98. context,
  99. &context->enc_RealMemWindow[BufPos],
  100. bytes_read
  101. );
  102. context->enc_num_cfdata_frames++;
  103. return bytes_read;
  104. }
  105. static void encoder_translate_e8(t_encoder_context *context, byte *mem, long bytes)
  106. {
  107. long offset;
  108. long absolute;
  109. ulong end_instr_pos;
  110. byte temp[6];
  111. byte *mem_backup;
  112. if (bytes <= 6)
  113. {
  114. context->enc_instr_pos += bytes;
  115. return;
  116. }
  117. mem_backup = mem;
  118. /* backup these bytes */
  119. memcpy(temp, &mem[bytes-6], 6);
  120. /* overwrite them with 0xE8 */
  121. memset(&mem[bytes-6], 0xE8, 6);
  122. end_instr_pos = context->enc_instr_pos + bytes - 6;
  123. while (1)
  124. {
  125. while (*mem++ != 0xE8)
  126. context->enc_instr_pos++;
  127. if (context->enc_instr_pos >= end_instr_pos)
  128. break;
  129. #if defined(_X86_)
  130. offset = *(long *) mem;
  131. #else
  132. offset = (long) (
  133. ((ulong) mem[0]) |
  134. (((ulong) mem[1])<<8) |
  135. (((ulong) mem[2])<<16) |
  136. (((ulong) mem[3])<<24)
  137. );
  138. #endif
  139. absolute = context->enc_instr_pos + offset;
  140. if (absolute >= 0)
  141. {
  142. if ((ulong) absolute < context->enc_file_size_for_translation+context->enc_instr_pos)
  143. {
  144. if ((ulong) absolute >= context->enc_file_size_for_translation)
  145. absolute = offset - context->enc_file_size_for_translation;
  146. #if defined(_X86_)
  147. *(ulong *) mem = (ulong) absolute;
  148. #else
  149. mem[0] = (byte) ((ulong) absolute & 255);
  150. mem[1] = (byte) (( ((ulong) absolute) >> 8) & 255);
  151. mem[2] = (byte) (( ((ulong) absolute) >> 16) & 255);
  152. mem[3] = (byte) (( ((ulong) absolute) >> 24) & 255);
  153. #endif
  154. }
  155. }
  156. mem += 4;
  157. context->enc_instr_pos += 5;
  158. }
  159. /* restore the bytes */
  160. memcpy(&mem_backup[bytes-6], temp, 6);
  161. context->enc_instr_pos = end_instr_pos + 6;
  162. }