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

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

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

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

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

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

本帖最后由 shane007 于 2021-1-2 13:56 编辑 , K; M/ k. a6 g& |! \; Y" o. b
1 n$ Z* \& ]# [9 o
最近找到了一些和幽魂系列Phantasmagoria 有关的资料,
+ l2 g: x* O8 f1 u0 F也许将来可以用于汉化。/ v3 d: H- W. S
9 `2 }, Y% c8 k( s5 X7 Q
和日文版有关的信息! k! O! d) H# ]4 d, W/ Q$ L
http://anthonylarme.tripod.com/phantas/phintgtp.html
' d3 ~" R! j$ p8 ?  p" x8 M! L1 W& s3 X$ c9 F7 l
相关工具( q8 k; K% e& W  z
http://anthonylarme.tripod.com/phantas/phcheats.html, q$ m( B: G) y/ B  E
-----------------------------------------------------------------------5 k/ }7 P+ K8 G- u0 |
2012/1/2  更新9 R: ?' j! B0 C8 e/ B4 u7 B  k6 i
关于幽魂游戏的字幕
4 m3 d. O* ]; X# k, ~( SPhantasmagoria subtitles function discovered - ScummVM :: Forums
' t) ~9 n, M# T: |7 A
. G! P( q# W" A' F( V6 aVMD文件, }: h6 }% I5 n. W7 O( @
Subtitling Sierra VMD Files | Breaking Eggs And Making Omelettes (multimedia.cx)VMD - MultimediaWiki& x$ R. s+ \8 P6 V+ u
) S1 F5 j( a1 P( {5 h) t, R- z
字幕
8 [% C% Q7 {4 j' Z# CSubtitling Sierra RBT Files | Breaking Eggs And Making Omelettes (multimedia.cx)
; o8 i/ D/ d% N4 |5 D4 Y3 z1 X& c; F% A& S
FFmpeg/subtitle-rbt.c at feature/VMD_encoder · multimediamike/FFmpeg · GitHub: ^/ m% ?, j, Y7 ~* |
  1. /*- Q; B4 a9 x# ^% v* D
  2. * subtitle-rbt.c
    , O4 W! d# F4 G# C  \$ b1 [' g" M
  3. *  by Mike Melanson (mike -at- multimedia.cx)/ \- ~$ n4 C; w, E* h6 @
  4. *0 m, U' [6 M( l7 ~3 q
  5. * build with this command:
    # u* c2 k5 t& {
  6. *   gcc -g -Wall subtitle-rbt.c -o subtitle-rbt -lm -lass. @% S6 P* s# R$ t+ e
  7. */
    & v/ ^1 }. X  P% g2 U+ S2 g

  8.   z9 [' V* v7 L( s: ]* N" v* _* y" L
  9. #include <inttypes.h>
    - M! F1 P. }* v, ^
  10. #include <math.h>
    / f+ `$ d- v7 M1 K2 j
  11. #include <stdio.h>3 L" \9 N) M- E/ ?2 P; O- c4 P
  12. #include <stdlib.h>
    : y( k9 Q4 a$ P  p6 J, ?# |
  13. #include <string.h>
    + V( N! y0 m/ o7 s) Z9 b

  14. $ `0 E4 h9 c% y* F2 i  v
  15. #include <ass/ass.h>7 S  _& h" d0 t0 p3 \8 k( m
  16. : K0 P. h( x" _; Y4 @. \
  17. #define LE_16(x) ((((uint8_t*)(x))[1] <<  8) | ((uint8_t*)(x))[0])
    9 N. [# R' C& W* ]6 B$ F

  18. " C, U% r) {. K  P; Z& Q  \
  19. #define LE_32(x) (((uint32_t)(((uint8_t*)(x))[3]) << 24) |  \
    3 _0 q( m% ]( O$ h; Q1 R
  20.                              (((uint8_t*)(x))[2]  << 16) |  \
    8 |2 E; I0 k( m5 Y
  21.                              (((uint8_t*)(x))[1]  <<  8) |  \* I% }. W- ?# V& ], Q6 j$ W8 t
  22.                               ((uint8_t*)(x))[0])/ Q8 C- I" V$ N$ N8 \4 {
  23. ; E8 [% c8 ?* x$ l( M( O/ p5 u
  24. /*********************************************************************/
    1 T; B+ C" S3 e- P

  25. , |! m2 X8 A# Z, S! S
  26. /* Bit reader stuff *// m6 e. ?+ w* D2 E

  27. $ W/ I8 M" Y! C( D
  28. typedef struct
    & @% `. i' x: Z3 g+ l- A% q
  29. {
    7 ^- q7 p7 T8 j/ ^! X' x- [; Z4 b! _& ^
  30.     uint8_t *bytestream;' @- f0 m% L/ [! p; u$ \) N
  31.     int bytestream_size;
    " D4 H  x$ N2 `" M. d* o
  32.     int index;
    . m5 d+ E( z2 Y4 R3 Y$ d. I
  33.     uint32_t bits;
    9 b' Z" x0 w9 V8 A# n
  34.     int bits_in_buffer;
    % j* `* V9 g6 K  E3 y2 T
  35. } get_bits_context;- V+ T5 ~7 V" a2 [' [2 y1 a
  36. : N' z' F# ]1 r
  37. static inline void reload_bits(get_bits_context *gb)" B0 B6 v1 n5 y9 T. [% L" c3 q5 O
  38. {
    7 Y: \7 n- b9 g! Y  G1 t* d
  39.     while (gb->bits_in_buffer <= 24)
    : b3 I0 g3 k- b, b, Y6 b
  40.     {, g1 @9 Q% I. F4 u, a
  41.         if (gb->index < gb->bytestream_size)6 Y& \" Y/ m/ \  M; j
  42.             gb->bits |= (gb->bytestream[gb->index++] << (24 - gb->bits_in_buffer));( v2 w4 V0 p, Y8 p9 l+ a
  43.         gb->bits_in_buffer += 8;
    ; B! a9 m2 O) a5 e; a6 _
  44.     }
    1 K+ Y# @% A* K
  45. }
    $ l. q( z9 P# ]4 a& ?- x1 k/ f5 x; h
  46. # u+ q4 m. j8 V
  47. static void init_get_bits(get_bits_context *gb, uint8_t *bytestream, int size)
    ' K$ a: l/ U- _. t# r% M$ v9 L2 x. h
  48. {
    , h( ]7 @7 k, p! @
  49.     gb->bytestream = malloc(size);) f  m7 W/ w  R: c
  50.     memcpy(gb->bytestream, bytestream, size);  M) X" b4 n7 u( c
  51.     gb->bytestream_size = size;$ W, V' Y! t' n1 O" I6 o' `
  52.     gb->index = 0;
    / R  u# f' i4 h+ u5 _
  53.     gb->bits = 0;) J: P! i% ^9 m
  54.     gb->bits_in_buffer = 0;
    4 }  L4 f1 {5 f7 l* n

  55. ' B. }' B4 S2 I1 s3 V1 F0 b$ Z4 ]
  56.     reload_bits(gb);/ v# }. y( L3 @8 Y* y0 Z  R
  57. }+ \, g" e5 C( ?. h+ ?
  58. 7 G! i& V' {) Y* W1 K
  59. /* read bits without consuming them from the stream */
    & Q4 `5 O3 n" r. v8 A. B
  60. static int view_bits(get_bits_context *gb, int count)7 z! U# g( K$ b. b" c$ |: s; {6 b; D
  61. {7 M' v$ c1 f- d1 L3 E/ `
  62.     if (count >= 24)# |  o8 \; c0 |3 l5 l$ V
  63.         return -1;& G! q5 v' v& b7 [
  64.     if (gb->bits_in_buffer < count)/ F7 d: N# z7 w8 O
  65.         reload_bits(gb);% l0 i1 I7 K# p- f" [" `* v5 V
  66.     return (gb->bits >> (32 - count));! I+ [$ m0 E- l$ ^$ U/ z
  67. }
    ) {5 L: J# @* D: F9 r
  68. 1 d! E  e! N) e+ c: K. k% N
  69. /* read and consume bits from the stream */$ O" c- n5 ]" g6 U" m8 N
  70. static int read_bits(get_bits_context *gb, int count)
    % g8 E. _- w8 N' j/ m! s
  71. {" [8 w. e9 h0 Q: |+ H8 U/ w
  72.     int value;- R( P0 B1 p+ S* ^4 ]0 R7 K: d

  73. 9 d( i0 m" [! o: s4 u: w: b) T
  74.     if (count >= 24)
    ; ~- c; o0 }1 z1 X1 z' J& C# Y3 ?
  75.         return -1;
    ) |, S! a4 h% V6 T' {
  76. - s" v8 V8 t  d" y
  77.     value = view_bits(gb, count);
    0 r& N$ t/ @/ K
  78.     gb->bits <<= count;
    ( x# w! }' K( G$ ^  K/ U
  79.     gb->bits_in_buffer -= count;, Z% {* n# D7 N; _* \

  80. # O- W0 v- l' d0 m' ]7 R$ x  c' H
  81.     return value;
    - v& a1 S; e! G: Q8 S9 u1 _' n
  82. }
    3 G7 a; Y4 ^/ P; r8 n$ K0 g. o: X

  83. ; G; f: ]# T' O  N& R! N' ^
  84. static void delete_get_bits(get_bits_context *gb)& r9 ^7 e* E% M6 x" @- |
  85. {
    # x1 {- E- N- U
  86.     free(gb->bytestream);3 y: C: _7 T6 i* r( \
  87. }
    ( d) ]! h' H6 Y9 o
  88. ) e8 o. _& f+ Z# t
  89. /*********************************************************************/
    9 X" s) a. f/ o: B" e- |+ A

  90. ; O7 A. F/ V: B0 s' z1 t' D+ `  x
  91. /* Bit writer stuff */
    2 R! Q' x2 Z$ r- h# w& |0 z
  92. 4 ?2 l: L  Y" X1 R, w- U
  93. #define MAX_PUT_BITS_BYTES 63000
    4 w7 e5 D5 c% X, Q
  94. typedef struct- d- M9 \5 A6 T! f  W: a
  95. {
    ( f& K" H" H# n) i; Q, [
  96.     uint8_t bytes[MAX_PUT_BITS_BYTES];
    # n, k5 I5 l* \" M  ]
  97.     int byte_index;
    9 d4 r: L" \' J5 j+ d# c
  98.     uint32_t bit_buffer;; F+ Q! c" G8 \: I3 I2 g
  99.     int bits_buffered;( @9 n; [# C8 j* x, j: Z) J9 S3 B6 y
  100. } put_bits_context;
    9 n  X/ O, Z1 m+ S/ R' K- @* x
  101. ! ]5 R9 F- P, N8 o3 h. @
  102. static void reset_put_bits(put_bits_context *pb)
    & q7 f; f+ O( P; V
  103. {& z' `+ Q! \7 W7 j5 S  x: W
  104.     memset(pb->bytes, 0, MAX_PUT_BITS_BYTES);4 m' r+ z6 u' a
  105.     pb->byte_index = 0;  C% L1 B: }* [. q! x
  106.     pb->bit_buffer = 0;! l0 X7 X" n& k# C$ j, X
  107.     pb->bits_buffered = 0;
    ; E$ A1 S5 a, i' b# C
  108. }! B' {6 J% l+ w- E- x! m

  109. 8 d4 h6 J" L% L* D
  110. static put_bits_context *init_put_bits()7 ?* A, S! c% \
  111. {/ q+ `  s( D$ \8 ?, @
  112.     put_bits_context *pb;& s) D/ Z( H2 Q, Z. j

  113. . A/ h/ `. i, _' x2 l* K) Y6 [
  114.     pb = malloc(sizeof(put_bits_context));7 ?3 ~; J! u' e( [+ ?/ z
  115.     reset_put_bits(pb);/ i, n8 W/ b. H) y! p( f

  116. 4 X1 \3 L& s+ V8 k
  117.     return pb;4 \9 x  w" o$ \6 n: o
  118. }
    $ D) J( k4 |/ n/ w: M5 @
  119. + A( `1 L3 G4 F! `- F
  120. static void put_bits(put_bits_context *pb, int bits, int count): e+ m' F" p/ `! b/ U2 y" v
  121. {+ z/ z1 X% B# H( p2 O
  122.     pb->bit_buffer <<= count;8 x, m7 z, D6 w4 {# A
  123.     pb->bit_buffer |= (bits & (~(0xFFFFFFFF << count)));6 l  @2 t2 \2 V
  124.     pb->bits_buffered += count;% B+ F4 S2 {# g+ f8 I" e8 ?6 F

  125. , Z2 G. s2 l2 Y8 q" Z! F
  126.     while (pb->bits_buffered >= 8)% r+ Z' T4 }/ j! s+ g+ K
  127.     {8 A7 n( z% {+ {3 e: y- w
  128.         pb->bytes[pb->byte_index++] = pb->bit_buffer >> (pb->bits_buffered - 8);
    - q' F* c5 W9 q$ h: Z( i5 c
  129.         pb->bit_buffer &= (~(0xFFFFFFFF << (pb->bits_buffered - 8)));- W. L1 w& N8 R9 N0 M
  130.         pb->bits_buffered -= 8;
    ( T7 D9 {  R" X  i
  131.     }1 z* J6 e# ^% A3 d3 J
  132. 7 e% R% l4 n* ]4 S9 i4 ~4 L+ m: c
  133.     if (pb->byte_index >= MAX_PUT_BITS_BYTES)4 z8 j1 }2 A1 w8 T
  134.     {5 f4 \( X4 r8 r+ {- Y0 i
  135.         printf("HELP! Bit overflow\n");
    ! s6 i! K$ r+ L( u
  136.         exit(1);+ ^6 Y3 b) Y; I: X5 f) q$ ^, n
  137.     }  |/ r( ~% \4 N7 V
  138. }
    * w7 n9 w' ~* o! d& n$ Y9 ?# l" E

  139. 0 A& L( N9 n, m4 L8 F
  140. static void put_bits_flush(put_bits_context *pb)2 F8 m- ]8 G' Z
  141. {" P3 ^; I- a/ }! a  o. a4 h2 ^" L
  142.     if (pb->bits_buffered > 0)
    & u8 v( J9 J7 }" \
  143.         pb->bytes[pb->byte_index++] = pb->bit_buffer << (8 - pb->bits_buffered);
    " o3 r/ w) C. b7 o" C
  144. }
    3 M* z  \& j3 a$ H( h* C6 |: F

  145. , t* g$ z/ q. r: J6 M& C. P* O
  146. static void delete_put_bits(put_bits_context *pb)# U# K" Y. _& U1 v& e
  147. {8 W0 N7 V' Q9 C; T- E& K' H7 s
  148.     free(pb->bytes);! T3 {4 |$ A: q* |
  149. }
    0 d$ y( _1 E3 a! x3 ^

  150. - N3 T$ t; S; Z- _4 y  r& x' `+ j
  151. /*********************************************************************/. f$ J8 U' V+ D' F$ b7 U% u
  152. 5 [4 ]5 x2 J: H5 V7 H
  153. /* RBT functions */- w7 E- a0 K# Y3 K, W* A
  154. ; T$ Y2 K) F( V
  155. #define PALETTE_COUNT 256
    & Y* c4 F; R* Y& u2 D
  156. #define RBT_HEADER_SIZE 60  Q- x' a' i3 J% x/ d+ @, H
  157. #define UNKNOWN_TABLE_SIZE (1024+512)
    8 K1 ?/ ^- E# ^9 J  m; B
  158. #define SUBTITLE_THRESHOLD 0x70
    - r" c! b) f8 s7 ^0 T
  159. #define MILLISECONDS_PER_FRAME 1002 i7 a5 ?) Y* n) M8 _
  160. & K8 [6 |$ ?& y# _1 Y1 N+ a' H
  161. /* VLC table */
    / M# _, ]) p/ [$ {) L6 h) f
  162. #define VLC_SIZE 4  B' s! I- [1 o% H
  163. static struct
    2 f( c, j% {; t$ {8 s* E
  164. {
    2 x: i! F! ?! k( Z  x* g0 T
  165.     int count;$ x0 _$ n7 W# u- t/ V
  166.     int value;& \+ f$ G2 C" A4 L
  167. } lzs_vlc_table[] =% I% k" I: |- ~# X5 c" }
  168. {! O  m# ]. Q+ f5 e
  169.     /* code length = 2 bits; value = 2 */9 M  w' l, O: s& k: U
  170.     /* 0000 */ { 2, 2 },
    9 q' q9 _) Q' G- p& @% E0 v4 e
  171.     /* 0001 */ { 2, 2 },3 q0 X5 G6 E; B1 D6 J
  172.     /* 0010 */ { 2, 2 },
    % C- Q3 S. Q! x  m6 {1 R/ ]
  173.     /* 0011 */ { 2, 2 },
    # X3 \0 l5 Q! }$ _6 e% n1 l

  174. 6 i$ T  Q# e" j4 J6 Z$ s
  175.     /* code length = 2 bits; value = 3 */+ ~( v% m$ i3 Y; _- {! v( M+ B
  176.     /* 0100 */ { 2, 3 },' f: L; J2 ]9 C' g+ r2 T* W
  177.     /* 0101 */ { 2, 3 },
    $ I& m" z' b% _
  178.     /* 0110 */ { 2, 3 },3 s. ~( ~" K* W$ S" L' v; ^- \/ h  V; _
  179.     /* 0111 */ { 2, 3 },$ {1 g; |3 |5 Y6 j
  180.   t/ p1 b/ J3 D* F
  181.     /* code length = 2 bits; value = 4 */
    # l6 L# u$ G  B
  182.     /* 1000 */ { 2, 4 },2 K: n( L5 @$ X" `6 l; b2 W4 |5 m
  183.     /* 1001 */ { 2, 4 },
    - k* V0 n; O; {. E4 \
  184.     /* 1010 */ { 2, 4 },( r# v. ?  b! b: o8 C; k  b% O
  185.     /* 1011 */ { 2, 4 },
    2 ^% |8 }# e5 m: L% \9 D  L& H" c
  186. 7 J. G3 l' r- i0 Z8 R1 |+ E
  187.     /* code length = 4 bits; value = 5 */( v" \9 l% F  H. g' k- R
  188.     /* 1100 */ { 4, 5 }," ~. ^$ z' z( O. L0 u1 D' z/ ?

  189. # s0 h  U+ n* u& t7 H; X* ^
  190.     /* code length = 4 bits; value = 6 */) _$ Z2 E- N" Z/ [% q
  191.     /* 1101 */ { 4, 6 },5 o3 l$ W2 u/ k* p, r

  192. ( ]( w: E) L# g$ q, F' }
  193.     /* code length = 4 bits; value = 7 */  n6 ^% @& w4 l. Q3 u
  194.     /* 1110 */ { 4, 7 },( t0 s  N1 k# o5 f( M8 q
  195. & Y% \. x1 ^; b8 g$ m8 m1 u9 p/ P
  196.     /* special case */1 e' F: h1 v& n7 F( m( L1 _
  197.     /* 1111 */ { 4, 8 }
    6 e, X" g' `& @) j2 L
  198. };
    " j5 p' e+ x: |- [6 Q; z+ ^

  199. 8 m. W$ M, @, D
  200. typedef struct( C: A# ^. Q% L
  201. {$ {2 I2 ]1 k' v' ]
  202.     int version;
    # T6 D  B7 G/ I# D
  203.     int width;
    1 f- r/ [0 X6 q
  204.     int height;
    6 ]$ D& _; e  c' j$ F% L
  205.     int frame_count;5 \3 T6 i$ E* D! x  i+ P
  206.     int audio_chunk_size;
    5 E5 P" n6 \4 I# Z4 a
  207.     uint8_t palette[PALETTE_COUNT * 3];
    0 n# u' u) ~5 K
  208.     off_t video_frame_size_table_offset;# B( u8 z8 i8 Z% ?7 ]/ x
  209.     uint8_t *video_frame_size_table;  w! ~8 s- Z! ]$ e; y* c
  210.     off_t frame_size_table_offset;
    : \1 Q! m/ \+ G0 T: o& O7 i: C
  211.     uint8_t *frame_size_table;
    0 i( b$ Q. J* t; H+ ~3 R
  212.     uint8_t *frame_load_buffer;& {7 Q, Q' u# D7 }) b, g0 Q' g9 T
  213.     int dump_frames;2 Z( q4 {6 \6 ?# H/ {  Q8 I% z
  214. * l$ |7 ^2 P. X! B; J9 t
  215.     /* subtitle library */4 E# S0 Z1 y% _& f3 u! m
  216.     ASS_Library *ass_lib;9 a3 v" K5 O" y1 w8 }$ X
  217.     ASS_Renderer *ass_renderer;
    ' r5 g" L) g8 P, b# k$ k
  218.     ASS_Track *ass_track;
    - M9 f$ `3 ?: D: H$ @
  219. } rbt_dec_context;
    0 r* E; Y- r* @7 R8 [& }  z

  220. 7 [5 d$ N2 r" e; w4 y# Y1 E8 m. |( r
  221. static void dump_pnm_file(char *filename, rbt_dec_context *rbt,+ I8 G9 |6 A& a1 g
  222.     uint8_t *image, int width, int height)0 S( Y4 I7 f4 W" O5 E
  223. {( ^; m1 [0 G& c! i
  224.     FILE *outfile;$ }" |* m+ ?6 y# f
  225.     uint8_t bytes[3];  I% w% g, n$ T/ q" e. {' k
  226.     int p;
    " m+ J3 t; N0 h
  227.     uint8_t pixel;
    8 G7 y; T: f$ X" S& K/ X

  228. 1 E8 J) \( X$ I
  229.     outfile = fopen(filename, "wb");" a: w/ ]( q% J' D
  230.     fprintf(outfile, "P6\n%d %d\n255\n", width, height);
    3 L, z+ Z! V, y, F) S9 B$ N
  231.     for (p = 0; p < width * height; p++)
    - f9 f" K7 Z2 [: g* F' T
  232.     {! |5 U2 {, J1 n  f4 D5 h. ^
  233.         pixel = image[p];0 m8 Z1 q% v6 |3 {% g
  234.         bytes[0] = rbt->palette[pixel*3+0];& R" L+ A" G8 X  n
  235.         bytes[1] = rbt->palette[pixel*3+1];( V1 Y4 n- i8 U
  236.         bytes[2] = rbt->palette[pixel*3+2];
    ) C0 h& e& _3 O: p! r
  237.         fwrite(bytes, 3, 1, outfile);5 S8 `) _* H6 d9 C. |( e" e* m! D
  238.     }0 }+ A4 e2 h9 R- i1 ~
  239.     fclose(outfile);
    8 l" b/ ^4 I" K+ P' U% u4 k
  240. }
    : m/ t0 p0 W9 Z+ B0 m- m

  241. * M0 ~, X) R% @, N# v
  242. static int load_and_copy_rbt_header(rbt_dec_context *rbt, FILE *inrbt_file, FILE *outrbt_file)
    ) z) r& f3 {+ u3 o* u
  243. {. |: C( C/ y6 o: v
  244.     uint8_t header[RBT_HEADER_SIZE];" c) \; K$ l$ y9 t
  245.     int palette_data_size;
    ( }8 d- m, ~- S* \1 l. U% ]  U/ N
  246.     uint8_t *palette_chunk;+ G0 Z, A4 w$ a# V4 F, I( {) X" W
  247.     int unknown_chunk_size;
    : M" e7 e. S# N3 Y
  248.     uint8_t *unknown_chunk;$ _" H6 b% j5 U6 G) D- }, q, f( D
  249.     uint8_t unknown_table[UNKNOWN_TABLE_SIZE];& \7 z) B/ X& r+ j5 w0 r
  250.     off_t padding_size;% x6 l7 B8 c3 d8 K* B
  251.     uint8_t *padding;9 _* g4 f  W) A8 x! F1 P) H. f
  252.     int i;4 h( I5 l9 B! M: J5 `
  253.     int frame_size;
    3 d1 c; h- L0 k
  254.     int max_frame_size;  Y8 F$ E5 Q3 C: D5 d/ e
  255.     int first_palette_index;
    ) q( G8 f  S5 |! w
  256.     int palette_count;5 G& f& p0 Q$ |& z
  257.     int palette_type;
    5 m6 R" ~0 {5 s4 c1 {2 N
  258.     int palette_index;$ |; _$ n4 K' }

  259. $ D% ?! q/ n1 M: {( K
  260.     fseek(inrbt_file, 0, SEEK_SET);
      G( G& I9 i1 t
  261.     fseek(outrbt_file, 0, SEEK_SET);
    4 s9 X2 T' l) L
  262. ( U3 ]! i+ L8 K9 G4 P
  263.     /* load the header *// C" R& |7 V' C9 E
  264.     if (fread(header, RBT_HEADER_SIZE, 1, inrbt_file) != 1)1 G& A( X. t6 c" C! d. A
  265.     {1 }( o' Y, F* ~3 Z
  266.         printf("problem reading initial RBT header\n");
    ; [7 k3 b- L6 N; R) @% w2 P/ V
  267.         return 0;3 l/ \, g, D( \, m0 |% B, ^
  268.     }2 d6 h; f+ X1 i, X1 b
  269. 1 E) F) ]+ a: h* j& N5 s
  270.     /* copy header to the output */+ ]0 S+ S6 _0 S; }7 D3 A
  271.     if (fwrite(header, RBT_HEADER_SIZE, 1, outrbt_file) != 1)
    0 [" X& e& c0 \& G* J0 P, L
  272.     {
    : d5 ?8 G7 c! U1 V% P
  273.         printf("problem writing initial RBT header\n");+ W' r" H8 W2 b: ]! l8 N
  274.         return 0;8 p/ Z: N; s1 a/ M% }% a  P. P
  275.     }  j' g# S- V- h, ~$ m4 W1 n
  276. " ~; v: v5 L3 P, ?' n; G) z$ s. ^8 r
  277.     rbt->version = LE_16(&header[6]);( K  v/ \7 x( u0 t1 r9 ]) e8 w) f
  278.     rbt->audio_chunk_size = LE_16(&header[8]);
    ' z1 _, n1 j! Y: N: Y, Y$ Q- f* E
  279.     rbt->frame_count = LE_16(&header[14]);
    1 V" D1 n0 y% w2 _8 j) T6 a' Q  E
  280. 0 P8 w: |2 E2 }# w; i0 O# y1 w5 k
  281.     /* transfer the unknown data, if it's there */7 e; C% n% o! d9 U) j; h
  282.     unknown_chunk_size = LE_16(&header[18]);1 ^' n( p: J' Q! z
  283.     if (unknown_chunk_size > 0)* ~1 H5 H  g5 q& k! n
  284.     {
    # f( n. E+ g  X2 q& m3 S0 T
  285.         unknown_chunk = malloc(unknown_chunk_size);
    * J/ P" f( ?( R. W# d2 S
  286.         if (fread(unknown_chunk, unknown_chunk_size, 1, inrbt_file) != 1)5 f) T/ J3 m1 m, _) l! L  R- R
  287.         {4 I2 o) ?) R/ K. v3 ]9 A) U
  288.             printf("problem reading unknown data\n");
    $ u5 Z/ Q( T6 O) b9 e1 t2 s
  289.             return 0;& e/ O- ]0 J" W3 ^  z$ z
  290.         }+ j( E* ]% D2 b1 s+ g
  291.         if (fwrite(unknown_chunk, unknown_chunk_size, 1, outrbt_file) != 1). P9 H, i& I7 z. q
  292.         {
    , ?( f  j7 j! Q& `% `
  293.             printf("problem writing unknown data\n");
    2 B7 f; V9 C. o- E/ v6 x" y/ h; R
  294.             return 0;
    1 ?5 x2 _# R* \3 B
  295.         }
    # {* S4 M( @( o
  296.         free(unknown_chunk);
    2 }  `. D, {4 s. l
  297.     }
    - A/ g2 \; @' U3 L; P( s/ R
  298. . C. ?4 [& Y9 e: h7 i; v8 R1 x
  299.     /* transfer the palette chunk */
    : j& `% g1 N6 q) w; O, M
  300.     palette_data_size = LE_16(&header[16]);1 M( d0 H9 Y: C. m4 x, v& G, e
  301.     palette_chunk = malloc(palette_data_size);3 P. |( c% d' Q* g( r  T8 i
  302.     if (fread(palette_chunk, palette_data_size, 1, inrbt_file) != 1)
    4 [0 `6 [8 E7 U1 J( O
  303.     {
      j( \, O, h; W, ^, J
  304.         printf("problem reading palette\n");2 \8 |" H7 T2 U0 D: w* ?
  305.         return 0;
      i3 m) y  t2 ?% [/ V& @# D6 J
  306.     }6 t- ?6 V# V7 G5 [/ G# H# k
  307.     if (fwrite(palette_chunk, palette_data_size, 1, outrbt_file) != 1)
    & `3 W, u# H8 l" l& W
  308.     {
    & ~" r& G# U9 Q* y" ]7 }/ C8 M
  309.         printf("problem writing palette\n");
    * E% L- z! j6 j, R# W
  310.         return 0;
    1 i! {6 I2 X7 q6 g
  311.     }% s, \1 h" _& C3 O1 Y
  312.     /* load the palette into the internal context */
    2 K" N) h( u0 z
  313.     memset(rbt->palette, 0, PALETTE_COUNT * 3);
    6 P0 J' n+ L- H/ N% y
  314.     first_palette_index = palette_chunk[25];! v' w$ V7 d7 p# J% M
  315.     palette_count = LE_16(&palette_chunk[29]);* t# K  C3 H  b) P% p# j
  316.     palette_type = palette_chunk[32];
    # Q: S1 g, A- Y5 y! z7 ]2 N6 q+ |% f0 R
  317.     palette_index = (palette_type == 0) ? 38 : 37;( s+ @! W; ]4 w4 w6 S3 L
  318.     for (i = first_palette_index; i < first_palette_index + palette_count; i++)! k0 t/ b0 X0 ?( b+ j9 k9 Z6 b5 ~5 e
  319.     {
    ' o6 S! R0 W; W8 o4 V9 o
  320.         rbt->palette[i*3+0] = palette_chunk[palette_index++];
    # r/ n& W$ s. |) Q
  321.         rbt->palette[i*3+1] = palette_chunk[palette_index++];2 v4 e. p/ h  U+ |5 ~: H
  322.         rbt->palette[i*3+2] = palette_chunk[palette_index++];0 e2 s6 U% P, S& l3 T
  323.     }
    - L4 V# a4 C# o& ~
  324.     free(palette_chunk);7 F! Q5 f, f: w/ T$ z7 @* r% \! |9 o
  325. + l5 i" r& N/ `, ^- M/ K
  326.     /* copy the video frame size table (2 bytes per frame), as a placeholder */
    8 U3 ~! ?! B& A
  327.     rbt->video_frame_size_table = malloc(rbt->frame_count * sizeof(uint16_t));
    : k5 I$ g  A3 v; D- U
  328.     if (fread(rbt->video_frame_size_table, rbt->frame_count * sizeof(uint16_t), 1, inrbt_file) != 1)0 [+ t/ I. z4 m5 e5 w4 n3 x5 N
  329.     {
    0 g: L4 e& K3 H) r8 C  b
  330.         printf("problem reading frame table\n");$ }8 w8 g7 N' K8 w$ v* M2 s7 W# N$ d) a
  331.         return 0;
    : Y, ]* V! l: ]" f' o2 i8 r
  332.     }
    / l4 a# W6 k1 [
  333.     rbt->video_frame_size_table_offset = ftell(outrbt_file);" l% F( G. }  K# b
  334.     if (fwrite(rbt->video_frame_size_table, rbt->frame_count * sizeof(uint16_t), 1, outrbt_file) != 1)
    4 E7 b% v. _% k: |
  335.     {4 Z; n! D2 k2 ^$ H* n
  336.         printf("problem writing frame table\n");- R# N% r* p1 |! v' ~
  337.         return 0;
    9 W! v9 t7 Z4 c7 [6 S& m6 u
  338.     }5 e! ^9 i% A6 Q* a6 e8 L
  339. 6 {% J: Y  D5 R2 I
  340.     /* copy the frame size table (2 bytes per frame), as a placeholder */
    0 }% [" s; M4 y3 G
  341.     rbt->frame_size_table = malloc(rbt->frame_count * sizeof(uint16_t));8 l" V$ m; d$ ~
  342.     if (fread(rbt->frame_size_table, rbt->frame_count * sizeof(uint16_t), 1, inrbt_file) != 1)
    ! k9 F. }$ o' k* I
  343.     {6 i; p! {& X) x  E6 m3 y/ \
  344.         printf("problem reading frame table\n");
    ; o% S, S) z2 J2 O/ I- N* ^# @
  345.         return 0;
    1 A- i4 x- {% i' s- F3 K" P
  346.     }
    ) [. L& e% j. V5 D8 _7 I/ X7 F
  347.     rbt->frame_size_table_offset = ftell(outrbt_file);; Z5 Z; B4 Q$ Y  |
  348.     if (fwrite(rbt->frame_size_table, rbt->frame_count * sizeof(uint16_t), 1, outrbt_file) != 1)/ L1 A" q9 L- b1 Y/ g* i4 [& k% w
  349.     {: Z; |( k% [# d# i+ s  P4 Q
  350.         printf("problem writing frame table\n");- Z! }1 S1 }7 Z2 r+ ^( e( |
  351.         return 0;
      u$ @$ A+ `: Q' [4 y) a! G4 p
  352.     }
    , {, K4 b3 J/ ?, u$ ^6 i% q
  353. 0 Y. C/ t1 \9 T$ R; L% c1 d
  354.     /* find the max frame size */) x4 ]  V% ]$ Q, {
  355.     max_frame_size = 0;8 _& H# N1 g) c& r0 t
  356.     for (i = 0; i < rbt->frame_count; i++)
    # @) e+ I- G1 J0 j/ D" _
  357.     {$ ]" J7 x7 B' F+ J6 X/ `6 N1 i
  358.         frame_size = LE_16(&rbt->frame_size_table[i*2]);# v4 q: Y" y6 `8 K( U4 W' f5 v
  359.         if (frame_size > max_frame_size)
    - T. `- h1 Q4 {
  360.             max_frame_size = frame_size;
    3 l* }; ]! f, I* ?
  361.     }
    4 Q- ?. i( n! {: I6 r% I+ K
  362.     rbt->frame_load_buffer = malloc(max_frame_size);
    , b: l5 v1 t9 I$ `# t+ ?& N& [9 R

  363. / x8 a0 u0 f6 \' ~
  364.     /* transfer the unknown table(s) */
    8 Y  r0 b' J! P1 f! M) ~% g' m
  365.     if (fread(unknown_table, UNKNOWN_TABLE_SIZE, 1, inrbt_file) != 1)
    2 M  k- {) _) }$ X5 h
  366.     {2 b. x4 d  H' j4 N* q
  367.         printf("problem reading unknown table\n");
    ' A. v  p- w" E1 e2 m& r
  368.         return 0;
    8 W& J3 M1 O8 ]8 K9 ~. Y$ l
  369.     }
    2 D6 V  A" q3 D' T
  370.     if (fwrite(unknown_table, UNKNOWN_TABLE_SIZE, 1, outrbt_file) != 1)* H- x. Z, g4 N8 e6 {/ P' W
  371.     {; V8 M/ o& a; d6 Q
  372.         printf("problem writing unknown table\n");" K: P( v/ e, `( N
  373.         return 0;
    * k! ^$ K+ k# I* H
  374.     }
    ' g- g7 b5 R5 ?) h+ f

  375. 3 V8 M+ ]! T2 c: V3 E
  376.     /* copy over padding */
    ' F$ Q6 \4 J3 G: m
  377.     padding_size = 0x800 - (ftell(inrbt_file) & 0x7FF);
    # a0 A% Q! _/ b- y
  378.     if (padding_size)
    + P& T4 Q( v' ^
  379.     {
    * r/ ?" x4 _" N% Z8 J$ E6 L0 q
  380.         padding = malloc(padding_size);; j4 u) f9 o6 P& f2 H# }
  381.         if (fread(padding, padding_size, 1, inrbt_file) != 1), q- ~3 o; t3 j, Q/ \
  382.         {
    & h2 ~. y- ~7 ]% @" [4 m, @
  383.             printf("problem reading padding\n");( H9 Z! e4 ?* o. Z# z7 x  G
  384.             return 0;, u7 h, ?/ n8 l
  385.         }
      l1 h5 ?( F$ z' L
  386.         if (fwrite(padding, padding_size, 1, outrbt_file) != 1); }" V! }# b6 O. }  w
  387.         {0 ^' y& L; w2 W6 K  `0 G: U
  388.             printf("problem writing padding\n");
    ) N2 x& l+ ?9 s
  389.             return 0;; Z4 o- a4 x8 E9 h" U9 I( e8 Y3 N
  390.         }, G/ c& u3 Q5 [. n1 e1 f
  391.         free(padding);8 ~- t5 g- X9 l* {2 V
  392.     }: D+ r6 H9 g1 t0 ~8 O
  393. 0 T. \6 J" m% E3 \
  394.     return 1;& z* t! p# |4 }, l
  395. }
    ! Z5 e- _9 U, v
  396. : }  |# G3 p4 F2 ^
  397. static int get_lzs_back_ref_length(get_bits_context *gb)4 D9 w: r" `* H5 P" @% L& `! K
  398. {
    4 O1 i7 Q" F, h( G! x$ A
  399.     int vlc;7 a' y/ A7 u- x. R/ C
  400.     int count;% }' {7 Q7 Y$ X' }
  401.     int value;
    & o. R8 Q- w8 B! h( s2 T
  402. + q1 j8 e5 |& Z5 ]5 F4 O
  403.     vlc = view_bits(gb, VLC_SIZE);
    & M2 `% q+ J1 |, O8 K2 s
  404.     count = lzs_vlc_table[vlc].count;
    % z  n* A- L4 h
  405.     value = lzs_vlc_table[vlc].value;$ T) s6 S1 S' b! d+ n& Q
  406. - a* y% Y* w& U
  407.     read_bits(gb, count);
    + K! ~1 ~; A! U$ X  [2 F
  408.     if (value == 8)
    3 I8 E) `& }& I+ k+ P2 _8 B; ^
  409.     {- g4 I) O; A* x: V
  410.         do
    + t) o- H; f+ V" O& n+ s6 ?
  411.         {
    * m8 Q( C: y& r+ R8 G$ {. R+ e4 [7 Y
  412.             vlc = read_bits(gb, VLC_SIZE);) g* r* W/ L$ C4 E7 i( o
  413.             value += vlc;1 \' s; w* B5 |% `6 V6 Z# p' j: D
  414.         }! Y/ `" o) t. G7 }
  415.         while (vlc == 0xF);
    / J3 |5 {1 |) P) S2 F' o# W$ ~: w
  416.     }
    - o( _: k% |$ O* [" H& g0 a

  417. $ }& L1 v$ O% w2 `3 m) Z6 Q% ~8 F1 M
  418.     return value;4 o* \0 `+ l, o' l5 \
  419. }
    ; R. ]& z0 ^) S; f- `% e0 T
  420.   p9 E0 ^& W5 _6 t3 y! M8 o
  421. static void compress_window(put_bits_context *pb, uint8_t *full_window,& t1 |& f& m- m( u9 D/ s7 P: N
  422.     int full_window_stride," V! p3 z% t. n- h
  423.     int window_top, int window_bottom, int window_left, int window_right)
    ! {- [/ }/ [8 f) }! y% B8 @. G
  424. {* B# W. {, A. w' D; O
  425.     int last_pixel;
    # I* v0 h- ?- J5 k4 o9 o; ]
  426.     int run_size;5 ^- f* p, ~& X
  427.     int x;& f1 s# `2 f  b  [0 n
  428.     int y;
    7 S  u5 k; k, {6 [3 J" U
  429.     int start_index;1 X7 D4 `; S% w% ?4 B' ~
  430.     int end_index;
    3 @& w8 p0 l, y
  431.     int encode_last_run;3 u. J# y# ^! {: v

  432. 8 ]1 D8 }. `; e/ T6 A# `3 Q
  433.     last_pixel = full_window[0];4 {0 h/ h% |  ?5 ~
  434.     run_size = 1;
    * x* Q5 ^: C, [7 }
  435.     for (y = window_top; y <= window_bottom; y++)
    2 @7 U- D; x0 ~  \, t; ~
  436.     {& q$ v2 Y& r  p' \# b: J
  437.         start_index = y * full_window_stride + window_left;0 D2 o8 o$ n0 d* _
  438.         if (y == window_top). X" m: k: J9 r
  439.             start_index += 1;
    + F8 _9 M) t+ W; P# `
  440.         end_index = y * full_window_stride + window_right;
    8 u6 m8 h/ v) A+ U6 I; L9 s
  441.         if (y == window_bottom)* D5 O$ J* k: w% p1 i% P
  442.             encode_last_run = 1;
    " R6 Z1 Y/ t4 l' a
  443.         else! k- }+ C6 l; c. h/ T
  444.             encode_last_run = 0;% ~! J5 F6 q" w( k( N
  445.         for (x = start_index; x < end_index; x++)1 e" o, g1 E8 E8 ?- c
  446.         {  z% h4 ^0 j7 I
  447.             if (!encode_last_run && full_window[x] == last_pixel)
    * M. d& H& N8 H! o/ J! F
  448.                 run_size++;! a' ~, M5 }+ A* d, V
  449.             else
    9 r: q3 b! X$ A' B5 E* @6 |$ Y
  450.             {
    ) [' N: s) Q, X" u( B8 t1 I9 A
  451.                 if (run_size == 1)
    4 u6 g6 U1 }9 t1 \6 d+ }
  452.                 {( @6 D" l  X8 h1 b) e
  453.                     /* encode a 0 bit followed by raw pixel byte */
    & w& N: M) f. [4 W
  454.                     put_bits(pb, 0, 1);" k% V- `5 T& }
  455.                     put_bits(pb, last_pixel, 8);. B5 g5 U# v7 z% g
  456.                 }3 F9 w+ V; _) X3 v2 G
  457.                 else if (run_size == 2)
    & d" [. x  s) @3 b. h9 ~  E
  458.                 {
    9 ~) M5 B8 Y! \3 I5 C6 T
  459.                     /* encode a 0 bit followed by raw pixel byte */1 b2 p- O4 Q# S# B8 X' z
  460.                     put_bits(pb, 0, 1);
    0 v9 q& B, H, k: ?
  461.                     put_bits(pb, last_pixel, 8);
    4 R( I( m* T) R8 T" [0 v' w
  462.                     put_bits(pb, 0, 1);* ^+ ]# J/ d7 a% U9 n  P! Z  w
  463.                     put_bits(pb, last_pixel, 8);% k7 T* r, n& |7 b  L+ J# k5 y
  464.                 }7 b' s2 l: D% R+ _7 A% [
  465.                 else
    % ^" `2 b. J; X" q# M
  466.                 {' C% s3 F) [' P) o0 F
  467.                     /* encode a 0 bit followed by raw pixel byte */
    5 i* o. X% {( W6 ^
  468.                     put_bits(pb, 0, 1);& u* [; b, [2 ]/ u
  469.                     put_bits(pb, last_pixel, 8);- f0 c: b: I8 i5 t% w
  470.                     run_size--;
    ! j- Z3 M) ^4 m6 O- m
  471.                     /* encode a run: a 1 bit, followed by a back reference
    4 z5 w0 ?1 v% z' E' _  f
  472.                      * offset (-1), followed by a length */
      q! D1 V- [. a. a; x
  473.                     put_bits(pb, 1, 1);7 c- M4 o5 d' W6 K* R0 q
  474.                     put_bits(pb, 1, 1);  /* 1 = 7-bit offset */
    9 W9 K1 D7 a- V
  475.                     put_bits(pb, 1, 7);
    , R3 s9 ^; u8 l/ y- P
  476.                     if (run_size <= 4)7 A7 V* V" z: B. }$ S
  477.                     {( @8 `5 D) Y- |! s6 O' [, ~2 C
  478.                         /* lengths 2, 3, and 4 are 2 bits */
    & }+ C/ a1 S. j  P& i1 O
  479.                         put_bits(pb, run_size - 2, 2);5 j) ?. j1 F! E" S; i- p+ ~1 `0 P3 a2 h
  480.                     }( D2 I4 E  C( K8 l, y& k
  481.                     else if (run_size <= 7)7 O( b% z' t; G
  482.                     {, J4 K* }3 v4 ], x/ o; O& X. F! k
  483.                         /* lengths 5, 6, and 7 are 4 bits */
    8 \  H! ?- K! o: O5 _0 }9 s4 [0 A
  484.                         put_bits(pb, run_size + 7, 4);4 p1 h/ g' a$ T, h( }- [# ^
  485.                     }2 Q. Q7 C& H1 k
  486.                     else
    9 L" C  `" B" ^: S8 j0 \
  487.                     {
    6 s+ Z9 J4 t/ r0 U$ i- [
  488.                         /* arbitrary length; start by encoding 0xF which; I1 ]4 K% W" u+ B
  489.                          * stands in for an initial version of 8 */# @6 e( i& b3 g& l2 I, D7 \
  490.                         put_bits(pb, 0xF, 4);/ |6 l% D/ n: ]# I
  491.                         run_size -= 8;
    : C% J% x3 B( i' D0 x; l

  492. 4 }$ S& U* ^# g+ q3 ~1 K
  493.                         /* encode blocks of 4 bits until run_size is 0 */4 V: {6 _9 s( m9 U8 H2 k! ]
  494.                         while (run_size >= 0)
    " E( F+ F# r, `8 o+ b7 z
  495.                         {! I  X& D' H( \- ]4 l# s9 ?9 q# T5 l
  496.                             if (run_size >= 15)
    ( x% d( D8 z# g% H1 i
  497.                             {
    ! i8 a! S. o: q  v, U9 M, l
  498.                                 put_bits(pb, 0xF, 4);$ Z/ w  B; g0 r" F' N
  499.                                 run_size -= 0xF;
    9 _0 E4 l9 _, w* U
  500.                             }# G. b: C8 H/ q
  501.                             else
    3 Z# g" S3 _+ u
  502.                             {. L" X8 J# e) j* I4 C
  503.                                 put_bits(pb, run_size, 4);
    ( ?5 ]4 W1 |$ v6 \  s
  504.                                 run_size = -1;
    % v/ V% I6 r# |  W$ o4 y0 }; a
  505.                             }
    ' A$ c! B7 ^& I3 B, B! b
  506.                         }
    4 W' s5 ?" w) ]
  507.                     }
    1 H9 v7 r0 |8 C# \3 F. q
  508.                 }' T+ c' K- {0 x+ K* b/ j3 S, W0 }4 D

  509. , H, }$ w$ u( l
  510.                 last_pixel = full_window[x];
    - B; }* b2 Z- P7 L% m4 J2 F
  511.                 run_size = 1;7 R. O! W2 R9 t8 l& `
  512. 2 |2 U- ~  B, W5 o" O8 p
  513.                 /* this single x iteration was only here to close the final run */
    * h: ]- m" t8 x( t
  514.                 if (y == window_bottom)3 Z, K& G& J: C6 z# A1 l
  515.                     break;
    0 f, r4 P! J5 Y% V
  516.             }
    0 J! E- e" f) Y! _
  517.         }& o0 t: x" }+ [) F" g8 R
  518.     }1 x$ @) ~3 v1 M/ T
  519. / [3 E/ `7 ^$ ]8 E
  520.     /* close the bitstream by encoding a back reference with length 0 */
    4 I! T' o" p. O5 Z6 p
  521.     put_bits(pb, 1, 1);  /* back reference run */
    . a( C& H0 ~; D  u# b; l# v3 [# J
  522.     put_bits(pb, 1, 1);  /* 1 = 7-bit offset */
    + f0 V8 F# t" T* |% P' Z0 p. H
  523.     put_bits(pb, 0, 7);  /* length 0 */$ d' x- `, R4 R  }: A; T. y

  524. ( h# x. |7 U4 O- O( {" U) Q2 O
  525.     put_bits_flush(pb);$ |/ P3 A- ]; C1 g- F6 ]8 U; k
  526. }% o4 N1 W2 w; `2 T

  527. 0 K8 u& A& S9 e
  528. /* compute Euclidean distance between an RGB color and the desired target */
    % L) D& e6 C) E& F* |1 f
  529. static int compute_rgb_distance(int r1, int r2, int g1, int g2, int b1, int b2). @$ a% s2 }4 Q- g; l1 k
  530. {
    $ ^7 ~& g; S$ t$ B8 ^
  531.     return sqrt((r1 - r2) * (r1 - r2) +
    1 [3 T* G; R, X: c
  532.                 (g1 - g2) * (g1 - g2) +
    / u( n- X8 @% X. F1 s! _
  533.                 (b1 - b2) * (b1 - b2));
    % ^1 |( j( S2 N) t
  534. }% S) U1 H$ Z2 q* C/ D  Y8 A# }
  535. 0 m7 q/ w4 e) X! ^: Z  C
  536. static uint8_t find_nearest_color(rbt_dec_context *rbt, int r, int g, int b)
    ! ]# W) j5 V. w. q+ x
  537. {
    ' _. C* O0 Q) `
  538.     int i;
    " K  U9 C6 B) s& ]9 g+ [
  539.     int nearest_distance;
    3 U' A% S4 U% f. J( D6 _
  540.     int distance;% }7 Y# x& y9 @+ Q) E
  541.     int rp;  W0 @+ q2 Z' M$ L
  542.     int gp;
    # r8 ~2 |( n3 F. ^9 y
  543.     int bp;) r8 }, s) u- v8 ]7 Y
  544.     uint8_t palette_index;8 M4 X* S  V! G7 F0 I0 `

  545. ' n( o6 X" I/ i- s& N" \2 F1 O
  546.     nearest_distance = 999999999;
    ) u9 {+ n7 K9 d" |) b
  547.     palette_index = 0;- F' a- C2 ]1 ~' E
  548.     for (i = 0; i < 256; i++)
    8 f% @$ M2 O4 p6 |8 ^- G4 n: L4 p
  549.     {( D! e  `  e7 ^
  550.         rp = rbt->palette[i * 3 + 0];. d/ N. q4 `8 l. _! i* x& Z; c# G# p/ ]
  551.         gp = rbt->palette[i * 3 + 1];6 o# b4 k' I7 R$ d+ [
  552.         bp = rbt->palette[i * 3 + 2];0 _7 o% [1 M( ~2 ?* V  I
  553.         distance = compute_rgb_distance(r, rp, g, gp, b, bp);% I% q4 h4 R( C" Z/ L9 O2 f8 z
  554.         if (distance < nearest_distance)+ e9 ?8 I( ~* `% \5 r! y8 q6 A
  555.         {
    6 n7 \6 r. D% H+ S+ ?& l) W9 q
  556.             nearest_distance = distance;; l1 I( P2 x4 `0 f/ S4 E
  557.             palette_index = i;
    $ ]" P- @# b4 x( M1 x7 ?) G( a
  558.         }
    ' t" s3 i5 R7 ]# X9 E6 f* T: W7 a
  559.         /* can't get closer than 0; break early */
    5 s) V' `  i  H5 S* k, e
  560.         if (distance == 0)
    ' X$ [$ m8 f1 e7 b" N
  561.             break;' w3 x. b6 C" i0 c
  562.     }) n! c/ b  X. S# Y

  563. 4 [9 R; Q3 H% _
  564.     return palette_index;" i" A2 q3 {  N
  565. }
    + B+ _& ~# d" G: \$ {3 I& Y/ `
  566. 2 ~9 D, s; R; W  \! g8 g+ n" o
  567. static void subtitle_frame(rbt_dec_context *rbt, uint8_t *frame,) h  Z' k) f0 h6 b$ |
  568.     int width, int height, int timestamp)& U8 E' w- b5 ]
  569. {
    6 Y) v* f' f1 d- l- ], r- \. I
  570.     ASS_Image *subtitles;% t% ?, Y$ V9 H  p% y) b
  571.     int detect_change;
    1 v9 }" o9 P4 J) J0 N
  572.     uint8_t subtitle_pixel;
    & c+ i! @, X0 w, i* F( {
  573.     int x, y;
    $ S3 |/ ?0 |) e) S! w
  574.     uint8_t *frame_ptr;
    / U# ^9 }! Z# R& c7 y
  575.     uint8_t *subtitle_ptr;
    4 r6 z9 y, r, e8 \. I" G5 S
  576. / |: Y; X. i: l8 X6 f% q/ v
  577.     /* ask library for the subtitle for this timestamp */2 s7 f7 a/ N5 {! ?: G8 Z9 G) Q
  578.     subtitles = ass_render_frame(rbt->ass_renderer, rbt->ass_track,
    9 D; _8 p8 m( j3 h1 E
  579.         timestamp, &detect_change);
    & B) i7 V! D8 ^+ m/ K9 k+ `, V
  580. ( z: V/ l8 g- J' G  h
  581.     /* render the list of subtitles onto the decoded frame */% j( F9 p3 h% u$ s: q
  582.     while (subtitles)7 J! M9 D* y* Z" K( U" [( _" v" k
  583.     {
    7 N1 o( p8 e! ^8 l  _
  584.         /* palette components are only 6 bits, so shift an extra 2; G2 d- `( q( i% @% `" ^
  585.          * bits off each component */
    % a, a" r% |/ M8 @. W5 g" }0 W* I: C
  586.         subtitle_pixel = find_nearest_color(rbt,
    ; A  ^, p- F1 D3 p  {' Z
  587.             (subtitles->color >> 10) & 0xFF,
    ; Y% h$ k* ]: }4 K! q0 `
  588.             (subtitles->color >> 18) & 0xFF,2 [# n7 u8 q- `0 @, `: E; ]
  589.             (subtitles->color >> 26) & 0xFF);
    1 l& `. S" }; e4 f& v
  590.         for (y = 0; y < subtitles->h; y++)
    3 ^0 ?6 Y$ u  N2 G( g/ K
  591.         {
    ! ?6 K% Q: N8 o- K- T
  592.             subtitle_ptr = &subtitles->bitmap[y * subtitles->stride];8 o; ^  p, {# U! D
  593.             frame_ptr = &frame[(subtitles->dst_y + y) * width + subtitles->dst_x];* z7 ?3 N7 N" h8 O) _8 e- [
  594.             for (x = 0; x < subtitles->w; x++, frame_ptr++, subtitle_ptr++)
    & K2 R* q4 F. a( E0 A' c& g
  595.             {- Q2 g: M' @) p9 S0 x
  596.                 if (*subtitle_ptr >= SUBTITLE_THRESHOLD)
    ; @* A5 d; [  u- L: Z$ P
  597.                     *frame_ptr = subtitle_pixel;# d$ ?. i9 N2 R* P, s
  598.             }
      y% |# t+ O, n/ a  {( \7 ]7 `* Z
  599.         }: p, v& I4 [+ p5 ^, F
  600.         subtitles = subtitles->next;
    - ~# G' A" V- V# k
  601.     }! ?+ T6 n+ y4 }# n& m; G* _, ~
  602. }3 f5 w: _- D5 ?

  603. : u7 {' ?6 j- E/ q& \$ }! p
  604. static int copy_frames(rbt_dec_context *rbt, FILE *inrbt_file, FILE *outrbt_file,  e+ m" X/ R  C+ x
  605.     int origin_x, int origin_y, int window_width, int window_height)
    ) }& l9 ]6 g" t8 b8 ]% j# U
  606. {/ Y( r3 U  W7 a" s2 \
  607.     int i;
    2 k" b. G& z8 R9 o3 a& J( |) S  B! B
  608.     int j;
    ( a; ~& f& j. u% v
  609.     int scale;
    ; Y3 ^# g+ g* |+ p
  610.     int width;
    1 W8 @# E8 {0 z  k. ?
  611.     int height;' F! I. i+ o( i
  612.     int max_width;9 s3 Z" R9 j& `& [: l# a1 [
  613.     int max_height;+ k' W' P) t0 n  h4 f; D9 l
  614.     int frame_x;
    ; ?6 h  A5 |. w' E* s2 ?
  615.     int frame_y;' J) G0 I/ ?' ?" t- O" b4 m2 D
  616.     int fragment_count;4 \1 ]7 O7 \* V
  617.     int decoded_size;
    . @* J. k8 N& t+ \/ j6 }/ M) c
  618.     uint8_t *decoded_frame;
    . P; e* ?: U7 u& Y3 W6 `' R
  619.     int fragment;- A# D" u  q. j8 I+ A9 r8 t
  620.     int fragment_compressed_size;& Z' e- m+ C0 l5 @) b! l$ W  j7 c0 ?
  621.     int fragment_decompressed_size;# v1 z2 m4 J# D2 m: X$ h' F
  622.     int compression_type;
    ) w( U8 x2 R) D) H$ S6 \
  623.     int index;1 i4 w: j( C3 y: l
  624.     int out_index;) R& l1 f, l! a6 ~
  625.     get_bits_context gb;/ s6 `. E: j* k$ V4 l# u
  626.     int frame_size;
    ; I1 P" E8 u' s7 W
  627.     int video_frame_size;
    6 S2 k4 h0 ]1 d6 Q8 J0 c
  628.     int audio_frame_size;
    . q0 ?, {$ f2 R- R! S5 L3 c) p& E" {% ]' }
  629. - E" d- p, Z* V) i6 W0 n9 a7 l
  630.     int back_ref_offset_type;
    3 a$ B( s  o4 J, U% l. p* j
  631.     int back_ref_offset;! h9 _3 Z7 u4 Z1 G. s
  632.     int back_ref_length;
    : d# @5 K0 V' D* V
  633.     int back_ref_start;
    2 d& V5 }. n. D3 Z+ F
  634.     int back_ref_end;! q1 X8 h8 H8 u# }- X1 b

  635.   |& @2 }4 ?! b( I
  636.     uint8_t *full_window;! G: J* J3 B7 A
  637.     int full_window_size;& P$ D$ S$ a0 b+ B! Y
  638.     int y;
    & y, J% D# N8 b: T% O) c
  639.     int window_top;
      m) m* l3 e# O- T* i* l! Y. _$ q
  640.     int window_bottom;" |* U$ h! p( [" k
  641.     int window_left;
    ) v+ k+ |4 o% J% b: p9 M2 _1 t
  642.     int window_right;
    # f+ d/ q2 {6 `
  643.     int window_size;
    , Y8 G8 U  r+ A3 X  D! F; ]% a( V6 b

  644. . v  e# g' A: D
  645.     char filename[30];; k! _; ^/ b# @( K: i4 T
  646. . E# \/ y+ q. t- d
  647.     put_bits_context *pb;) \/ o) z2 W- \0 ]

  648. , T) h; i5 ^' _' p, E$ R; t
  649.     full_window_size = window_width * window_height;& u, l: `3 T) a" S! Q6 H# c
  650.     full_window = malloc(full_window_size);
    9 Y" K+ ]$ A& F, e/ a
  651.     pb = init_put_bits();* k" i' g9 l- e: P0 O- n
  652. / l4 B- \# g% f" M) ?' z
  653.     max_width = 0;+ {1 y% b" D6 |. P1 Z* H* z  }5 n
  654.     max_height = 0;
    3 J: O9 y1 F$ Z( M

  655. ' M- ~8 n2 [1 f
  656.     for (i = 0; i < rbt->frame_count; i++)5 Y# R4 u$ k- [( i4 o
  657.     {) Q9 c* w# [) g) I
  658.         /* read the entire frame (includes audio and video) */
    ; Q7 `& l: ]5 L$ ?3 n) D- }
  659.         frame_size = LE_16(&rbt->frame_size_table[i*2]);. W6 R9 o& k9 O% \) ]4 V
  660.         video_frame_size = LE_16(&rbt->video_frame_size_table[i*2]);1 g3 e* U" o' V& L1 E  F
  661.         audio_frame_size = frame_size - video_frame_size;
    5 @- R  G  L4 R# ]
  662.         if (fread(rbt->frame_load_buffer, frame_size, 1, inrbt_file) != 1)
    , n) R9 u' ~9 `9 V- n0 o
  663.         {( t+ K2 w" V* X) W& j; o2 g5 r
  664.             printf("problem reading frame %d\n", i);
    " X9 @$ X6 C4 {% e
  665.             return 0;
    $ i, N- U6 O( i! c& E, Y; W2 O4 ~
  666.         }
    2 c% t; @1 M; P$ q7 p, E5 O
  667. / l/ m. |, ?% z" \5 C% ~; z4 e
  668.         scale = rbt->frame_load_buffer[3];
      z+ K7 R' w0 h& |+ z
  669.         width = LE_16(&rbt->frame_load_buffer[4]);
    ( O( Y8 S- m5 ~; a/ G8 r
  670.         if (max_width < width)0 e8 M) E* Z6 D, S- T2 @6 j
  671.             max_width = width;2 D, L$ `1 E/ u3 `- o
  672.         if (max_height < height)
    + m# ?- t* a8 z3 y6 l# f* X6 d: w
  673.             max_height = height;/ w0 c- Y7 s; z* ~- U3 o
  674.         height = LE_16(&rbt->frame_load_buffer[6]);
    9 q- ?: D3 W( ~- x- T1 T- S
  675.         frame_x = LE_16(&rbt->frame_load_buffer[12]);' I1 C  y, |9 H7 a9 R7 s
  676.         frame_y = LE_16(&rbt->frame_load_buffer[14]);' F7 E9 J0 n1 W( i6 l  ~
  677.         fragment_count = LE_16(&rbt->frame_load_buffer[18]);
    ' n& K- `7 Q1 z0 K4 j: {. O3 J
  678.         decoded_size = width * height;
    + {% ^: G% j. R6 L/ v4 M
  679. $ M+ k; K9 O5 i: @
  680.         printf("processing frame %d: %d%%, %dx%d, origin @ (%d, %d), %d fragments\n", i, scale, width, height, frame_x, frame_y, fragment_count);4 F6 E2 M& e4 H

  681. 8 X  u, Y' a* Z& v
  682.         /* decode the frame */9 Z1 W3 r9 n4 J! b# y
  683.         decoded_frame = malloc(decoded_size);
    6 i; z  C4 z( y) v" R7 X6 c' B
  684.         index = 24;
    6 m1 u# D- Z: L; B' h; D- J. e
  685.         out_index = 0;
    : r: E- e3 K  @, H9 i: M* o1 H
  686.         for (fragment = 0; fragment < fragment_count; fragment++)2 t. J) g) Y8 r/ j
  687.         {( j: G' }& H$ l; ]9 S
  688.             fragment_compressed_size = LE_32(&rbt->frame_load_buffer[index]);
    + A& h4 i+ N" e# N, {# }
  689.             index += 4;! b. u- n" ~+ D
  690.             fragment_decompressed_size = LE_32(&rbt->frame_load_buffer[index]);
    1 L1 G% ^, U6 ~. F& g; {. ~
  691.             index += 4;
    % l4 ^7 I, S' B3 o% y' {
  692.             compression_type = LE_16(&rbt->frame_load_buffer[index]);- ^0 O4 g: N$ T' X6 ]8 W$ l1 W
  693.             index += 2;3 F4 K' ^" h1 k5 I5 c  S

  694. : w+ E. U( z" r# @- K
  695.             if (compression_type == 0): k2 N6 N7 t! m: C& ~; g9 m/ X
  696.             {, s) {/ G* V7 U) N# O5 f3 c: _! A! P
  697.                 init_get_bits(&gb, &rbt->frame_load_buffer[index],
    / C' _, e4 V* `) S4 u- J% u4 {
  698.                     fragment_compressed_size);
    / }$ ]' r! b$ h3 E3 J4 H5 v) T1 [2 l

  699. 5 K4 l0 o. N6 p+ i
  700.                 while (out_index < fragment_decompressed_size)* y( }) _! I- P! X5 r( [. k  g
  701.                 {" O; ^4 J+ A; ~9 N4 |% k
  702.                     if (read_bits(&gb, 1))
    : b2 h2 p. p" w3 D7 I8 U  w5 p
  703.                     {' g( {6 Y: J) T( ?
  704.                         /* decode back reference offset type */* G" g' n0 b0 a( ?
  705.                         back_ref_offset_type = read_bits(&gb, 1);
    1 v7 ]! E+ j: T9 w
  706. / E5 k) X5 Z: c( R# [1 H
  707.                         /* back reference offset is 7 or 11 bits */
    1 t2 p3 Y# ~% S! q$ P2 q4 @- a
  708.                         back_ref_offset = read_bits(&gb,
    ( d- X: Q7 e( k. Q3 O2 B
  709.                             (back_ref_offset_type) ? 7 : 11);* ]  K  d! x" i- \
  710. ) _( S9 [+ [$ t" @+ Z
  711.                         /* get the length of the back reference */' G" s. m/ r1 o: V
  712.                         back_ref_length = get_lzs_back_ref_length(&gb);
    5 E5 t# W( H# Y4 s. n5 f
  713.                         back_ref_start = out_index - back_ref_offset;8 g2 x- l; }$ x) P3 v2 Z; D
  714.                         back_ref_end = back_ref_start + back_ref_length;
    & E# l, l# N! ~) i8 I& Q( G

  715. 8 H& u$ U1 ?, O3 h, @2 J% j
  716.                         /* copy the back reference, byte by byte */
    3 C+ }$ [( \& W# D- `
  717.                         for (j = back_ref_start; j < back_ref_end; j++)
    4 R, h; O5 ?6 v6 @8 t
  718.                             decoded_frame[out_index++] = decoded_frame[j];
    4 u) l6 T7 l; d. E! F
  719.                     }
    . b8 X, N* {% U1 \1 F( a6 s5 D
  720.                     else  d" t% i( [( @
  721.                     {7 ?8 u$ ?8 R2 _( x
  722.                         /* read raw pixel byte */
    , q9 a; [# X' E* V; D4 X  D
  723.                         decoded_frame[out_index++] = read_bits(&gb, 8) & 0xFF;
    0 h* ?  `8 V. h3 z5 \: Z
  724.                     }
    $ X/ a* }! J% r  e1 j/ q. m4 C: z7 N
  725.                 }
    : j; ]" _  a) {0 ?) G6 s$ V  s  S$ ~3 T
  726. ' U& m, U9 G* p5 X3 l) H! D) r# s9 p
  727.                 delete_get_bits(&gb);
    ) N, Y/ a7 j' y# M5 {/ A
  728.             }
    4 X4 L" {; Z4 @! U, Q, G* t3 n
  729. * H) E$ Q" N2 s$ E
  730.             /* next fragment */& n* X1 h8 I7 q8 O  U1 O
  731.             index += fragment_compressed_size;' a& }* X) ^2 x8 h% |# T
  732.         }& H$ I% Y& j5 y/ C- w

  733. 6 i" ^4 f8 V% U% |- W9 w9 k& k; b
  734.         if (rbt->dump_frames)
    ' Q6 z- K- E9 F% F* s, V
  735.         {
    8 a, X; ?! z; @- u8 z
  736.             /* dump the original frame */
    ' P* Z- y7 Z9 }5 w! c; `8 m
  737.             sprintf(filename, "original-frame-%03d.pnm", i);) x1 K; ]9 \3 `: z$ ~+ z2 x
  738.             dump_pnm_file(filename, rbt, decoded_frame, width, height);
    9 P1 B; m  ?6 Z1 L' l$ q
  739.         }
      q  S7 k8 a9 x/ x8 z- U( o6 g

  740. ' S' |, l$ W" f$ Z( w: E: b
  741.         /* transfer the image onto the frame window */
    ) Q3 J4 t1 l! d' ^- ]
  742.         memset(full_window, 0xFF, full_window_size);
    3 T3 K9 a; ~4 y' W% _, p7 a
  743.         index = 0;% b, x! b: N: t0 c. k
  744.         for (y = 0; y < height; y++)9 w" p. K8 W8 c
  745.         {
    7 r$ l$ h6 {% B8 [! |
  746.             out_index = window_width * (frame_y + y) + frame_x;1 f( p2 T( K9 H% x4 V2 u1 J
  747.             memcpy(&full_window[out_index], &decoded_frame[index], width);
    3 s+ h; Y# x4 H/ z
  748.             index += width;' l9 {6 }) G9 H. |3 U3 z
  749.         }
    . L, T9 \. E# o+ ~' a

  750. $ k, g8 L; F% i) O3 i% `' @
  751.         /* write the subtitle */# M( }; }2 ^3 p* B/ V2 Z
  752.         subtitle_frame(rbt, full_window, window_width, window_height,
    & p  S3 J" ^: v1 O! I
  753.             i * MILLISECONDS_PER_FRAME);2 P) G2 g  @6 X. l" t* G( W! y# E

  754. % P6 H& H. T, k" u% u
  755.         /* figure out the smallest change window */
    1 `, p% t$ w  [6 \0 Z
  756.         window_top = frame_y;$ L9 i. L) g" z' h  G7 s
  757.         window_bottom = window_height;
    4 W# l* N0 f$ S0 O% G
  758.         window_left = 0;
    & X! ?5 a8 T' C6 b3 \
  759.         window_right = window_width;6 Y; \2 [" A4 g  q/ Z& V" k- T
  760.         window_size = (window_right - window_left) * (window_bottom - window_top);6 K2 W" {$ ~- K, u
  761. ' i7 O( U: A# P5 D
  762.         /* compress the frame */  _8 a- t! O$ S1 s
  763.         reset_put_bits(pb);- @' `9 m# u2 L! t3 q3 O) H1 e7 t
  764.         compress_window(pb, full_window, window_width, window_top,
    , K/ P% Z6 i2 C$ V
  765.             window_bottom, window_left, window_right);: ^2 x1 e8 L* w# i2 Y7 v, i" S

  766. / R! y2 m7 V( N* N
  767.         if (rbt->dump_frames)
    , z4 b( W+ }- P
  768.         {7 m" ^$ K0 K6 G- j1 y
  769.             /* dump the frame plotted onto the full window prior to encoding,0 u; w; y) P9 b. K( l2 E5 Y! c
  770.              * with subtitle */
      w: ~) A2 K- D# s' V# K9 E. v+ F
  771.             sprintf(filename, "pre-encoding-frame-%03d.pnm", i);* B  l" d& b" T4 R; G6 Z
  772.             dump_pnm_file(filename, rbt, full_window, window_width, window_height);- t1 x8 K; _7 S. @3 J9 X& ]+ x
  773.         }1 K# p) \/ W! B
  774. & F6 b9 T: U2 s! m# v, ^; ]
  775.         free(decoded_frame);* U3 ^- H5 r# {% P3 m+ F; @- e4 _
  776. - x6 [# i# _9 W% i6 K% [
  777.         /* update the frame header */. q8 @5 M& N4 ~$ T, ^% J
  778.         /* width */( m0 D& S8 H7 e0 ], w5 q
  779.         rbt->frame_load_buffer[4] = (window_right - window_left) & 0xFF;# S" w5 V/ _, J9 [) S
  780.         rbt->frame_load_buffer[5] = (window_right - window_left) >> 8;
    / s9 e  ^8 i# X$ g9 R
  781.         /* height */
    # T# ~  @4 z  ^
  782.         rbt->frame_load_buffer[6] = (window_bottom - window_top) & 0xFF;* D) w, }9 |( @
  783.         rbt->frame_load_buffer[7] = (window_bottom - window_top) >> 8;# ~$ V3 E$ E4 h( m/ p; @
  784.         /* origin X */2 f" _4 e$ q! P% L! v6 l* Q
  785.         rbt->frame_load_buffer[12] = window_left & 0xFF;' t* w5 ?0 ]3 n* c: h5 B3 `' m
  786.         rbt->frame_load_buffer[13] = window_left >> 8;  w0 h1 y" ^) V6 b4 e* a) |. V
  787.         /* origin Y */5 @- W1 T( G- r4 X* x2 e
  788.         rbt->frame_load_buffer[14] = window_top & 0xFF;9 x  q, C# ~- d; ]
  789.         rbt->frame_load_buffer[15] = window_top >> 8;5 I1 f+ x" C9 W  Y- s5 l/ U
  790.         /* fragment payload size */
    * v: _/ d1 q2 C. |! |1 N
  791.         rbt->frame_load_buffer[16] = (pb->byte_index + 10) & 0xFF;
    $ Q; w' x* F6 l# ?: K  w3 }/ m
  792.         rbt->frame_load_buffer[17] = (pb->byte_index + 10) >> 8;5 k- B8 P" l* L6 n1 m+ v7 p! {+ B$ E
  793.         /* fragment count (1) */
    ) S6 @6 Q* A1 Q  K8 d" p
  794.         rbt->frame_load_buffer[18] = 1;$ w& _" p0 O) l1 N+ t
  795.         rbt->frame_load_buffer[19] = 0;
    # V1 p* N$ r1 A; [6 {5 {7 g1 W
  796. 0 M) \* e& J, [+ |! U% Z
  797.         /* update the fragment header */
    1 m/ M1 y( h7 o8 l6 D3 Z* [8 E, r
  798.         /* compressed size */
    ) ^% o4 _- ^3 \% H) z- K
  799.         rbt->frame_load_buffer[24 + 0] = (pb->byte_index >>  0) & 0xFF;+ \( _9 b+ y9 O/ O4 e
  800.         rbt->frame_load_buffer[24 + 1] = (pb->byte_index >>  8) & 0xFF;) s6 _3 X7 ?1 C6 L; ~
  801.         rbt->frame_load_buffer[24 + 2] = (pb->byte_index >> 16) & 0xFF;: e% p" B2 I. p5 l3 \
  802.         rbt->frame_load_buffer[24 + 3] = (pb->byte_index >> 24) & 0xFF;, G8 ]  \$ h. k
  803.         /* decompressed size */, P8 U3 Q5 Y8 Z
  804.         rbt->frame_load_buffer[24 + 4] = (window_size >>  0) & 0xFF;5 g. Y/ T. ?3 @
  805.         rbt->frame_load_buffer[24 + 5] = (window_size >>  8) & 0xFF;
    2 z1 R. e9 w$ V1 l. F" s. {
  806.         rbt->frame_load_buffer[24 + 6] = (window_size >> 16) & 0xFF;
    4 c& E0 u) D! c* o5 J
  807.         rbt->frame_load_buffer[24 + 7] = (window_size >> 24) & 0xFF;$ g2 `$ l# y9 x0 n$ n9 Q
  808.         /* compression format 0 */" j  G1 E& c% S* o$ t
  809.         rbt->frame_load_buffer[24 + 8] = 0;/ j5 W# ]6 N$ T' \
  810.         rbt->frame_load_buffer[24 + 9] = 0;
    ' S0 ~! h/ M/ Z! W; ^
  811. ( A0 X3 [. j" W! x. r
  812.         /* write the 24-byte frame header and the 10-byte fragment header */
    4 T$ ~- {1 d$ _6 C, {
  813.         if (fwrite(rbt->frame_load_buffer, 24 + 10, 1, outrbt_file) != 1)% _  \6 Y0 B2 K6 E1 W. H
  814.         {! G0 {! Z" H/ O" L
  815.             printf("problem writing frame %d\n", i);4 F2 }# V' t6 n+ R6 B3 R3 F# L
  816.             return 0;
    : Y1 ~) ]( d+ A
  817.         }6 W7 K# {* U: q+ i  x/ E7 a

  818. % r2 e; k3 f6 J9 r% [7 l" Q
  819.         /* write the new compressed frame data */
    0 _* I6 a$ r2 V' D
  820.         if (fwrite(pb->bytes, pb->byte_index, 1, outrbt_file) != 1)
    3 s5 B) ~  u0 c* I# P
  821.         {
    7 C- P0 A; _  d
  822.             printf("problem writing frame %d\n", i);* ^" H0 q7 `3 c9 @4 x
  823.             return 0;
    : K7 C% g* ?7 C- p; Q5 V
  824.         }, Q4 d0 t; M7 a! W! a* W- b

  825. : y! j3 V% ^' M4 ~$ ~+ J4 V
  826.         /* write the audio data */6 Y. O- K" f# \, h
  827.         if (fwrite(&rbt->frame_load_buffer[video_frame_size], frame_size - video_frame_size, 1, outrbt_file) != 1)1 H  A# S: N" q1 a% G
  828.         {  T: ?* f% y' p' Q, j6 _9 A
  829.             printf("problem writing frame %d\n", i);
    9 E3 ^: T: Q( R& N6 a
  830.             return 0;( y( K, l6 u) p4 b
  831.         }+ p3 e8 c6 z+ Q" s8 O( C# x' s' T

  832. , |# z. x8 X! F/ d. ]6 f  B0 H
  833.         /* update the table entries */
    4 d' x7 U6 D' P; [" ]5 Q" j
  834.         video_frame_size = pb->byte_index + 24 + 10;
    * |: m3 P) S" ?3 ^
  835.         frame_size = video_frame_size + audio_frame_size;8 m2 z8 @- r" m( ^8 K
  836.         rbt->frame_size_table[i*2+0] = frame_size & 0xFF;
    . U6 j8 h0 R. s8 r2 B# o' a3 D
  837.         rbt->frame_size_table[i*2+1] = frame_size >> 8;0 `* M7 o8 T7 V- Q
  838.         rbt->video_frame_size_table[i*2+0] = video_frame_size & 0xFF;
      `$ d2 f3 L5 y) `7 {# f* d
  839.         rbt->video_frame_size_table[i*2+1] = video_frame_size >> 8;
    . r6 J  g( H& x$ T. q) J6 ?
  840.     }
    & O+ r. t+ q0 z- q  b
  841. & D" q$ M. _1 W
  842.     printf("maximum dimensions seen are %dx%d\n", max_width, max_height);, F& ?& _; ]1 N  i" H

  843. 3 Z. x0 }$ Y0 n
  844.     delete_put_bits(pb);
    2 \# d9 h% |- S; v1 ]
  845.     free(full_window);
    / m( g/ ]' A0 |

  846. 7 S2 }! Y" k8 Y: o& D
  847.     return 1;7 R' b2 B; l- z
  848. }7 n7 f/ K5 |4 Z8 \* N+ m

  849. , l/ y: r% s- s, m) u( I
  850. int main(int argc, char *argv[])+ a9 `3 H+ d+ c4 Z. u4 t2 J
  851. {
    ) y+ k2 y7 r3 B6 U) e* K
  852.     char *subtitle_filename;
    $ Y& n- E0 u1 u& U( G, K. O9 Q0 ]2 ~
  853.     FILE *subtitle_file;
    2 ?* j/ n+ m9 Y; e* O" c) w, ?6 j
  854.     char *inrbt_filename;) f9 ]& C: k4 v0 F
  855.     FILE *inrbt_file;
    2 S& M) j+ \8 Y$ Q* W
  856.     char *outrbt_filename;  S1 f% t% D$ \) p  g
  857.     FILE *outrbt_file;
    ) N' W, b; Y# f* ~' q1 V. z2 z
  858.     rbt_dec_context rbt;
    $ ~3 \" I, ?4 j' P; b: I
  859.     int origin_x;
    # F7 {" A5 t1 J: L8 {
  860.     int origin_y;' z. j+ x  L6 ?3 G, P
  861.     int window_width;
    " g1 j3 h% }7 m9 g3 ^' ?/ |  Y2 |
  862.     int window_height;) I3 a, P5 T3 y9 {

  863. + M5 Z: \! S" C# K8 e% O* J
  864.     /* testing the bit functions */) y2 A7 }& h$ r( |( t# S* t
  865. #if 0( h: x( ^9 }' P% _0 i
  866.     int i;
    : `( u+ I0 [, n, D
  867.     uint8_t bytestream[] = { 0x55, 0xAA, 0x00, 0xAA, 0x55, 0x77, 0xFF, 0x1B, 0x70, 0x8F };5 a/ |# M! t2 e3 E
  868.     int bytestream_size = 10;+ h8 N7 S8 Q7 c. d# o% c! G
  869.     get_bits_context gb;
    4 @" e3 ]% [/ z% g% i
  870.     put_bits_context *pb;7 r% @$ ^# [  p1 n
  871.     int bits;
    ; ~& x- T  B% U1 i* c

  872. # c9 l6 n. H: G5 d
  873.     init_get_bits(&gb, bytestream, bytestream_size);" H$ X. s7 r1 m6 v
  874.     pb = init_put_bits();- K1 _: ^. \* d4 E
  875. . D* t' h& c" d- A6 y6 u
  876.     for (i = 1; i <= 12; i++)
    8 d/ T/ U3 d, J% o8 \
  877.     {
    - B; `/ ]& Q( d5 Y
  878.         bits = view_bits(&gb, i);  ?% f9 V! G5 v) I  T3 P
  879.         printf("view %d bits: %d\n", i, bits);
    ( A7 ?# N, u' g) ~6 e
  880.         printf("read %d bits: %d\n", i, read_bits(&gb, i));) I& i0 B$ q. E+ U$ t
  881.         put_bits(pb, bits, i);# C" M& c6 n; o" c2 z
  882.     }
    ! R' J+ K0 C0 o# a. {% {7 i$ `
  883.     put_bits_flush(pb);
    5 T2 D% B1 T# z, d
  884.   c) k- m* H3 i
  885.     printf("original bytestream:\n");
    7 |# s+ `9 ]$ d& {0 z; F
  886.     for (i = 0; i < bytestream_size; i++)
    1 p; m  p  y5 |5 k- }8 I0 [/ P/ h
  887.         printf(" %02X", bytestream[i]);
    : \  `4 X1 t$ k7 x
  888.     printf("\nnewbytestream:\n");# F; L4 n$ X" [. ^$ f- ~; p
  889.     for (i = 0; i < pb->byte_index; i++)- L9 a! ~0 x9 z, p1 W' n* h
  890.         printf(" %02X", pb->bytes[i]);" T# D& B- T( `6 Z% T
  891.     printf("\n");
    8 N+ R+ N5 i+ }; `& @
  892. 1 b+ f; n: w1 j- c- j
  893.     delete_get_bits(&gb);, N7 c) X0 t" j& n
  894.     free(pb);
    4 g* Y5 g" p: H7 k
  895. #endif5 z& I6 `6 t. H' v# Q- |! S$ j
  896. 4 V' B! @* M( v$ T9 ~" z$ j; S& D1 M9 H
  897.     /* validate the number of arguments */% }+ m0 B$ z3 N' p0 o/ W
  898.     if (argc != 8 && argc != 9)
    $ l- B* m8 A$ i1 o
  899.     {/ V! d+ u) J9 {7 Q
  900.         printf("USAGE: subtitle-rbt <subtitles.ass> <in.rbt> <out.rbt> <origin X> <origin Y> <width> <height> [dump_frames]\n");. h) N# J* R' p: F& g
  901.         return 1;
    7 H2 ^% y( Y' i4 P2 S4 f
  902.     }
    ; p0 F4 Z; B# R$ V
  903.     subtitle_filename = argv[1];8 S- ]% L+ T' L/ Z$ I' `, V2 C
  904.     inrbt_filename = argv[2];
    6 K! h% E2 g6 b/ @0 e, Q- V
  905.     outrbt_filename = argv[3];
    ' {* N2 x+ E& _& O
  906.     origin_x = atoi(argv[4]);8 i2 F' w8 i& I3 E2 T
  907.     origin_y = atoi(argv[5]);6 d* f& @/ ^( M3 z3 x
  908.     window_width = atoi(argv[6]);
    * P% ]' _9 r1 V6 R' n
  909.     window_height = atoi(argv[7]);: l( |' y/ t* H0 m& G& H2 v( _8 R
  910.     rbt.dump_frames = 0;
    . L) H5 p' H: K
  911.     if (argc == 9)
    : S0 n. @: L+ N' s3 ^0 F
  912.         rbt.dump_frames = 1;
    & @4 O: s# [) R2 W" Z7 e+ `
  913. 2 Y( M3 ~9 h6 c0 v+ A% D
  914.     /* verify that the specified input files are valid */
    6 Y+ ]( o* |8 h2 y5 i# x) Q
  915.     subtitle_file = fopen(subtitle_filename, "r");
      u1 X% D& v* }9 L
  916.     if (!subtitle_file)  H$ T5 _; U8 r9 t& T
  917.     {+ X4 l' p7 Y( B% @' I( C" w- E# s0 M& N
  918.         perror(subtitle_filename);
    ! i6 F! I4 _- q6 p. H; `
  919.         return 1;
    ' e5 e. z% [) f" b
  920.     }
    % F- V, D8 e$ e9 r* j' z
  921.     fclose(subtitle_file);/ B8 K+ d- E; q  e4 k% S+ a& @/ v" Z
  922.     inrbt_file = fopen(inrbt_filename, "rb");
    % J7 K! S0 @' g: g. W/ [0 C% C
  923.     if (!inrbt_file)
    ! a2 }* _. {! ~7 O) M$ \% J
  924.     {
    ' h/ x+ j% S* j1 V# g$ @
  925.         perror(inrbt_filename);
    % }% n, a& f  L- x# j9 K4 P
  926.         return 1;
    6 r: m# c% g3 u/ H$ ?; K
  927.     }
    " C3 B( k/ D( g7 J$ r* ?2 Q
  928. ' z$ l) P, Y7 }4 M. S) o# ?
  929.     /* initialize the subtitle support */
    7 Q7 j7 @) k8 s  D. ^7 ]
  930.     rbt.ass_lib = ass_library_init();* Y/ |) ~1 A# ^
  931.     rbt.ass_renderer = ass_renderer_init(rbt.ass_lib);
    - i* ^1 H5 a% w# h1 i
  932.     rbt.ass_track = ass_read_file(rbt.ass_lib, subtitle_filename, "UTF-8");
    9 z4 o/ H1 P: q! f& i
  933.     ass_set_frame_size(rbt.ass_renderer, window_width, window_height);* b, u0 a4 i) k' ]
  934.     ass_set_fonts(rbt.ass_renderer, NULL, NULL, 1, NULL, 1);
    - \+ L# y$ J3 E" R) {

  935. ( P3 `' K1 ~5 P& C$ ^8 N2 l! Y/ M% W
  936.     /* open the output file */, `1 P; M3 l% }- g" S8 z2 u. z
  937.     outrbt_file = fopen(outrbt_filename, "wb");
    3 U2 z1 u, v3 Q8 R" J
  938.     if (!outrbt_file)& f$ y, x9 X4 O4 ?
  939.     {
    - ]8 D  F  x' B/ N/ H
  940.         perror(outrbt_filename);
    % v% p- [' ?$ s
  941.         return 1;
    4 b! Z. v/ f, T) {7 T' H& a1 V
  942.     }
    2 x' ~& c8 E. ]7 b) C

  943. 4 ~1 ^1 V1 }  R. D
  944.     /* transfer header from input to output */
    ' l. I: Z& y& T" {4 r1 S  s
  945.     if (!load_and_copy_rbt_header(&rbt, inrbt_file, outrbt_file))
    6 N: J' k! |: m5 s; q
  946.         return 1;8 n* N2 [6 {! R# Y3 Y) I1 ~' f

  947. : |0 ^) Z4 R& L# u; b8 N, {0 w" M* B
  948.     /* rewrite the frames */
    ! W& L, k( i! z9 R% E' A0 U
  949.     if (!copy_frames(&rbt, inrbt_file, outrbt_file, origin_x, origin_y,
    - }! s# H. b6 a* T
  950.         window_width, window_height))4 E$ [) q3 }6 ?
  951.         return 1;
    ( C+ ]/ C* {/ p  x0 y
  952. . n# i1 o" N2 s+ w: {
  953.     /* write the modified frame size tables back to the file */
      ^; j( H! X6 |* A1 A+ x9 X1 B
  954.     fseek(outrbt_file, rbt.video_frame_size_table_offset, SEEK_SET);
    8 ]2 }( E1 w4 k- T
  955.     fwrite(rbt.video_frame_size_table, rbt.frame_count * sizeof(uint16_t), 1, outrbt_file);/ f2 y3 ?1 V6 C
  956.     fseek(outrbt_file, rbt.frame_size_table_offset, SEEK_SET);
    ) H; Y8 t2 D2 w
  957.     fwrite(rbt.frame_size_table, rbt.frame_count * sizeof(uint16_t), 1, outrbt_file);
    9 w( `0 X$ D& K+ L
  958. 8 f: ~( J9 K# s! {5 o; S- q
  959.     /* finished with files */
    ' d; \" B0 Y: X6 o9 J) V
  960.     fclose(inrbt_file);
    # ^  n# W, P+ T& c  P( c
  961.     fclose(outrbt_file);+ Q: `. g$ h  u, o# n8 o

  962. 5 q8 ^' _$ ~# h
  963.     /* clean up subtitle library */, |& F& E  }" L! Y; d# \' A
  964.     ass_free_track(rbt.ass_track);
    : T4 c8 t0 g$ d* P1 c/ e5 w% O$ o2 F
  965.     ass_renderer_done(rbt.ass_renderer);
    3 \( Q/ A: U# C2 e/ l8 z! e
  966.     ass_library_done(rbt.ass_lib);
    1 U% f# Z; @4 Q9 a% b, `% n

  967. % _- R1 G4 O8 G$ @0 G) L
  968.     /* clean up */2 Z. i( y" ?+ G
  969.     free(rbt.frame_load_buffer);2 n4 ?1 m& [3 t! K5 v
  970.     free(rbt.video_frame_size_table);& d& e! V4 W; f/ `8 X
  971.     free(rbt.frame_size_table);
    - ?7 c# P( w) [4 j; Q- U. S8 x
  972. ( i# M0 f  D2 w5 a2 g
  973.     return 0;
    6 G& f' e/ ^6 [% b! x7 o3 h3 D9 E: N
  974. }
复制代码
3 ?  Y0 _( p  E& W- `# B5 G# M

' b  M5 P' r+ ?' i1 H3 k: k, M- I5 c9 @

4 K- d0 R. H% y2 h- f# w
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 很美好很美好 很差劲很差劲
回复

使用道具 举报

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

使用道具 举报

板凳
 楼主| 发表于 2009-11-19 11:38 | 只看该作者
引用第1楼soring123于2009-11-19 11:09发表的  :% s+ E( O, I. B( Z
这游戏有字幕吗?
) u' F# m: `4 e1 K- e
好像没有字幕,我说的是给视频外挂字幕方式的汉化。
9 u& U& G3 r% E! m- c! G" x# z就像syberia2汉化版下面那行字一样。
回复 支持 反对

使用道具 举报

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

使用道具 举报

5#
 楼主| 发表于 2009-11-19 17:39 | 只看该作者
引用第3楼soring123于2009-11-19 17:07发表的  :
! q: K1 k, `. v# b: Z2 I& f我记得是没字幕的 比较麻烦 都是视频的
. w7 H" x& `$ Z1 L" @; D
给视频外挂字幕方式汉化也许能行。# O2 k" x0 C' ^3 A
要结合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日,是全球华人共同的冒险解谜类游戏家园。我们致力于提供各类冒险游戏资讯供大家学习交流。本站所有资源均不用于商业用途。

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