设为首页收藏本站官方微博

汉化资料 [第4波]幽魂系列汉化的有关资料

[复制链接]
查看: 2820|回复: 6
打印 上一主题 下一主题

[汉化资料] [第4波]幽魂系列汉化的有关资料

跳转到指定楼层
楼主
发表于 2009-11-18 23:56 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

[第4波]幽魂系列汉化的有关资料

本帖最后由 shane007 于 2021-1-2 13:56 编辑 ( d7 w* q# a7 J3 Q' k: v, Q
: w( p' @) ?  v4 @) U" i$ C* M
最近找到了一些和幽魂系列Phantasmagoria 有关的资料,
# B4 l6 e% ~( m) S* u* g, t也许将来可以用于汉化。7 o; `) H- n9 ^9 b/ f' T
2 o0 I4 t. P; s
和日文版有关的信息
) o* s- y3 D  {' i/ S6 ^http://anthonylarme.tripod.com/phantas/phintgtp.html
  D9 h( w/ e- k1 r
, ?. F4 c8 d8 p' t+ L1 ^相关工具7 \# h$ z9 Q  d- d2 t
http://anthonylarme.tripod.com/phantas/phcheats.html
* V, T& i, P4 _6 L8 r6 o" ?-----------------------------------------------------------------------" B$ a' J2 M- [- x5 t  f& @  B$ w
2012/1/2  更新5 g' Z& `1 U9 h- u, x
关于幽魂游戏的字幕" I  ~1 `; A3 T& W
Phantasmagoria subtitles function discovered - ScummVM :: Forums
2 x( J5 h$ I6 b# E1 e; c( V/ H0 G) ?  l5 P
VMD文件0 h0 E: Q8 \+ L1 n
Subtitling Sierra VMD Files | Breaking Eggs And Making Omelettes (multimedia.cx)VMD - MultimediaWiki
! _5 k+ `5 `0 O8 Y- d% F. m! F' {
. l& S, v# r& W6 x, G3 M9 Y9 Q' k字幕* x0 O2 t* L$ }5 l7 G
Subtitling Sierra RBT Files | Breaking Eggs And Making Omelettes (multimedia.cx)
! S0 W5 `) W( Q; C2 K! {& r6 {6 M3 t8 J) Q2 t8 C# [+ R$ h
FFmpeg/subtitle-rbt.c at feature/VMD_encoder · multimediamike/FFmpeg · GitHub
2 a6 P$ s: w. R$ T/ R, [
  1. /*
    " V1 z, a! n9 L( _' J% h
  2. * subtitle-rbt.c% v6 k7 @. Y5 a: X3 ^
  3. *  by Mike Melanson (mike -at- multimedia.cx)
    ! E) _% \5 j. y, K! `+ B7 f
  4. */ K( K7 U. G2 G* A9 f6 A
  5. * build with this command:
    8 i( S4 G9 f3 r% ?! v5 O9 c) a/ m9 g
  6. *   gcc -g -Wall subtitle-rbt.c -o subtitle-rbt -lm -lass
    * I+ K" E8 }( R4 J$ D6 {& |
  7. */
    % z& x# s3 `/ m- E$ o8 A

  8. : B3 x, X: X! `5 k6 Q* A
  9. #include <inttypes.h>- R) Z, S, W& L
  10. #include <math.h>8 t* G% B0 T* W+ h
  11. #include <stdio.h>
    ; a9 Z3 P6 e9 [0 |& }+ M
  12. #include <stdlib.h>
    # \, V$ k0 n3 Q2 E2 K
  13. #include <string.h>( X* o+ ]# r2 r8 R' H8 }

  14. ! f$ V* u6 b6 T* y$ v% V
  15. #include <ass/ass.h>2 @4 p* L/ I: c8 |% `5 F
  16. 6 V. }9 H" Q- a9 ]7 D) M; Y/ {
  17. #define LE_16(x) ((((uint8_t*)(x))[1] <<  8) | ((uint8_t*)(x))[0])
    - t; H" r9 U( m3 y; ^
  18. # Q) f5 e1 v+ ^1 e+ z+ E
  19. #define LE_32(x) (((uint32_t)(((uint8_t*)(x))[3]) << 24) |  \
    : \* F: B, U% `! |- r# P
  20.                              (((uint8_t*)(x))[2]  << 16) |  \! g' }; `) @, t9 l( Y
  21.                              (((uint8_t*)(x))[1]  <<  8) |  \
    " S* ], [& D0 J# d
  22.                               ((uint8_t*)(x))[0])  M, v7 A+ t8 p
  23. ! m" {* o; G6 `6 V/ o
  24. /*********************************************************************/7 H5 q! L; ~; }1 o4 f. l9 R* z
  25. ; g3 v1 R8 h4 P
  26. /* Bit reader stuff */
    9 {* Y) t5 z' Z$ T

  27. ' ~$ G* D. j! u0 e6 T5 b# k' \
  28. typedef struct
    * X2 G' c  v! h/ n: |6 B
  29. {* Z7 j+ d( v7 b9 [$ K% j/ j- h. ^
  30.     uint8_t *bytestream;8 C/ g+ [0 o3 U4 _3 F
  31.     int bytestream_size;
    ! U! M  C5 f; l* b( f- T% ~6 \- ]
  32.     int index;
    . {; s6 h/ \1 S0 I( |# t% w+ U
  33.     uint32_t bits;& A( ]" X$ H8 @
  34.     int bits_in_buffer;9 c# `% ~" k# e( @+ n8 h7 [
  35. } get_bits_context;( o$ d# y" C4 M2 v8 q

  36. , S  z9 H6 c$ n$ H
  37. static inline void reload_bits(get_bits_context *gb)4 a! ^2 ?7 }8 ~. r
  38. {& P* s' G' k; @( d
  39.     while (gb->bits_in_buffer <= 24)6 ^6 P) t4 b9 O
  40.     {# |, T- j8 b& C
  41.         if (gb->index < gb->bytestream_size)( k* s2 i* u: |6 _# g9 ~0 m2 B
  42.             gb->bits |= (gb->bytestream[gb->index++] << (24 - gb->bits_in_buffer));& T- L, ?1 J! P- Y  N# O0 [
  43.         gb->bits_in_buffer += 8;" H7 y+ h( T# H6 y+ e
  44.     }4 y( {9 y4 b1 P3 y0 t! {' s
  45. }
    $ j- \; z& \( }( A, @
  46. ! o' c+ l  [* y5 o: e+ f% r: _, y
  47. static void init_get_bits(get_bits_context *gb, uint8_t *bytestream, int size)3 n0 X; _' c$ t( L1 N! {
  48. {
    , e7 ~0 z3 X, }1 e2 k
  49.     gb->bytestream = malloc(size);" q; U4 P7 g) `6 C' q) e; t" F
  50.     memcpy(gb->bytestream, bytestream, size);3 @9 N8 l- F9 f
  51.     gb->bytestream_size = size;
    0 b! w6 @8 k+ O8 V$ d" P9 j
  52.     gb->index = 0;
    4 e6 i8 C: `. `2 A% h
  53.     gb->bits = 0;
    $ r* g4 ^4 B$ h8 d
  54.     gb->bits_in_buffer = 0;
    & N: a! a$ d# T) J7 ~$ |
  55. * z. Y! D  P, g0 s! E, ^" e" ^
  56.     reload_bits(gb);
    . D2 l; K% E( C! ~" g1 M
  57. }3 a* ?" k( x8 S2 @$ b

  58. - T: G& X- w& _! |6 e. [, W* X8 R& r
  59. /* read bits without consuming them from the stream */+ C4 _1 _  \# |
  60. static int view_bits(get_bits_context *gb, int count)
    ) v: b. O- i  S: c: P
  61. {  Q' f& [" C7 j3 [, K4 s
  62.     if (count >= 24)# P% k# Q9 q; t, A$ }
  63.         return -1;1 y9 P4 |5 V& b* P; N! `
  64.     if (gb->bits_in_buffer < count)0 D& B$ Z4 c/ h. Q# g
  65.         reload_bits(gb);
    8 l4 e# Y9 l2 D7 O  |' a) Q, ^0 X
  66.     return (gb->bits >> (32 - count));3 [% t. |7 O0 m) I/ H
  67. }' Z8 W3 c+ C; H% v
  68. : q' V4 `" B* U( X+ ~$ D
  69. /* read and consume bits from the stream */7 j# d7 r4 o8 e, B6 k8 l. d: o
  70. static int read_bits(get_bits_context *gb, int count)2 |! x# _! l8 L2 P. e9 k, @2 F
  71. {6 v7 I. w- b9 L4 w) ^- E
  72.     int value;
    4 v* y/ G! S+ }1 o
  73. - A/ O& S* ]& Q( n; u1 B
  74.     if (count >= 24)
    / @/ C& W5 B+ C: O/ o9 @. r
  75.         return -1;. O2 v* R/ w4 U" R/ [7 E! O

  76. 2 j! t6 a" G" s$ c4 _
  77.     value = view_bits(gb, count);/ J8 u, h. E/ w, t- g
  78.     gb->bits <<= count;. F) Z0 o+ I3 v! b* [4 A
  79.     gb->bits_in_buffer -= count;
      z+ {0 y. E1 }5 [1 n
  80. , O0 s3 X4 ~& @- L
  81.     return value;. r' u3 M( r) S. L$ X2 a
  82. }  O7 O5 l% h/ T9 V
  83. , u* d) k" B; h# Q  R) w/ S9 }+ ]3 M
  84. static void delete_get_bits(get_bits_context *gb), @' _1 T3 T- i1 R7 _& x& E
  85. {
    ( a7 f. \! ^2 a" H
  86.     free(gb->bytestream);4 |4 S: e" V7 q4 J+ h7 A  s
  87. }, x) I6 X. a  Y" P0 g6 U& g& d

  88. 1 Y3 S, h+ r+ i3 y$ Y* A2 x% c
  89. /*********************************************************************/( o# a- H9 w& x& W' U- K

  90. 4 e' Y+ |" `! m: o) G
  91. /* Bit writer stuff */: y5 I% f& D% _6 }
  92. ' z0 q0 P6 W! c1 d5 j" P% d3 a9 J
  93. #define MAX_PUT_BITS_BYTES 63000
    % w8 s5 w) f  l
  94. typedef struct
    8 s+ {' _' L5 o% z
  95. {
    6 H! X2 C' i8 V, U
  96.     uint8_t bytes[MAX_PUT_BITS_BYTES];& D/ z6 K( E$ E0 S! @: b& R
  97.     int byte_index;6 N& o, y. t, \
  98.     uint32_t bit_buffer;/ @8 {& ?9 x: d# S; _3 k  L
  99.     int bits_buffered;: _, Q" t' [+ H0 J
  100. } put_bits_context;/ ~6 X& c. f: p$ u# s- s5 W
  101. " g1 K- p8 }" d
  102. static void reset_put_bits(put_bits_context *pb)
    ) P0 b  f  L- q) v/ `
  103. {+ e1 }& i& |/ ^: E- K
  104.     memset(pb->bytes, 0, MAX_PUT_BITS_BYTES);' E8 O  Z2 P" f  P
  105.     pb->byte_index = 0;, J( l0 v' D5 A% r
  106.     pb->bit_buffer = 0;
    5 v- I- j  r0 m* B$ e
  107.     pb->bits_buffered = 0;9 L7 V2 l1 M# l  E8 o+ s
  108. }3 z! [) w# a; H# }. z4 F* v
  109. ( b; s9 I% ^7 n' ~/ u
  110. static put_bits_context *init_put_bits()
    8 S' J8 S. z! L9 L
  111. {/ u- D) Q" l- J+ J
  112.     put_bits_context *pb;
    . I8 @% u1 I* {8 t( m' O  I1 ~
  113. 2 p0 K" x5 _  K$ l
  114.     pb = malloc(sizeof(put_bits_context));
    / i' l6 E9 D! ]7 Z/ k
  115.     reset_put_bits(pb);
    ) p. U1 A4 @/ I% _) c: A- o

  116. & ]2 c2 q" f% O0 c& V9 h: R; ]' r
  117.     return pb;" F& \  i- L" `
  118. }
    ' S4 F8 A8 O* z3 q5 q7 m9 f% F7 N

  119. ' O# t$ N- B3 |* J: j9 z! i0 z
  120. static void put_bits(put_bits_context *pb, int bits, int count)
    % X  j2 O3 P' D" Z0 q
  121. {" Y# a. I* Z) @8 }! b: l
  122.     pb->bit_buffer <<= count;0 e0 K' d, {, q* y9 O
  123.     pb->bit_buffer |= (bits & (~(0xFFFFFFFF << count)));
    ) Y( ^3 V- Y5 Y, v
  124.     pb->bits_buffered += count;% X) i$ t1 a7 k; V0 Z. b
  125. 8 @% n" |! y0 f7 y& c- F
  126.     while (pb->bits_buffered >= 8)
    # A, P2 @; y" u
  127.     {2 e- ]' ^$ E! m0 y' K+ b/ |) p
  128.         pb->bytes[pb->byte_index++] = pb->bit_buffer >> (pb->bits_buffered - 8);
    ; j% g4 J. b0 |- `4 \; p
  129.         pb->bit_buffer &= (~(0xFFFFFFFF << (pb->bits_buffered - 8)));2 G/ {& m) U5 q8 Z+ C( M5 R
  130.         pb->bits_buffered -= 8;
    ' Q% k: l. X2 C. [! V
  131.     }
    , ~! T( ~5 j$ u# ?7 l
  132. ; n2 e3 ], T, }8 j, V2 q2 L
  133.     if (pb->byte_index >= MAX_PUT_BITS_BYTES)
    ( p6 [: v6 E  E! P( Q/ o  c! V
  134.     {
    # g. {! x$ Q0 ]9 j
  135.         printf("HELP! Bit overflow\n");7 I4 n6 {1 O1 I  _
  136.         exit(1);
    8 F9 t& ~, w1 r4 V* B. `
  137.     }
    3 A5 X% i: f6 c
  138. }
    # P4 P# h/ I) |4 e
  139. . z/ w9 b$ e7 V( f, ~7 a% u1 ]
  140. static void put_bits_flush(put_bits_context *pb)- G  O  G  m0 U1 `8 b
  141. {- a2 m$ x$ a- N8 D1 I7 P7 u8 W
  142.     if (pb->bits_buffered > 0)
    ( C6 D, c: l5 W8 K
  143.         pb->bytes[pb->byte_index++] = pb->bit_buffer << (8 - pb->bits_buffered);
    ( v0 R. s9 N$ x; C" }
  144. }% Z. b. F8 N0 t
  145. , ]" f+ }( c) f! U, K1 m
  146. static void delete_put_bits(put_bits_context *pb)" s/ O+ I3 B; Q# j3 S
  147. {" z; v4 g+ E" V! l# x( Z
  148.     free(pb->bytes);
    ' e% K" [, [3 L4 P' a* F1 D
  149. }% U6 ?2 X  V; m; F- i6 m
  150. % }+ f" c. J! P: w2 A, E# o) n
  151. /*********************************************************************/
    0 A- D* ~9 R) T5 H( L3 z

  152. 1 y& m" J! z( C1 O% p% A( Q/ @
  153. /* RBT functions */8 c, o" I5 a+ {+ O0 ]- [& S) b3 O
  154. 1 E9 [) g1 j; b* L4 @! ?
  155. #define PALETTE_COUNT 2567 K2 s: l, P* p+ r2 S9 O
  156. #define RBT_HEADER_SIZE 60
      ^' f0 Z% q' P7 i3 R- N" m  a
  157. #define UNKNOWN_TABLE_SIZE (1024+512)( T6 U; i7 _. n3 i8 ]! P# Z; \
  158. #define SUBTITLE_THRESHOLD 0x70
    + S3 g0 y6 G% A1 g3 o4 z* `- ~
  159. #define MILLISECONDS_PER_FRAME 100- O$ p4 j: ~2 f1 G
  160. $ I  v8 X" f, _$ O; a) M
  161. /* VLC table */
      y6 e$ z) F9 t* N  e! D0 ]% Q
  162. #define VLC_SIZE 4. |/ D$ P9 c0 ~6 I- \3 S: q3 J3 K# _
  163. static struct
    ! M8 ^9 T; F7 I- y- I9 d4 y
  164. {
    5 Z( c& `; D% t+ C9 z, ^6 S+ q
  165.     int count;
    2 B. f$ A6 {: i
  166.     int value;& e6 R2 i1 x# j* ^" B1 S* q
  167. } lzs_vlc_table[] =
      \! Y7 p* x( U$ `7 |* @
  168. {/ a! ~: [, A  a3 r) \/ |
  169.     /* code length = 2 bits; value = 2 */" b- P) m% _- Y- ~( [7 A
  170.     /* 0000 */ { 2, 2 },: {/ y0 o' W9 C5 T3 J; G8 v, L
  171.     /* 0001 */ { 2, 2 },
    " ~4 t% m3 S. p, L
  172.     /* 0010 */ { 2, 2 },0 k% J$ F& G. ~3 u# }& ~# y
  173.     /* 0011 */ { 2, 2 },  d( P: Y* w6 ]+ b* H
  174. % i# r3 E. K! _0 H# n9 Y
  175.     /* code length = 2 bits; value = 3 */) b( t, l" e9 Y
  176.     /* 0100 */ { 2, 3 },3 |* I. O# F- h0 y" I2 |& u
  177.     /* 0101 */ { 2, 3 },( b: k2 w; k1 s% Q# |/ e
  178.     /* 0110 */ { 2, 3 },
    3 E# {; i% f+ C
  179.     /* 0111 */ { 2, 3 },
    7 i) u$ I& s" }
  180. 2 z) @, F2 g* O# w1 R* j3 w
  181.     /* code length = 2 bits; value = 4 */
    3 g2 V) H+ D" g# R
  182.     /* 1000 */ { 2, 4 },2 O% d- h  {$ w, m
  183.     /* 1001 */ { 2, 4 },
    1 p4 Q2 ^  B& {7 q/ R- M) h# T) y
  184.     /* 1010 */ { 2, 4 },
    , }6 s3 }, {. @2 l. k
  185.     /* 1011 */ { 2, 4 },# O7 O+ X+ X5 k  T( \# L2 S
  186. 5 z# E. \5 W5 p+ d) g
  187.     /* code length = 4 bits; value = 5 */
    0 z$ M; K$ a4 j  N2 q0 O! k2 O
  188.     /* 1100 */ { 4, 5 },
    1 C' p5 D& ]! O
  189. 8 p  ~, g: L7 E/ G& f7 I5 n  K  @0 k
  190.     /* code length = 4 bits; value = 6 */: O% q3 b+ _6 I- u/ [+ F
  191.     /* 1101 */ { 4, 6 },
    1 {/ k6 I' P% |2 F( D1 \; ^. _
  192. - S# A8 _4 A6 g
  193.     /* code length = 4 bits; value = 7 */
      D  j2 d2 u6 t6 I# m/ w% s% `& a
  194.     /* 1110 */ { 4, 7 },
    ) h7 }/ f! P( M3 k! p

  195. 8 C0 T" D( {' m
  196.     /* special case */
    9 h3 h+ ?6 E* E
  197.     /* 1111 */ { 4, 8 }
    1 L5 b  u7 e  Y
  198. };
    * v4 P8 t- R+ ^3 n2 s

  199. / U; n) f3 b8 o
  200. typedef struct2 V/ u' z' X& o/ N4 ^
  201. {
    ; ^/ V9 ]2 g) x& i7 T- D. O! T
  202.     int version;
    2 Y( Z3 J+ C' ^) b! f
  203.     int width;  \/ u: ?! U; T# P: l! M7 s; m
  204.     int height;' |9 x# o, R) A3 X4 a. h
  205.     int frame_count;
    , s5 H9 P$ u. P3 j7 ?
  206.     int audio_chunk_size;
    $ W# }9 t5 D* [& s7 S; {7 Z
  207.     uint8_t palette[PALETTE_COUNT * 3];
      D! m: z; C5 p  G) f
  208.     off_t video_frame_size_table_offset;- F& W5 ^5 r' |/ A* ?. p/ a& G7 c
  209.     uint8_t *video_frame_size_table;
    % v, c; k1 v1 T7 T! j7 h, n- ~1 i0 Q
  210.     off_t frame_size_table_offset;
    & `1 q: i  |" h+ Z/ i) l
  211.     uint8_t *frame_size_table;8 Y2 E4 `* m' a" [
  212.     uint8_t *frame_load_buffer;
    ) @* M3 Q1 \) y3 `
  213.     int dump_frames;. d- ^, ^; z$ x

  214. 9 n7 \5 d2 }+ l' R; u% N
  215.     /* subtitle library */
    8 {( g* f, p$ o! n
  216.     ASS_Library *ass_lib;
    ( i3 g: w* ~8 Z! c0 h# U5 l7 B! Z0 x
  217.     ASS_Renderer *ass_renderer;2 s( F) u! q* x. A7 _
  218.     ASS_Track *ass_track;
    % p3 ?2 t3 d8 |, T: B4 e' x/ ]. s
  219. } rbt_dec_context;
    ; B. F9 D5 K/ ~" p; t- h, _

  220. * W! s$ w. R* a- B" b& w0 z* Q
  221. static void dump_pnm_file(char *filename, rbt_dec_context *rbt,
    / C$ X4 f1 G6 U: e& a4 Y, j0 ^5 `; T
  222.     uint8_t *image, int width, int height)
      B% Q  g/ k/ V( q' f
  223. {
    , {5 ?. y7 f. z/ L1 W: }
  224.     FILE *outfile;0 n. p$ y4 g! I6 C6 g1 J
  225.     uint8_t bytes[3];7 u! O0 ^: q9 D8 J! W4 `5 |
  226.     int p;1 c5 [4 \/ ]' U
  227.     uint8_t pixel;8 [" u: Q$ i  ?
  228. $ R( P& a/ K/ ?
  229.     outfile = fopen(filename, "wb");( b% X0 \( N$ g) r# h
  230.     fprintf(outfile, "P6\n%d %d\n255\n", width, height);/ i/ K4 y5 m* D4 u7 n" ~0 l3 x
  231.     for (p = 0; p < width * height; p++)
    . w+ {1 h# S: U/ K3 Y2 s0 d* y
  232.     {
    ; i; d; {. P; {2 ]  ^: O
  233.         pixel = image[p];
    * }5 e5 s/ \& E% ~# W* C; {, G
  234.         bytes[0] = rbt->palette[pixel*3+0];
    5 @* s& }3 s9 _% T
  235.         bytes[1] = rbt->palette[pixel*3+1];
    ; j+ P5 L( }) }- E( [
  236.         bytes[2] = rbt->palette[pixel*3+2];
    5 K0 B2 n8 h0 d- b3 J
  237.         fwrite(bytes, 3, 1, outfile);* L- y  t! Q1 k
  238.     }
    ) X1 x' I: K3 [2 p# o! H7 I: y' N
  239.     fclose(outfile);, ~$ K9 b) o% _
  240. }
    0 g7 T% c) k! ?: ^6 r

  241. 0 r2 c( ]) T+ t# m9 _& M
  242. static int load_and_copy_rbt_header(rbt_dec_context *rbt, FILE *inrbt_file, FILE *outrbt_file)
    7 F/ y1 f! C; n& M4 m
  243. {3 _$ a3 U6 D" z: E
  244.     uint8_t header[RBT_HEADER_SIZE];
    1 p6 T0 I+ c; @0 G% E! C
  245.     int palette_data_size;
    6 u! G9 j; O: v1 }! [' O9 v
  246.     uint8_t *palette_chunk;& {/ g2 t9 x' D2 N: e. N
  247.     int unknown_chunk_size;
    3 w8 P6 y2 u5 s7 p+ a; Y
  248.     uint8_t *unknown_chunk;/ @6 U* X" z! x9 V/ \' T- [. t3 ~. ~
  249.     uint8_t unknown_table[UNKNOWN_TABLE_SIZE];5 C) N% T, Q$ A% E, g6 W
  250.     off_t padding_size;
    " x9 m- W: Q, l1 W! F* r* K0 i
  251.     uint8_t *padding;
    % X1 A. L3 B  |; |6 U
  252.     int i;
    0 S' c/ N3 a1 S0 i. v
  253.     int frame_size;
    ; Z& y+ Y" U% J: G- z7 G
  254.     int max_frame_size;6 E* J$ L6 l0 Y' g3 Q- _; w1 @
  255.     int first_palette_index;6 t5 T& _1 b( O5 \2 \6 _
  256.     int palette_count;
    7 S* @: |/ G* [) ]- t, u
  257.     int palette_type;
    * k0 v1 G& b4 `* o. Q2 h
  258.     int palette_index;
    " K. W9 m3 z+ q

  259. ' V6 X1 G' \& |. v, S- r; o* A2 c
  260.     fseek(inrbt_file, 0, SEEK_SET);
    7 w$ H/ x0 S* \, F$ C
  261.     fseek(outrbt_file, 0, SEEK_SET);( C, O! R! a0 f) T( P! X# J" n# _
  262. . n- h: Y2 F  }5 [9 u4 `4 {/ r
  263.     /* load the header */& D$ B$ Q; H/ k$ c& J+ T2 a; G
  264.     if (fread(header, RBT_HEADER_SIZE, 1, inrbt_file) != 1)+ g; a& j9 _4 S2 B
  265.     {
    4 A1 B, w0 v: }! B6 O
  266.         printf("problem reading initial RBT header\n");% m! L+ W. }0 S0 Z
  267.         return 0;4 }9 b0 ~9 W* E- v8 _- u6 g
  268.     }& ]( d9 I6 I0 `
  269. & y6 R& @0 k& t0 r. i6 t
  270.     /* copy header to the output */9 O3 _0 _& P0 S6 a; c
  271.     if (fwrite(header, RBT_HEADER_SIZE, 1, outrbt_file) != 1)
    * K0 C- d# Y* v. c* ^/ {5 h
  272.     {+ j$ ?3 o  }' n) p8 K0 v! M6 Z
  273.         printf("problem writing initial RBT header\n");
    ' C  L( _6 w& {4 V
  274.         return 0;# R, y. l" X. @; m5 P# Y
  275.     }
    6 K* e( B' p& N1 p
  276. 2 a* m: }4 b7 \  |8 q* W" c5 A
  277.     rbt->version = LE_16(&header[6]);
    5 S7 s: _# P% [# _! L# d
  278.     rbt->audio_chunk_size = LE_16(&header[8]);8 I9 r) P2 z5 R: B, `
  279.     rbt->frame_count = LE_16(&header[14]);: V1 i2 q( P7 N2 Y5 G3 D( u) h/ d

  280. & I, e. f( \0 T( i
  281.     /* transfer the unknown data, if it's there */( z3 A4 }* [) W4 I" E0 k' s( O' F
  282.     unknown_chunk_size = LE_16(&header[18]);
    ! g! ^* n7 K* \, F+ F3 Z/ _
  283.     if (unknown_chunk_size > 0)
    8 E* v, ?( n* B
  284.     {3 }: k  ]- O1 {- J2 L0 L/ I% ~! j  `
  285.         unknown_chunk = malloc(unknown_chunk_size);1 N3 u7 n1 F4 r7 `/ b+ a" m
  286.         if (fread(unknown_chunk, unknown_chunk_size, 1, inrbt_file) != 1)
    ( D" h  _, v7 t
  287.         {
    # r5 b5 q! ^% g  _& U
  288.             printf("problem reading unknown data\n");! g8 T4 I* Q, I+ S. O
  289.             return 0;4 C+ \+ `/ H; v
  290.         }
    ; v3 `: U  I0 K
  291.         if (fwrite(unknown_chunk, unknown_chunk_size, 1, outrbt_file) != 1)
    % t0 L* i' F$ I1 `$ I# I
  292.         {
    2 j0 N) U7 r; H$ z. `* g" q. F4 l0 M6 z
  293.             printf("problem writing unknown data\n");- v/ j' I' K6 ]6 c6 Z6 c6 ~
  294.             return 0;
    . G- v" C, v7 P/ m/ j% i
  295.         }
    7 Z" J) _0 A7 [6 ]
  296.         free(unknown_chunk);
    " X6 m6 O( f$ ^$ r1 `# S* @, Q. u6 Y: J. C
  297.     }
    6 A7 v0 a6 |( y; y7 I4 a  a+ H
  298. 7 S  l$ |. F( e9 u. v, Q
  299.     /* transfer the palette chunk */1 a: d/ P- p6 w5 B8 W
  300.     palette_data_size = LE_16(&header[16]);
    $ y  O- |" |7 Y2 [% F( e! H! A
  301.     palette_chunk = malloc(palette_data_size);
    0 q) z4 ?  S9 j: ]; S* ~+ e$ S
  302.     if (fread(palette_chunk, palette_data_size, 1, inrbt_file) != 1)
    ) B7 b6 l# Y# V, [% p+ Q) Z  M" _( d
  303.     {" A5 {+ D# D2 z& i6 Y+ n/ ^
  304.         printf("problem reading palette\n");1 J. w! q  B3 }$ g) N  O: g
  305.         return 0;- b- ^. \, h' Z
  306.     }
    + x' B; B. D' Q- Y& }" n
  307.     if (fwrite(palette_chunk, palette_data_size, 1, outrbt_file) != 1)
    $ p1 \, F5 O& `! n+ T& G1 Y4 ?
  308.     {
    , Y- h% ^1 f& R1 E2 o' I) S
  309.         printf("problem writing palette\n");) K8 @8 Z9 P* D2 P
  310.         return 0;0 Q- l7 |7 o. }9 p3 }
  311.     }  b5 X  r) N" P4 c' k
  312.     /* load the palette into the internal context */
    ! I' n0 ~+ N* E: M- q0 F
  313.     memset(rbt->palette, 0, PALETTE_COUNT * 3);
    . j* h" E0 J  l5 d7 L9 d
  314.     first_palette_index = palette_chunk[25];: U( c* \  V7 l: H( z
  315.     palette_count = LE_16(&palette_chunk[29]);$ S$ ~, T1 v+ X0 {4 ~: A9 z
  316.     palette_type = palette_chunk[32];
    . k2 V+ E0 P7 y
  317.     palette_index = (palette_type == 0) ? 38 : 37;$ T1 K! b$ ~+ t) j$ v9 Z
  318.     for (i = first_palette_index; i < first_palette_index + palette_count; i++). r$ A! z5 F5 x: K7 o5 K0 l) H
  319.     {
    8 Q0 l. {, l) `* S7 ?+ S
  320.         rbt->palette[i*3+0] = palette_chunk[palette_index++];' ~! _/ M1 J4 o# n
  321.         rbt->palette[i*3+1] = palette_chunk[palette_index++];% s2 ]$ x+ z2 L/ m1 O3 y3 l
  322.         rbt->palette[i*3+2] = palette_chunk[palette_index++];$ i- ]8 Y! F5 Q0 W3 Z" t
  323.     }
    * r( n# d2 `: g, |0 Z
  324.     free(palette_chunk);+ K" W( F' R( `4 J' U
  325. * h" G0 g. W2 }- B1 ^
  326.     /* copy the video frame size table (2 bytes per frame), as a placeholder */
    2 l5 e! X7 _( H. O9 a4 M7 u
  327.     rbt->video_frame_size_table = malloc(rbt->frame_count * sizeof(uint16_t));. u* s4 o8 D5 c; n5 W
  328.     if (fread(rbt->video_frame_size_table, rbt->frame_count * sizeof(uint16_t), 1, inrbt_file) != 1); z% @1 E5 S, d. v
  329.     {* z  U% s' l2 U$ a7 d* f& [
  330.         printf("problem reading frame table\n");
    9 G9 }: C  P3 v- D5 E) D
  331.         return 0;. w7 C; Y2 P: R$ j5 Y% ?
  332.     }. N$ V7 V. v: s' K' i) ^* I+ Z
  333.     rbt->video_frame_size_table_offset = ftell(outrbt_file);
    # `; y8 k" Y/ P1 L9 D. L
  334.     if (fwrite(rbt->video_frame_size_table, rbt->frame_count * sizeof(uint16_t), 1, outrbt_file) != 1)/ x4 a; \: D, L0 W8 P$ c
  335.     {
    $ b" e' n0 W! q) d# @# ~
  336.         printf("problem writing frame table\n");6 ^$ D9 y( a) U+ x/ g
  337.         return 0;/ y! u6 h. b8 a1 g% [5 B
  338.     }- U( _% I3 p9 @& {' e
  339. # W( r% m$ M6 M; y
  340.     /* copy the frame size table (2 bytes per frame), as a placeholder */( y3 m2 g  s. t/ M, h
  341.     rbt->frame_size_table = malloc(rbt->frame_count * sizeof(uint16_t));2 f( p0 c  c( ~( w, H
  342.     if (fread(rbt->frame_size_table, rbt->frame_count * sizeof(uint16_t), 1, inrbt_file) != 1)" f! X& d- f: R6 H  J' ~" T
  343.     {
      T* j$ ~# t" c# b$ D3 F1 g" q
  344.         printf("problem reading frame table\n");) H* [$ B! [+ U( p5 m) n
  345.         return 0;7 b& {' M# ?9 _' F" V
  346.     }5 p$ ]" W# z4 }6 `6 P+ _
  347.     rbt->frame_size_table_offset = ftell(outrbt_file);
    : |  [: l* _( J4 k/ T& i9 S0 q& d5 V
  348.     if (fwrite(rbt->frame_size_table, rbt->frame_count * sizeof(uint16_t), 1, outrbt_file) != 1)8 \% g; d& O/ G) g7 e- t
  349.     {' G! H( v, k- H2 @
  350.         printf("problem writing frame table\n");
    / P* R1 J+ x9 d* W
  351.         return 0;
    ! ?4 m$ U, L9 O9 d  ?, j1 z
  352.     }
    2 `. I/ B" R- r, U. t
  353. / _8 A! u/ _8 {
  354.     /* find the max frame size */* I$ _2 t0 Z. U- G1 ^
  355.     max_frame_size = 0;, ~; ?9 K, J* M1 [
  356.     for (i = 0; i < rbt->frame_count; i++)
    0 E  N1 c& t* H( W, A4 y$ c3 g
  357.     {
    ' B, B% p8 j$ \0 C- F* M
  358.         frame_size = LE_16(&rbt->frame_size_table[i*2]);% I( i. m7 n# @) y+ W, t' n
  359.         if (frame_size > max_frame_size)6 o  f$ c) M) i3 I
  360.             max_frame_size = frame_size;
    5 ^- z" ?, j2 E+ \
  361.     }
    6 v- J, Z5 Z. [- o
  362.     rbt->frame_load_buffer = malloc(max_frame_size);
    8 P+ u; j1 |$ }+ v& Q* T4 [8 q) k

  363. & T3 B* M: @0 X- j) E" g3 N& \6 N
  364.     /* transfer the unknown table(s) */2 t0 {  @! M" M( c
  365.     if (fread(unknown_table, UNKNOWN_TABLE_SIZE, 1, inrbt_file) != 1)# s, W1 L, `1 V9 ]( o1 @
  366.     {
    . Z( C, W+ l0 c  S' x
  367.         printf("problem reading unknown table\n");1 |: G7 I1 l, S/ K
  368.         return 0;) }2 D+ @' N3 b/ L0 ]+ z
  369.     }3 Z( K; p- E1 y) D! x* L
  370.     if (fwrite(unknown_table, UNKNOWN_TABLE_SIZE, 1, outrbt_file) != 1)
    + {4 o5 A# R9 a
  371.     {
    / h, J# q# E7 L5 F
  372.         printf("problem writing unknown table\n");
    / h, {5 K1 T) M5 `: t5 T
  373.         return 0;
    ' ]$ s' O; u( E  Q
  374.     }) m6 d# Z- k0 A& Z( [
  375.   q  `: Z& l4 j/ G) y5 P+ k( ?% _
  376.     /* copy over padding */# _! n  k9 i& u* \) p; o1 [
  377.     padding_size = 0x800 - (ftell(inrbt_file) & 0x7FF);' U( h3 L. y) c" n% B7 R7 B
  378.     if (padding_size)
    6 K; k1 f& q5 `9 Q
  379.     {
    , j9 {5 p& i& `0 U# B: K
  380.         padding = malloc(padding_size);
    ! o, c2 M* I' F8 H" `# |
  381.         if (fread(padding, padding_size, 1, inrbt_file) != 1)6 h3 ]6 a* L4 x
  382.         {2 [9 }: Q8 m0 `! S0 d8 _) W! H
  383.             printf("problem reading padding\n");0 ?" |' X3 v+ g  H" Y/ G4 n
  384.             return 0;  T( c: e4 ]2 M$ @
  385.         }
    ! Y$ I1 k1 F. S0 A% L
  386.         if (fwrite(padding, padding_size, 1, outrbt_file) != 1)3 |. m/ C9 B+ `0 p  R' ^3 A+ e: f
  387.         {
    " h+ V4 F4 A: ~, x- p
  388.             printf("problem writing padding\n");7 Y4 }, w: x' {" ?1 y" ^6 I/ r7 a
  389.             return 0;
    / K2 h6 c" g# f$ w1 o0 F4 p, x, N
  390.         }
      i3 \1 v6 Z! ?  h0 j: U3 `
  391.         free(padding);
      }4 C+ X! u% S5 j' o  k; ~
  392.     }/ o$ u+ }: i+ G. ~5 u

  393. / C# L6 c( a- @1 t1 O
  394.     return 1;- }+ o$ h7 Y$ J, M& q. M) ]6 x/ t
  395. }
    7 _! H( k; Q% }9 n+ m. N9 M9 V

  396. 4 M7 o. Q! _3 x% L5 G2 B2 R
  397. static int get_lzs_back_ref_length(get_bits_context *gb)  z' `$ \; L4 C' D# V( Z
  398. {
    & _7 ]$ l+ h8 i# _/ c
  399.     int vlc;# `" P9 a+ A% z* o- t4 `
  400.     int count;  ^2 P2 ^' T6 }- D1 |: H$ Q) x
  401.     int value;5 f) D5 J4 J, U# N0 o# `& Y) e

  402. 1 i1 K) M4 z% I, _3 C
  403.     vlc = view_bits(gb, VLC_SIZE);
    3 i. M& M5 h; t; F2 g. X
  404.     count = lzs_vlc_table[vlc].count;
    $ S. t, ^( {- L5 ^" o1 ~6 j
  405.     value = lzs_vlc_table[vlc].value;
    6 v& J% ]7 r* s

  406. 0 q) W, c2 ~5 e5 F$ D7 s" S
  407.     read_bits(gb, count);
    ' l! Q$ |) z* x
  408.     if (value == 8)
    - K! M3 p2 O2 |! l2 J
  409.     {
    % x! e$ j( L: ]( a$ {: X' X
  410.         do
    - A# V( n( M4 R6 Q: a
  411.         {
    1 Y( c9 n" x) A) c9 x$ |
  412.             vlc = read_bits(gb, VLC_SIZE);
    1 K  S  E% T1 a" x1 W0 [
  413.             value += vlc;
    ! h& l. g1 ]5 b' d9 \" ?
  414.         }
    ; l- l$ v1 S' A6 Z6 _+ A& a
  415.         while (vlc == 0xF);
    9 H2 P& T, g  i% ^
  416.     }- z2 P! i( J3 M+ y8 v* e
  417. 4 o+ Y2 }9 P) i8 ?
  418.     return value;$ b: t0 v7 `5 L7 E7 P; Y. r0 P! h
  419. }
    ' V; g9 [& w5 K! a( L* t
  420. # z3 X9 }; f6 F$ ]9 \2 G$ y
  421. static void compress_window(put_bits_context *pb, uint8_t *full_window,- S  @! t" X' B- ]  n! D7 I
  422.     int full_window_stride,
    9 D* M- ^- l$ n& O6 u& |: Q
  423.     int window_top, int window_bottom, int window_left, int window_right)4 s+ X& u2 e3 f2 k2 l' p
  424. {1 u" L  `1 F; F: b
  425.     int last_pixel;
    5 y4 T& X+ t1 S# Y6 {
  426.     int run_size;# i2 X5 F7 p! g4 |4 O% \8 O  S
  427.     int x;' Z- x% u( w; \, j2 v
  428.     int y;$ @$ R0 V  v! J2 J) p/ R: |- V* _. X
  429.     int start_index;  H1 ]! G; g% G" D: s: U0 @( V
  430.     int end_index;
    8 ^" ^- m- ?' p* a$ a& ]# q0 ^
  431.     int encode_last_run;2 @  J( H" r/ u- F, k" i/ y+ Z
  432. & _: a6 N8 W, D3 x  c
  433.     last_pixel = full_window[0];) n) ?+ w& e. ~, f" K
  434.     run_size = 1;
    $ X. ]# u& i4 T. r3 K
  435.     for (y = window_top; y <= window_bottom; y++)8 c/ ^- K( n2 c9 Y
  436.     {
    5 |7 V6 e) H* ^) F2 i( N; ^
  437.         start_index = y * full_window_stride + window_left;: B& Q- G" f' f: L  y% Z. {( \) O# t  a
  438.         if (y == window_top)
    $ G( ]& l6 T. I( \7 j/ X$ M) U8 o
  439.             start_index += 1;5 {" k' [( \$ N
  440.         end_index = y * full_window_stride + window_right;( U3 e' x# `! o( u' d: V- {
  441.         if (y == window_bottom)! P. l2 V! V5 a+ k( M& N, L) T
  442.             encode_last_run = 1;5 U( w* q0 n# I
  443.         else) C4 o2 s1 ?' V+ l4 p& {, p% Y+ U$ a
  444.             encode_last_run = 0;# E0 X% k! t) k' U7 g6 j
  445.         for (x = start_index; x < end_index; x++)
      A: \, C4 U: y8 Q9 _9 h& B
  446.         {
    4 ^9 v: e5 e4 y8 R! z' A# L2 B1 C
  447.             if (!encode_last_run && full_window[x] == last_pixel)
    4 {# L- {2 H. g+ p; y
  448.                 run_size++;
    8 g2 c% v! i0 v
  449.             else
    & J7 i9 c+ c; i, E! h
  450.             {. p; B6 J* h  H- K% L
  451.                 if (run_size == 1)
    7 R; \( P/ s# V1 J7 O: Z
  452.                 {7 g( q) b! s+ d) V4 B$ J
  453.                     /* encode a 0 bit followed by raw pixel byte */8 ^' ^8 `" p- J; s4 y
  454.                     put_bits(pb, 0, 1);$ l2 |* _7 z1 J0 m6 x
  455.                     put_bits(pb, last_pixel, 8);, _$ M3 b  o$ F+ }; X
  456.                 }* w  b7 ?" X! i) v8 A6 ~2 t: b5 o
  457.                 else if (run_size == 2)0 Z$ Q5 L3 M" @8 Y# o9 h
  458.                 {- [9 g+ L8 q' k
  459.                     /* encode a 0 bit followed by raw pixel byte */
    0 g) n$ d. c, P; O1 |7 s$ i1 e
  460.                     put_bits(pb, 0, 1);  u. L5 O! i! ?2 {$ N
  461.                     put_bits(pb, last_pixel, 8);
    7 W( E# `6 U9 P0 F2 o* p$ g
  462.                     put_bits(pb, 0, 1);
    1 |+ b2 M) `4 E) d
  463.                     put_bits(pb, last_pixel, 8);
    7 i! r/ n: b  o
  464.                 }
    ) V8 }- n( k7 r# h) r" J
  465.                 else/ G* `8 }8 X1 N( k5 T
  466.                 {
    + T& M3 U4 a# Y( {5 U$ \
  467.                     /* encode a 0 bit followed by raw pixel byte */, N& c% v/ @9 _! w! W
  468.                     put_bits(pb, 0, 1);
    9 t; N9 s2 M; v
  469.                     put_bits(pb, last_pixel, 8);
      w  U' k- M* e
  470.                     run_size--;
    ( U7 g) `: T7 R
  471.                     /* encode a run: a 1 bit, followed by a back reference
      O9 K9 e  ~: s5 E
  472.                      * offset (-1), followed by a length */# ?4 Q  r( t0 u
  473.                     put_bits(pb, 1, 1);
    , \8 ~( i* l6 [2 B- y0 Y  V
  474.                     put_bits(pb, 1, 1);  /* 1 = 7-bit offset */
    * n7 \* |( ?8 B5 I7 V; K
  475.                     put_bits(pb, 1, 7);
    # T5 A+ ^' w! l# n
  476.                     if (run_size <= 4)
    5 b0 d* k- m: n0 r& |
  477.                     {
    , I8 ^  I4 q9 s* r1 O0 {! a
  478.                         /* lengths 2, 3, and 4 are 2 bits */
    2 m) _1 o6 \4 ]
  479.                         put_bits(pb, run_size - 2, 2);
    % P( J8 Q* ?& \7 Y' n
  480.                     }
    / Y1 S% C. \/ `+ H( V- Y2 K
  481.                     else if (run_size <= 7)! ]& q4 B7 ~6 U: v  a& N9 [
  482.                     {( g) }9 U# d: A5 ]% Z
  483.                         /* lengths 5, 6, and 7 are 4 bits */
    4 Q$ P" v/ }8 \/ I5 B/ X5 }2 A
  484.                         put_bits(pb, run_size + 7, 4);6 o3 U, j2 {/ t# u1 Y' `
  485.                     }
      g0 k) Z- o* Y! T2 G0 r7 w  @
  486.                     else5 x" C; @& M1 ?. F, j
  487.                     {
    6 y2 Y8 g1 t: b
  488.                         /* arbitrary length; start by encoding 0xF which
    0 p* c* Q6 L- H% z  }; ?
  489.                          * stands in for an initial version of 8 */
    ! h& C; L7 u# Z3 l* [" L, W' ~0 a/ y
  490.                         put_bits(pb, 0xF, 4);6 D* l4 ]& W7 \8 ^$ u5 ?7 O/ }
  491.                         run_size -= 8;% S" Z: r- B( w$ c' b7 L: e
  492. # y5 r7 O; l4 Y; q* C
  493.                         /* encode blocks of 4 bits until run_size is 0 */  Y4 I# c. ]) Y% B
  494.                         while (run_size >= 0)! m- M5 M2 B  v: [! N, p. }7 x
  495.                         {. Z3 n3 Z/ Q, q
  496.                             if (run_size >= 15)" }; i1 ^) ~# M# X# L6 \
  497.                             {
    ' u4 l8 k8 B; Q' ?2 A! O5 @7 n' C
  498.                                 put_bits(pb, 0xF, 4);
    ; l8 C* M! u! ]" q7 M: l* b
  499.                                 run_size -= 0xF;
    - W* S2 V0 {  n' Q
  500.                             }6 J2 H/ X& o  ~
  501.                             else
    % a# u. G5 \5 h4 U
  502.                             {
    " {3 t8 H/ h6 |0 x
  503.                                 put_bits(pb, run_size, 4);
    0 n% d9 {( k" {
  504.                                 run_size = -1;. Q4 E' [/ L2 O, M/ Z% p3 ^
  505.                             }
    7 ?/ N8 d- ^1 D& w$ K# Z
  506.                         }% q. I: M" Q1 {# s
  507.                     }
    * z; `/ V5 P- M
  508.                 }! n: D- N- H2 X/ ~

  509. & J4 U: Z. x+ R: Z: x2 g/ e
  510.                 last_pixel = full_window[x];
    ( d4 I: J- b& H7 c1 h* q) A
  511.                 run_size = 1;$ r5 g' I2 E1 M, R

  512. ( Q% r4 j2 q$ |! ^4 q
  513.                 /* this single x iteration was only here to close the final run */8 J( j' t4 O* C
  514.                 if (y == window_bottom); S+ l! R4 W7 T% b+ A  W) r, _
  515.                     break;
    1 _' S% X% u9 w5 \* J) ^, e
  516.             }5 r1 J" E' ?1 z1 K
  517.         }" z, S( B- b" m
  518.     }
    % h& D* ~8 b, {0 ]& Q. |# O

  519. & h7 S8 O7 N* O
  520.     /* close the bitstream by encoding a back reference with length 0 */
    0 {# n/ i' O5 p1 i' n
  521.     put_bits(pb, 1, 1);  /* back reference run */" ^/ u6 n/ ]+ P2 z
  522.     put_bits(pb, 1, 1);  /* 1 = 7-bit offset */
    6 A( g' L9 E5 p" U: |1 G: V0 o
  523.     put_bits(pb, 0, 7);  /* length 0 */: j: o% [  P% E. v( \; \
  524. 7 R0 m! E# {7 d
  525.     put_bits_flush(pb);9 W8 u) K! z2 m* r/ f- i/ `4 I
  526. }
    ! Z* U+ g. q+ k6 {# y- ?1 p

  527. # B3 C3 ]2 }$ ?0 S4 z; s
  528. /* compute Euclidean distance between an RGB color and the desired target */
    3 V# F/ W  v+ U& U! t1 ^/ T
  529. static int compute_rgb_distance(int r1, int r2, int g1, int g2, int b1, int b2)
      Q5 A/ N) [! \# }$ F4 }% N
  530. {9 i. u" ?, x1 T
  531.     return sqrt((r1 - r2) * (r1 - r2) +
      e- {+ x6 p" ]' P1 T  m
  532.                 (g1 - g2) * (g1 - g2) +
    : ^3 D- b( Q2 T5 V1 U: q
  533.                 (b1 - b2) * (b1 - b2));1 e7 g5 d, @- }* {0 C4 T8 t
  534. }! O  r, t/ o: ]/ m# c

  535. 4 K; q. e( y* Z- y: c; N7 N
  536. static uint8_t find_nearest_color(rbt_dec_context *rbt, int r, int g, int b)
    : M* s6 B* Y, h2 v& d
  537. {
    ' [4 B' J* l- k
  538.     int i;" F1 o  d/ P) g( C3 U' z
  539.     int nearest_distance;. `7 Y# G' z2 W6 _
  540.     int distance;- ], z9 D) z7 Y, E
  541.     int rp;
      V1 @% H$ b; w  A! e7 [0 y
  542.     int gp;
    2 h  I7 t& Z9 N1 Q9 i$ z! b3 S  F
  543.     int bp;
    / J9 t/ J1 \! s* [4 i1 M' P  W7 r, l+ G
  544.     uint8_t palette_index;6 X+ y7 v  T+ o( N( c" r# O6 b

  545. " e9 z8 ]& V6 k2 \- F5 X
  546.     nearest_distance = 999999999;
    - K& k4 m: _9 c. u& t
  547.     palette_index = 0;$ h# y% t5 Q. _/ ]
  548.     for (i = 0; i < 256; i++). b1 y! `, g; R. S! ?1 V; b
  549.     {
      M9 ^! B/ G3 }$ u4 S7 |" \6 p' z
  550.         rp = rbt->palette[i * 3 + 0];' X1 X% M5 o5 ?% `, p; P
  551.         gp = rbt->palette[i * 3 + 1];  M, I. a, l$ b( H
  552.         bp = rbt->palette[i * 3 + 2];3 m) h: z4 b/ m% y. W, Q
  553.         distance = compute_rgb_distance(r, rp, g, gp, b, bp);
    : s# I  h' L( q- z0 o  |
  554.         if (distance < nearest_distance)
    ! k( ]& ~$ F2 a; C1 v
  555.         {! s# J9 U, b; _* l/ B
  556.             nearest_distance = distance;
    ; {) f1 U! t/ M2 Y9 B
  557.             palette_index = i;9 L3 l7 l) h2 j1 c, i* C* \
  558.         }! p6 b" {! o% E& ?; y; b6 l4 z/ j
  559.         /* can't get closer than 0; break early */) N' f6 i4 [6 j+ I" u4 f+ r
  560.         if (distance == 0)
    3 U& L# I/ `% L/ F
  561.             break;  F4 k8 G  j# M+ M! @; Q
  562.     }( M& _, y6 I) \5 ]1 n. k
  563. 9 r% Y1 B, L  f/ {5 p
  564.     return palette_index;& \0 A- e: s! ]: J% b
  565. }
    ! I1 A& r  M" ^* l& T: M: `

  566. ; L6 S2 B9 W1 C* z) u: Q4 ]
  567. static void subtitle_frame(rbt_dec_context *rbt, uint8_t *frame,
    3 X5 x* Z  ~) z' i, \
  568.     int width, int height, int timestamp)
    " v- b$ B6 @, i: k1 K5 X
  569. {
    % z! ~9 v& d2 I( _; Z
  570.     ASS_Image *subtitles;
    ) k9 E4 d6 ~( \  A
  571.     int detect_change;
    . r! E0 a( y& e
  572.     uint8_t subtitle_pixel;
    1 T$ B. {7 l: P
  573.     int x, y;& B% z+ A7 {5 [" Y2 v# H
  574.     uint8_t *frame_ptr;
    * |! M$ ~' z* D/ d# A, j
  575.     uint8_t *subtitle_ptr;" h  o: t9 v3 V9 t5 `; L) M: h
  576. 7 I( u6 Z& N$ \- k+ b" r4 u6 R
  577.     /* ask library for the subtitle for this timestamp */
    1 i- e. I& T  U  M
  578.     subtitles = ass_render_frame(rbt->ass_renderer, rbt->ass_track,
    / Y* N: S/ w, L5 u3 h
  579.         timestamp, &detect_change);
    ; c1 f7 N* o; m- ]& f: W: W

  580. / P4 c8 w/ ]2 d2 F8 e
  581.     /* render the list of subtitles onto the decoded frame */
    ; r+ t/ ^; u6 F" B3 y* `! n. p
  582.     while (subtitles)
    0 q1 J% e1 J# h+ [4 G9 R% c
  583.     {
    % l: d1 J; T# `
  584.         /* palette components are only 6 bits, so shift an extra 2
    4 E9 G' U: M: ~& m6 r+ N, U
  585.          * bits off each component */
    & j& K7 K; f+ R0 D0 J. e% r
  586.         subtitle_pixel = find_nearest_color(rbt,
    + n% y7 d% a. m; P6 x
  587.             (subtitles->color >> 10) & 0xFF,& b3 B, j' Y- l- l
  588.             (subtitles->color >> 18) & 0xFF,
    0 g" u6 ]* n$ y7 I  V
  589.             (subtitles->color >> 26) & 0xFF);. A6 v7 e: P' ]9 D$ K* {
  590.         for (y = 0; y < subtitles->h; y++)0 p3 X7 G6 ^+ y, S6 v
  591.         {2 e) f( g% q, b. T1 c' K9 F$ F
  592.             subtitle_ptr = &subtitles->bitmap[y * subtitles->stride];% m) t# g9 @; E5 `
  593.             frame_ptr = &frame[(subtitles->dst_y + y) * width + subtitles->dst_x];4 P$ C- s; l# w6 s
  594.             for (x = 0; x < subtitles->w; x++, frame_ptr++, subtitle_ptr++)
    : ~1 p+ S& {2 r+ d) O; x6 O
  595.             {
    * [1 J$ I. M4 F' a5 {# B
  596.                 if (*subtitle_ptr >= SUBTITLE_THRESHOLD)! X, z8 ~/ e3 V  \# }9 c
  597.                     *frame_ptr = subtitle_pixel;2 B* V" p- D8 O$ N9 I. V! [- p, U1 j/ l
  598.             }6 n+ B! `* n7 X' C; D+ h$ h3 G4 v
  599.         }4 r6 l5 c- \- o, a% ^. P' h% T9 y
  600.         subtitles = subtitles->next;
    5 C* Z! u- t& N- q2 k) C6 j) O0 D! h: R
  601.     }
    9 [" O' g7 }' Q
  602. }* O- }: |& \+ a+ K4 q4 a* s5 e/ A

  603. 0 X) v. U. M5 m0 f$ {' ~. V
  604. static int copy_frames(rbt_dec_context *rbt, FILE *inrbt_file, FILE *outrbt_file,
    - ~: }* V2 W3 J1 u9 k1 k
  605.     int origin_x, int origin_y, int window_width, int window_height)6 X: B  d( J) \
  606. {
    - ?$ |4 C1 ?& x  n" F  R
  607.     int i;
    2 L5 {& R  Q; {9 R9 o) J9 b/ r& W  C
  608.     int j;) X" `" M& t0 e% g
  609.     int scale;; l; c. p0 x6 [7 V+ i
  610.     int width;
    # g, Y' o) o7 ~8 T
  611.     int height;
    9 {; E6 n8 l4 q. O' E
  612.     int max_width;
    7 Q4 C3 B3 X" I9 W2 U
  613.     int max_height;
    ; |% W, Y8 v# _3 a/ @/ U
  614.     int frame_x;
    , x4 H9 {' c: n' N  y# ?
  615.     int frame_y;
    3 k5 b9 g1 u7 w) [
  616.     int fragment_count;, |* Z  u  _  E! b* e
  617.     int decoded_size;
    1 d  L, H; u) ^& P! S# H
  618.     uint8_t *decoded_frame;7 r. z3 e) }- W  `; M
  619.     int fragment;
    # [/ H2 n: a# f, k2 N5 l
  620.     int fragment_compressed_size;9 w2 }! c5 P( t( P* u3 V: ?9 z- x
  621.     int fragment_decompressed_size;
    7 C7 X# }1 [' L( @# _+ N: w- z
  622.     int compression_type;/ c3 L& n0 H" k3 W
  623.     int index;8 Z1 h" R* Q* ~  D. k1 F
  624.     int out_index;4 H0 x* ^# v4 g5 M
  625.     get_bits_context gb;
    3 j. a6 }; i0 q
  626.     int frame_size;
    $ R: Q8 p3 q! E  q" g) f( y
  627.     int video_frame_size;7 A) W0 s0 c5 P/ N' `
  628.     int audio_frame_size;
    ( f) V5 K3 e. R; A+ A6 l
  629. 8 R% T& s* O: x9 v8 l9 G/ h7 I
  630.     int back_ref_offset_type;, P* A# H& _5 O' ?/ E( m
  631.     int back_ref_offset;
    0 q% h4 x- `. s6 H
  632.     int back_ref_length;
    % `3 W7 v6 I  Q4 k2 m' j! `; s
  633.     int back_ref_start;
    , v) m' |1 |% ?1 y& z' Q
  634.     int back_ref_end;& E7 K+ G* ^3 o% }

  635. + I: s$ l7 r' o' A' `9 [
  636.     uint8_t *full_window;9 \! V" o' F+ s  |2 ?/ L% D
  637.     int full_window_size;' X9 C: G! J8 {# E) r# ]& A- G
  638.     int y;$ N/ i# W8 \5 q- [2 Q& _
  639.     int window_top;7 d# S/ d8 P) t) m* y/ R
  640.     int window_bottom;
    0 K( b8 a( c! J; d# ?5 t0 B5 A
  641.     int window_left;
    * d8 x9 {8 U9 u6 _! X
  642.     int window_right;3 e' i) [. ]1 J/ Z+ F) a
  643.     int window_size;
    0 [& x1 z& y. O& l* o

  644. ( N" r* e+ J; j+ J7 Y
  645.     char filename[30];6 s. j  f: F1 b- d9 M+ b

  646. " a$ @2 U  k! I0 n+ o
  647.     put_bits_context *pb;7 ?& N9 s# ~$ G* v8 D

  648. 5 e+ I2 c. d; N1 S
  649.     full_window_size = window_width * window_height;" Z% T% ^% O6 l, |! {6 U- y
  650.     full_window = malloc(full_window_size);
    0 v, q* h6 m' ~7 _
  651.     pb = init_put_bits();
    - g: O9 ]$ N2 U. U0 R. M
  652. 2 l. E% K& M1 [( i8 \; ^- C
  653.     max_width = 0;6 @6 N. ?0 n7 G
  654.     max_height = 0;
    & J. b3 _1 K5 T: g2 G8 l3 D
  655. / p; [" {& f: z( K, W1 O( m
  656.     for (i = 0; i < rbt->frame_count; i++)6 A$ Y) @- R* s% e+ n+ `# ]) M
  657.     {
    1 u+ ?$ ]0 [& I; L4 d* {
  658.         /* read the entire frame (includes audio and video) */
    : A+ V. d! n. o1 F& d. W
  659.         frame_size = LE_16(&rbt->frame_size_table[i*2]);) @- I; s8 r; g: l- C( R
  660.         video_frame_size = LE_16(&rbt->video_frame_size_table[i*2]);2 H1 W5 @4 U2 S! N
  661.         audio_frame_size = frame_size - video_frame_size;
    7 R3 z" T$ m) P4 w4 G: o
  662.         if (fread(rbt->frame_load_buffer, frame_size, 1, inrbt_file) != 1)
    9 d* k! J" ?$ d
  663.         {5 z3 Q" g$ ~) a8 G% ^
  664.             printf("problem reading frame %d\n", i);7 L. o" o4 \( l# ~" B0 }
  665.             return 0;
    ' p7 Y- Q- K* z
  666.         }! S, f" L* n; m) d
  667. * r. _5 c% ~) g: a: x
  668.         scale = rbt->frame_load_buffer[3];
    4 n7 g7 n8 Q9 b/ D% s
  669.         width = LE_16(&rbt->frame_load_buffer[4]);
    5 ^' K7 p* z5 \! i4 y3 }( U
  670.         if (max_width < width)
    / J1 q5 @+ T$ o# J
  671.             max_width = width;; o& m6 Y% p. b  o' ^8 `& U- b0 P
  672.         if (max_height < height)
    5 p' i. H8 J2 ?' K' K, }
  673.             max_height = height;
    2 d) A6 X$ f) e& }
  674.         height = LE_16(&rbt->frame_load_buffer[6]);
    ! Y, c6 @! m) v+ G& ^- M( o2 P
  675.         frame_x = LE_16(&rbt->frame_load_buffer[12]);, Q/ H, y  `" Z! Y
  676.         frame_y = LE_16(&rbt->frame_load_buffer[14]);
    + I( l/ E( ^/ l2 G" x
  677.         fragment_count = LE_16(&rbt->frame_load_buffer[18]);# q: g0 ~, J$ V! C4 I
  678.         decoded_size = width * height;
    6 P" |1 J2 g5 c) }! G/ i7 V6 w, @( m
  679. ! V. O, W' U8 M7 N
  680.         printf("processing frame %d: %d%%, %dx%d, origin @ (%d, %d), %d fragments\n", i, scale, width, height, frame_x, frame_y, fragment_count);3 q% U4 I: d2 G  i" b- ^$ y& k
  681. % {8 E! l) q  y; C) y2 k, ^" o
  682.         /* decode the frame */- c# l" t4 _; J4 P2 a. k
  683.         decoded_frame = malloc(decoded_size);
    & O1 g% o! Y1 X# @* U2 a! D
  684.         index = 24;
    9 o( `& G/ a9 W
  685.         out_index = 0;9 X$ N, k: Y/ W$ ^( o9 A  E
  686.         for (fragment = 0; fragment < fragment_count; fragment++)
    4 Z4 A0 I' b) T) M0 h  o7 {' s+ J
  687.         {
    ; @4 j2 {- C& Z( ^
  688.             fragment_compressed_size = LE_32(&rbt->frame_load_buffer[index]);2 d! a9 S9 E# f+ {
  689.             index += 4;; `; x8 |( R0 x+ t$ U
  690.             fragment_decompressed_size = LE_32(&rbt->frame_load_buffer[index]);' j9 |* t; S) W% ~( t
  691.             index += 4;/ i2 ?6 m4 ?. Z& g, A' [
  692.             compression_type = LE_16(&rbt->frame_load_buffer[index]);
    / Z( Y& M0 m% R/ x: y4 V5 v  K3 \
  693.             index += 2;
    9 r& g: `3 E  W& `1 C: W

  694.   r+ j6 s+ L. e3 X& O/ y
  695.             if (compression_type == 0)2 F4 c% L* f* f2 U5 x: V1 b) O
  696.             {) F& I# A/ ^# c  ^, R$ ^
  697.                 init_get_bits(&gb, &rbt->frame_load_buffer[index],: K; {& R" E) X  {! A: i. I! n
  698.                     fragment_compressed_size);4 h: ^+ \& n1 A% E2 {0 h$ X% |% @0 E
  699. + v* Y" }' j# |, }# ^
  700.                 while (out_index < fragment_decompressed_size)9 i0 [2 y3 N# e* u
  701.                 {
    ) P2 A  d5 G: m9 H* A/ }  `! A. w
  702.                     if (read_bits(&gb, 1))
    " f  x+ x$ I% x, s# z% l& m
  703.                     {
    0 q! |' Q4 Q2 M# |3 P
  704.                         /* decode back reference offset type */5 M7 K- I1 h& ]6 d2 V2 m
  705.                         back_ref_offset_type = read_bits(&gb, 1);' }% T( F+ I: j# K; p
  706.   z/ m0 g9 V1 d4 _( Q
  707.                         /* back reference offset is 7 or 11 bits */6 g$ n# O5 v1 h# l
  708.                         back_ref_offset = read_bits(&gb,- E9 ]; c, e' g) h, {9 \2 |
  709.                             (back_ref_offset_type) ? 7 : 11);4 M3 }, e; l( c. c

  710. 8 d  i0 J4 i! Z* T
  711.                         /* get the length of the back reference */
    1 K1 h9 `- ~' {4 i( F5 D, X0 X8 \
  712.                         back_ref_length = get_lzs_back_ref_length(&gb);# f6 q, S; C9 F
  713.                         back_ref_start = out_index - back_ref_offset;3 h  Z3 u: u1 `* P# J
  714.                         back_ref_end = back_ref_start + back_ref_length;# |0 J8 o- u3 e  M
  715. . K% Z- F2 S: D/ ]; U- `0 j
  716.                         /* copy the back reference, byte by byte */
      U! x! ^% `. Y7 G' d. U
  717.                         for (j = back_ref_start; j < back_ref_end; j++)
    ( f% u+ S+ S" F, j9 n" C$ G
  718.                             decoded_frame[out_index++] = decoded_frame[j];7 Y( ^/ F: w* g' j8 c- E- c' }
  719.                     }
    ( I8 T0 [) o2 e3 {' c
  720.                     else; F# x1 O  F9 _2 u4 `- Y
  721.                     {8 i) g' u' O4 O. U* d
  722.                         /* read raw pixel byte */
    4 g; H/ ~3 V0 O3 n  w" |
  723.                         decoded_frame[out_index++] = read_bits(&gb, 8) & 0xFF;9 u0 {0 {( {7 x* B* W2 x) ~: f
  724.                     }7 R7 r5 Z: C, |& s3 l5 q) D
  725.                 }
    " v: O& f3 s/ ^# @  q% {2 O

  726. # p6 a& ]1 Q% i. ?% Y5 k7 ^: r. D" B
  727.                 delete_get_bits(&gb);
    . G& T4 R# a1 m' }2 @2 P
  728.             }7 i* Y, _4 O5 z/ ?: m- q5 V0 y
  729. . N2 F$ y. }8 P  d; \$ w
  730.             /* next fragment */
    7 e. F5 S: X' U# s8 e% d; K
  731.             index += fragment_compressed_size;
    2 c* X# B1 m8 t& \' N* C8 K8 P
  732.         }- t- T1 Z6 {' }( j( f7 {8 K
  733. 2 W- z: E8 p0 P2 l, t2 F4 H
  734.         if (rbt->dump_frames)
    ' E6 N! Y" N; U- _- k9 F
  735.         {6 N- ~7 C5 I1 N, X. L  Z0 T6 ~
  736.             /* dump the original frame */, i% J5 |! K: z8 u0 f2 d$ i0 x
  737.             sprintf(filename, "original-frame-%03d.pnm", i);
    % J3 M+ Q3 \2 }% C5 T# o* V" [2 O- o
  738.             dump_pnm_file(filename, rbt, decoded_frame, width, height);! W" P5 [! H; j
  739.         }
    * T" S3 |, P& E* a( U) h
  740. - k2 t2 P; u$ M$ N6 s! L0 i( ~
  741.         /* transfer the image onto the frame window */
    8 t- B8 G- @* e# q6 W/ T
  742.         memset(full_window, 0xFF, full_window_size);
    6 U9 \% g) d% T
  743.         index = 0;
    / P; K# q3 _$ V
  744.         for (y = 0; y < height; y++)4 n# \4 w+ @7 Q5 g: B6 X. x
  745.         {9 Y2 c, X/ C7 u+ v6 I
  746.             out_index = window_width * (frame_y + y) + frame_x;
    * s* S! W. D/ Z* s
  747.             memcpy(&full_window[out_index], &decoded_frame[index], width);
      D% H" p: C# D. R) W# O" x
  748.             index += width;
    ; E) L, c9 U4 B$ i$ o8 F
  749.         }
    2 }% G5 s3 M- A/ @7 j

  750. , B' u5 a% D) e; n1 s0 [
  751.         /* write the subtitle */% v7 G- w8 {1 p4 O+ I
  752.         subtitle_frame(rbt, full_window, window_width, window_height,
    - A$ ?6 f+ u' g; T
  753.             i * MILLISECONDS_PER_FRAME);# L$ y6 X" c" w* v$ s
  754. ' x& a" x- G. V+ Y
  755.         /* figure out the smallest change window */
    + \+ u. K2 y) D! d( f* X" n
  756.         window_top = frame_y;
    * w* U* A( B5 R. C, A, G
  757.         window_bottom = window_height;
    ' \# C' P. r/ j& B' K
  758.         window_left = 0;
    * f5 p) d, y4 I* ?2 U2 p
  759.         window_right = window_width;- M1 N: D6 l+ T+ w) V0 t+ K0 n9 O6 n" h
  760.         window_size = (window_right - window_left) * (window_bottom - window_top);0 _; \: F5 o( ]) f1 y. R
  761. 9 V0 }" c( F5 Q4 D5 }5 s; g
  762.         /* compress the frame */" S+ a- T. f# [, S
  763.         reset_put_bits(pb);
    2 @& H3 h7 Y3 Z, l) g
  764.         compress_window(pb, full_window, window_width, window_top,# q& O6 ?7 D7 |+ ]& H( l* ?5 B4 \* Q3 A
  765.             window_bottom, window_left, window_right);; G& g9 Z! z) P, z. y! m% m

  766. 0 ]- k& T3 Y2 R& S8 Y
  767.         if (rbt->dump_frames)
    " E7 w: V7 v) `( Z) M
  768.         {. [8 b7 W' p) `' W3 x
  769.             /* dump the frame plotted onto the full window prior to encoding,
    # m' r- ^+ l% V, }
  770.              * with subtitle */, h( J1 P7 d8 L8 Q& V7 n
  771.             sprintf(filename, "pre-encoding-frame-%03d.pnm", i);6 L: e, T% H% g( h# l
  772.             dump_pnm_file(filename, rbt, full_window, window_width, window_height);0 `  T5 L6 G0 b' q
  773.         }) n8 u8 k/ x5 U: {
  774. 7 v- Q9 i7 P) F) l1 n0 Q9 m% `4 q4 r7 ~
  775.         free(decoded_frame);" F, h$ ]/ ^- Y/ d5 @

  776. 9 E1 o) s2 W  ~8 e
  777.         /* update the frame header */4 [/ m2 d- @" t( O% P0 I
  778.         /* width */
    1 \+ q3 [9 b0 o
  779.         rbt->frame_load_buffer[4] = (window_right - window_left) & 0xFF;. s* Z0 B! G- w& j: I
  780.         rbt->frame_load_buffer[5] = (window_right - window_left) >> 8;
    / l+ o$ B* C2 V) ~
  781.         /* height */+ c0 ~" c& K/ o
  782.         rbt->frame_load_buffer[6] = (window_bottom - window_top) & 0xFF;
    . V# H9 [7 f8 s
  783.         rbt->frame_load_buffer[7] = (window_bottom - window_top) >> 8;; G/ v. n0 E! a* H8 X/ v+ M  i
  784.         /* origin X */' I: w+ O( `8 A9 w: n
  785.         rbt->frame_load_buffer[12] = window_left & 0xFF;
    * W! p" X3 i* [2 e/ x, Z3 F* Z
  786.         rbt->frame_load_buffer[13] = window_left >> 8;* K, \2 `* W/ t7 Y# K' P
  787.         /* origin Y */
    # }6 c' B+ M! l  v+ f3 D9 V$ B
  788.         rbt->frame_load_buffer[14] = window_top & 0xFF;$ M8 H% n8 g* h
  789.         rbt->frame_load_buffer[15] = window_top >> 8;
    . j: u( L" F1 F0 G( j
  790.         /* fragment payload size */# ]7 j2 c0 O8 l. _. {. q
  791.         rbt->frame_load_buffer[16] = (pb->byte_index + 10) & 0xFF;. M. }: d5 o' c. w3 ]
  792.         rbt->frame_load_buffer[17] = (pb->byte_index + 10) >> 8;
    6 S8 O2 g2 |# ^  r! V% c$ K/ B
  793.         /* fragment count (1) */
    ' o/ T7 o5 ]7 Z. I4 {% D! U( J9 W
  794.         rbt->frame_load_buffer[18] = 1;
    * m+ @' R4 Y5 T& G3 T! B" X
  795.         rbt->frame_load_buffer[19] = 0;
    - e4 K& a: v( l6 `& K/ w1 x+ L

  796. / [$ M5 [$ V7 B/ y: X" A( O
  797.         /* update the fragment header */4 w3 H5 l  k  F& @: _, ~- I* V
  798.         /* compressed size */
    * n6 o" [5 L5 G) V
  799.         rbt->frame_load_buffer[24 + 0] = (pb->byte_index >>  0) & 0xFF;
    ; S* L8 ~4 k# D% I1 J: O1 Z8 F
  800.         rbt->frame_load_buffer[24 + 1] = (pb->byte_index >>  8) & 0xFF;! F, G& Q3 K  d. H
  801.         rbt->frame_load_buffer[24 + 2] = (pb->byte_index >> 16) & 0xFF;
    $ w5 c) K  ]& k& ~# Z) q. n
  802.         rbt->frame_load_buffer[24 + 3] = (pb->byte_index >> 24) & 0xFF;
    $ e+ `- q2 N5 |  Q1 X, }3 B/ H
  803.         /* decompressed size */
    9 z1 }# g/ D6 }
  804.         rbt->frame_load_buffer[24 + 4] = (window_size >>  0) & 0xFF;  M9 s: a: i5 Z& B6 `+ \
  805.         rbt->frame_load_buffer[24 + 5] = (window_size >>  8) & 0xFF;/ [# b! \$ k& {# v& d3 Q
  806.         rbt->frame_load_buffer[24 + 6] = (window_size >> 16) & 0xFF;8 |1 [; {0 q5 |7 u  G" p2 Q$ s
  807.         rbt->frame_load_buffer[24 + 7] = (window_size >> 24) & 0xFF;2 S, a6 ~" O! X# ~3 [7 I4 ^$ T
  808.         /* compression format 0 */
    0 a' T( z# }1 @4 R
  809.         rbt->frame_load_buffer[24 + 8] = 0;5 f+ O5 T9 q9 s  W8 y+ W: R
  810.         rbt->frame_load_buffer[24 + 9] = 0;3 N1 ]$ I% D5 V! R( [; J
  811. & e# L+ f; Q5 O7 w( s2 \0 n2 S
  812.         /* write the 24-byte frame header and the 10-byte fragment header */; ~3 l& G; C8 S8 u, k- ]
  813.         if (fwrite(rbt->frame_load_buffer, 24 + 10, 1, outrbt_file) != 1)
    5 Y9 o- F% c! y- g
  814.         {
    1 E! T" ^5 Q% i
  815.             printf("problem writing frame %d\n", i);9 C( H% X! _0 q" w$ ~4 n; b6 ^
  816.             return 0;! T* [+ _$ N! V6 P4 j- N' t
  817.         }, t- `0 Q- U; S  f
  818. * `& @$ X: X; [# X) y4 A2 ?0 |
  819.         /* write the new compressed frame data */7 z) O# y1 n% ~+ [) {- k4 r( ?% c1 f! C
  820.         if (fwrite(pb->bytes, pb->byte_index, 1, outrbt_file) != 1)
    8 N% S1 y. G$ w1 C& n5 n
  821.         {
    ( N, N* p' b: a, K
  822.             printf("problem writing frame %d\n", i);: ^, b' K8 B: j/ E
  823.             return 0;
    / B2 z+ N6 W3 V1 K& S% K" }
  824.         }
    7 k# B% B* j; M/ A3 c
  825. . b; i7 r9 J- x& Q- i- {& h" R. r: \
  826.         /* write the audio data */
    - n2 V2 d- o4 [6 K
  827.         if (fwrite(&rbt->frame_load_buffer[video_frame_size], frame_size - video_frame_size, 1, outrbt_file) != 1)6 t1 a$ e' _8 X
  828.         {
    : G9 b. U9 ~: r$ W7 _9 Z8 x
  829.             printf("problem writing frame %d\n", i);
    5 b8 ~& ?9 d6 f$ P; Y
  830.             return 0;
    * x+ m4 u6 X' `" z7 W! j
  831.         }
    ) t/ z/ R5 g: `2 s- f6 I! e

  832. / [. `' d2 x9 j5 G* r0 a
  833.         /* update the table entries */
    2 ?! J$ \% _. o+ h" `. m" F
  834.         video_frame_size = pb->byte_index + 24 + 10;
    % I2 I9 h  A: N, `
  835.         frame_size = video_frame_size + audio_frame_size;
    ) U) _; o& K% v; t) q
  836.         rbt->frame_size_table[i*2+0] = frame_size & 0xFF;- U2 H: F# a4 u3 Q, J" g& I
  837.         rbt->frame_size_table[i*2+1] = frame_size >> 8;
    0 h6 B. o6 d6 I; u, c, `+ C
  838.         rbt->video_frame_size_table[i*2+0] = video_frame_size & 0xFF;; J( A" d' }$ b, `; |# w$ u
  839.         rbt->video_frame_size_table[i*2+1] = video_frame_size >> 8;
    6 x, a! J7 p) _! K# \
  840.     }
    3 c% a9 V. v/ Y  A

  841. % ^* s% j  r: [8 R
  842.     printf("maximum dimensions seen are %dx%d\n", max_width, max_height);7 Y# k# R5 E. e0 A1 W. z
  843. $ n( A  f0 L3 E& r8 Z: D) s
  844.     delete_put_bits(pb);
    $ E# E/ I% y( q% v1 B. b
  845.     free(full_window);
    , w+ |( X  b6 a

  846. * l* `, }7 l( l) e
  847.     return 1;4 s5 e2 ], G9 w3 V
  848. }3 p- q% z/ }0 Y! L
  849. " W  g- t+ C2 j
  850. int main(int argc, char *argv[])- y9 x, b& E# H; o$ M
  851. {
    ' H' r7 m4 o' h( Z
  852.     char *subtitle_filename;
    ( i# k% x0 E/ `* y; Y9 s( {
  853.     FILE *subtitle_file;% \2 U$ T/ w8 Y" y$ V
  854.     char *inrbt_filename;! T: O. ]. w4 e' Z! `, Z
  855.     FILE *inrbt_file;
    ' ]9 G8 a: ]4 L% K1 U0 i! a
  856.     char *outrbt_filename;
    2 P% e# X+ ?% ^/ a: h9 U
  857.     FILE *outrbt_file;& W3 ?: d& K2 V" P- _! N3 f
  858.     rbt_dec_context rbt;
    1 i; q$ R. R5 ~2 A+ d$ L
  859.     int origin_x;  A/ j7 V5 ?1 k& @% I8 I
  860.     int origin_y;( `$ y! a4 Q1 ^: }  m
  861.     int window_width;! L: b5 h; `, e) W! P
  862.     int window_height;) G- a1 q% F* }: Y# C& |# ?( G( S' G
  863.   n5 o3 B9 g. C8 B* G
  864.     /* testing the bit functions */
    9 [, x4 A1 m! H. z8 K2 B& k
  865. #if 0( ^  ^- G! J+ ]" d- A
  866.     int i;7 N% ~' Q* N: t6 L# |  o: S
  867.     uint8_t bytestream[] = { 0x55, 0xAA, 0x00, 0xAA, 0x55, 0x77, 0xFF, 0x1B, 0x70, 0x8F };4 S1 }3 g2 P# ?$ U( h
  868.     int bytestream_size = 10;  u4 P3 \, `: v$ [% b4 a
  869.     get_bits_context gb;0 A3 J. H. e& e+ ^( i0 A3 j
  870.     put_bits_context *pb;
    " d( ~, y% D4 Z9 v
  871.     int bits;
    8 m7 [9 L/ D2 S+ Y: ~
  872. + C1 J/ t- k+ m
  873.     init_get_bits(&gb, bytestream, bytestream_size);
    ; Q7 c9 I) s8 D! h; u
  874.     pb = init_put_bits();; S) C7 W3 \1 f# g/ @7 F5 ?
  875. 1 s6 [( W; Q" G  e& e* z) C
  876.     for (i = 1; i <= 12; i++)
    6 ^, f" U2 g/ y2 Q# ]& \  m
  877.     {6 i9 i+ e* O# ~/ j* c/ P' t
  878.         bits = view_bits(&gb, i);
    6 \5 q2 `! q/ B( S
  879.         printf("view %d bits: %d\n", i, bits);! E9 h' y# ~3 q4 E# t5 ]
  880.         printf("read %d bits: %d\n", i, read_bits(&gb, i));; z! x1 s' P2 ^% ^' [0 z& i
  881.         put_bits(pb, bits, i);6 k9 C- X2 J" o) k  M: ?
  882.     }/ K& A! a2 P2 _, u
  883.     put_bits_flush(pb);# n& V& V1 i. w! k9 U+ Z
  884. / p7 s1 g5 t7 n! h! X! P
  885.     printf("original bytestream:\n");3 f0 q" g; ?- _. C! T, D
  886.     for (i = 0; i < bytestream_size; i++)- g% D, N: n+ T
  887.         printf(" %02X", bytestream[i]);
    5 v! s: i; @% o0 K& E  k$ t' e
  888.     printf("\nnewbytestream:\n");) K( v  X4 Z$ [* t$ w' |; {
  889.     for (i = 0; i < pb->byte_index; i++)
    ' w7 c* [; X! W
  890.         printf(" %02X", pb->bytes[i]);; ], S+ [) _* ]: x$ @1 s
  891.     printf("\n");) ^# O. A* l5 J

  892. + m; c( I4 |, F# \6 f) Y
  893.     delete_get_bits(&gb);8 u. L; l8 ^1 i3 e# @. @
  894.     free(pb);
    - S- Q7 k8 O8 c# c  c9 S
  895. #endif; g  F) U+ l7 T: T2 N

  896. 7 ]$ K% T+ p1 k4 x, |
  897.     /* validate the number of arguments */
    $ N' Z: x; n/ k' O( G5 b
  898.     if (argc != 8 && argc != 9)% m  C/ c  w# l) y+ F
  899.     {
    9 O: F  x* E2 Z+ x. u
  900.         printf("USAGE: subtitle-rbt <subtitles.ass> <in.rbt> <out.rbt> <origin X> <origin Y> <width> <height> [dump_frames]\n");
    2 m$ |( L) P( j
  901.         return 1;
    3 Y7 @6 k$ K4 O1 ?
  902.     }- ]$ V0 Q# ?& ]7 j. Z6 p+ K
  903.     subtitle_filename = argv[1];% k7 \; _! `1 t" T1 c" v1 }% D
  904.     inrbt_filename = argv[2];
    ' j- N2 h& J; k2 I5 |$ m7 `
  905.     outrbt_filename = argv[3];
    ; ]3 R# H2 z! q, u1 a9 p
  906.     origin_x = atoi(argv[4]);
    8 ~: j  @* h3 p1 t0 ]
  907.     origin_y = atoi(argv[5]);- B: {. |7 U. o7 J0 J
  908.     window_width = atoi(argv[6]);  k; y, U' A7 ^1 W1 }3 r$ x
  909.     window_height = atoi(argv[7]);  E" y# ]& w. ^$ r3 h/ N# ?& w
  910.     rbt.dump_frames = 0;
    * V/ {' L& H5 v* W* Z; y+ \% R
  911.     if (argc == 9)1 l- l. D+ m5 Y
  912.         rbt.dump_frames = 1;; v; K5 q1 @/ J3 n: e* V  f, z( _: O

  913. ! p' \& P' q$ b  w- F- u8 J; d
  914.     /* verify that the specified input files are valid */) `4 d% t  O1 l2 y( n
  915.     subtitle_file = fopen(subtitle_filename, "r");7 Y3 {) Q) }( Y# z. r6 D; e, u  ?) x
  916.     if (!subtitle_file)& z' s+ ?7 R5 s+ l) T
  917.     {$ r& B1 d. `8 `) T
  918.         perror(subtitle_filename);
    9 s/ y' M' B) s! j
  919.         return 1;
    - O- D7 ~* @# p0 M
  920.     }# E: a& _9 ^+ u: |
  921.     fclose(subtitle_file);
    ; j( ~( D" t5 `; o
  922.     inrbt_file = fopen(inrbt_filename, "rb");7 O# M  X' B% s! u/ R0 U
  923.     if (!inrbt_file)
    9 S* f# F+ o! I/ k+ L! W( k
  924.     {( T/ J+ Y0 w6 s8 e) C  t# X5 Z
  925.         perror(inrbt_filename);; k3 c' _! O/ Z+ ?) ], O" ^
  926.         return 1;
    5 O: L0 U; ~0 ]1 x  F1 |7 e( O& a  }
  927.     }, g' w+ x/ \) _4 `8 k

  928. 5 g; h- ~3 L, q, W; \
  929.     /* initialize the subtitle support */
    ; Z% O/ w9 ]# [
  930.     rbt.ass_lib = ass_library_init();$ L& a. \+ B- q" y/ B0 i. K
  931.     rbt.ass_renderer = ass_renderer_init(rbt.ass_lib);
    . N% `$ ?. N/ B6 I% y
  932.     rbt.ass_track = ass_read_file(rbt.ass_lib, subtitle_filename, "UTF-8");
    6 u" ?8 X' B" E$ R2 g0 B! g
  933.     ass_set_frame_size(rbt.ass_renderer, window_width, window_height);
    1 D, L/ e3 U6 Z% x0 Z5 s
  934.     ass_set_fonts(rbt.ass_renderer, NULL, NULL, 1, NULL, 1);. y$ {% x5 U) D* M+ B9 I

  935. # v' H" m- ]2 i! Q8 N
  936.     /* open the output file */$ @; o7 Y" |' R1 s0 y
  937.     outrbt_file = fopen(outrbt_filename, "wb");! }, E+ O; H; h0 k! }/ a
  938.     if (!outrbt_file)
    6 P2 G3 u" V$ @& g8 ^* A
  939.     {5 o& w) l, {  A8 p
  940.         perror(outrbt_filename);$ c' @/ o- P9 Q% o0 B' s& r( F
  941.         return 1;
    : C2 W8 ?) r4 s: z' [- e2 G
  942.     }
    / o: n2 z% |4 H( K# G/ }( H
  943. ( A5 c/ E. ]$ v: P8 J. O  \, h
  944.     /* transfer header from input to output */
    % J7 R5 b: |' t0 y5 A/ J+ W  ^9 X
  945.     if (!load_and_copy_rbt_header(&rbt, inrbt_file, outrbt_file))! ~6 V/ o9 X) z# `  d9 v( `" x
  946.         return 1;1 H" _; Z' n, X- ]. j. L5 V
  947. " o  d# X# F/ G
  948.     /* rewrite the frames */
    0 I' o' n7 {! }  e+ w1 a
  949.     if (!copy_frames(&rbt, inrbt_file, outrbt_file, origin_x, origin_y,
    : X- u- C* r8 n" p
  950.         window_width, window_height))
    1 B) N/ @# U/ P3 m* J' l. q& Y
  951.         return 1;5 C* T/ n  [" s- @- b
  952. : w5 D8 O/ o+ x
  953.     /* write the modified frame size tables back to the file */
    ) k) ^# h' r3 D7 s. q
  954.     fseek(outrbt_file, rbt.video_frame_size_table_offset, SEEK_SET);
    ! q8 h7 |, x+ J* y- Z8 w* h0 h
  955.     fwrite(rbt.video_frame_size_table, rbt.frame_count * sizeof(uint16_t), 1, outrbt_file);
      ~8 X' s8 v: p" n
  956.     fseek(outrbt_file, rbt.frame_size_table_offset, SEEK_SET);  M6 A( h; |, i7 H0 H  K
  957.     fwrite(rbt.frame_size_table, rbt.frame_count * sizeof(uint16_t), 1, outrbt_file);
    7 ?+ w6 W. W5 G+ Y5 ^6 L
  958. $ q4 J: c& \! o4 \+ z
  959.     /* finished with files */
    / k6 o& ]1 c& C+ |- ]9 g
  960.     fclose(inrbt_file);
    9 ^4 ?$ J7 u3 |1 b# \# D
  961.     fclose(outrbt_file);  w1 A5 h& O; ^4 t

  962. . E# K# q3 M( x2 `: A( p4 E
  963.     /* clean up subtitle library */8 c* \6 D. S* ?' I3 p% z- B8 I
  964.     ass_free_track(rbt.ass_track);, V: G4 h8 W' H+ w8 ]7 G
  965.     ass_renderer_done(rbt.ass_renderer);
    , [/ S" [% O  C+ r3 q0 C
  966.     ass_library_done(rbt.ass_lib);8 [# n6 j% W) g4 U" z5 A( c6 m

  967.   C  Y- F- }  O! T5 w% N8 m: U# A
  968.     /* clean up */
    8 M7 w8 W& `& O+ z9 Q, y/ g: D
  969.     free(rbt.frame_load_buffer);9 E  Y- o1 {5 i
  970.     free(rbt.video_frame_size_table);
    4 C% J# c% J2 w# C" B/ k- a
  971.     free(rbt.frame_size_table);
    # ~, I/ J! p8 F# X* Y( |

  972. , t) @3 d7 j6 r! Z
  973.     return 0;9 G- x1 r+ f+ P5 @; g+ O
  974. }
复制代码
2 t  A8 o2 n1 R/ |

2 i/ u8 o0 t4 L7 m3 \- V7 X# W
3 O$ `* u: C: Q! Q8 G$ m7 Q" X! D# d& ?# @' O/ Z' S
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 很美好很美好 很差劲很差劲
回复

使用道具 举报

沙发
发表于 2009-11-19 11:09 | 只看该作者
这游戏有字幕吗?
回复 支持 反对

使用道具 举报

板凳
 楼主| 发表于 2009-11-19 11:38 | 只看该作者
引用第1楼soring123于2009-11-19 11:09发表的  :/ y: j) n' K! k* @
这游戏有字幕吗?
( Y/ ~% a2 }, P" u( Y5 c( k
好像没有字幕,我说的是给视频外挂字幕方式的汉化。
7 I) R' q- @* Y! o* L3 v就像syberia2汉化版下面那行字一样。
回复 支持 反对

使用道具 举报

地板
发表于 2009-11-19 17:07 | 只看该作者
我记得是没字幕的 比较麻烦 都是视频的
回复 支持 反对

使用道具 举报

5#
 楼主| 发表于 2009-11-19 17:39 | 只看该作者
引用第3楼soring123于2009-11-19 17:07发表的  :
0 G5 F$ A8 Z; l: [我记得是没字幕的 比较麻烦 都是视频的

, I6 d: i7 [. y( G7 o给视频外挂字幕方式汉化也许能行。. X; X) W: N- e/ z! G5 D: X
要结合dosbox和代理dll技术。
回复 支持 反对

使用道具 举报

6#
发表于 2016-7-21 23:33 | 只看该作者
求汉化啊!
回复

使用道具 举报

7#
 楼主| 发表于 2021-1-2 13:50 | 只看该作者
顶上来
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

冒险解谜游戏中文网 ChinaAVG

官方微博官方微信号小黑屋 微信玩家群  

(C) ChinaAVG 2004 - 2019 All Right Reserved. Powered by Discuz! X3.2
辽ICP备11008827号 | 桂公网安备 45010702000051号

冒险,与你同在。 冒险解谜游戏中文网ChinaAVG诞生于2004年9月9日,是全球华人共同的冒险解谜类游戏家园。我们致力于提供各类冒险游戏资讯供大家学习交流。本站所有资源均不用于商业用途。

快速回复 返回顶部 返回列表