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

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

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

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

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

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

本帖最后由 shane007 于 2021-1-2 13:56 编辑
9 x4 Y* I0 d. t0 R/ v- c* o) i$ {, y  Y$ N. H: u
最近找到了一些和幽魂系列Phantasmagoria 有关的资料,6 d1 p# W3 p) h  P4 ]2 l8 r
也许将来可以用于汉化。
( K) Q  V/ i# {! z+ s4 L( |6 t( U' E& ]* N
和日文版有关的信息6 N- Y+ k/ x" }* ^
http://anthonylarme.tripod.com/phantas/phintgtp.html1 x5 }( u8 s3 b# i2 x# C
1 q. ?" x# `4 w7 K. O
相关工具' O4 ]. V& D' u
http://anthonylarme.tripod.com/phantas/phcheats.html1 O( Q. L. _: g' t& ?
-----------------------------------------------------------------------! Q$ o3 d4 C6 r
2012/1/2  更新
' X3 ~8 a& Z8 x1 O! A关于幽魂游戏的字幕( A' }+ z: l2 E+ {) g. y
Phantasmagoria subtitles function discovered - ScummVM :: Forums
: ^; b  y) w5 F) {8 ~! Z' f7 K/ `8 m/ D0 Y1 I) ~( x
VMD文件# w: v! x1 w2 F' B) h3 P0 N7 @0 c
Subtitling Sierra VMD Files | Breaking Eggs And Making Omelettes (multimedia.cx)VMD - MultimediaWiki
4 s1 @1 F- ~- D5 P* U0 \* W1 `# Y/ I
字幕
" X2 C0 V) B% eSubtitling Sierra RBT Files | Breaking Eggs And Making Omelettes (multimedia.cx)
' S- [/ T& C9 ?+ l
+ s1 X8 k' l- e; V9 `) X2 a: y. TFFmpeg/subtitle-rbt.c at feature/VMD_encoder · multimediamike/FFmpeg · GitHub
2 r7 R$ }0 }3 q$ L( M! ?* W, x; z0 I
  1. /*6 I% o2 P' x/ n! s, @& _2 u  r
  2. * subtitle-rbt.c/ A6 ~1 w: C! p
  3. *  by Mike Melanson (mike -at- multimedia.cx). z2 ]) Q* {( p
  4. *
    , U9 o( H/ a% w+ @: G5 y
  5. * build with this command:6 d3 p6 |6 M: R( p( c5 N
  6. *   gcc -g -Wall subtitle-rbt.c -o subtitle-rbt -lm -lass
      f; P, G( P, ]7 P3 e
  7. */, M* p0 ?- t* i. D6 A* N8 M. ~
  8.   N& x! c4 t4 k  t  t  n
  9. #include <inttypes.h>9 c2 ]8 q( g) w5 l/ M
  10. #include <math.h>+ z, f, f5 B2 L$ Z& I# i6 D6 C
  11. #include <stdio.h>
    / g  ^: g& o8 f. ?9 a9 d0 A) u
  12. #include <stdlib.h>
    + U; c0 W* o+ l+ r" K
  13. #include <string.h>0 u% \" r; c8 w1 {- ?5 J! d3 y" P

  14. ( [* N: I! q2 ^1 M+ i
  15. #include <ass/ass.h>
    , o( g. E; R4 B- H  }

  16. 5 C, Z/ ], m: L. I: j5 l/ n
  17. #define LE_16(x) ((((uint8_t*)(x))[1] <<  8) | ((uint8_t*)(x))[0])$ N0 T/ y1 Y! z& i/ f+ {% W
  18. 0 T9 c. B( T% d, `. m; N
  19. #define LE_32(x) (((uint32_t)(((uint8_t*)(x))[3]) << 24) |  \
    : f- S. m& `: H$ I4 n- s9 i, A- P9 K
  20.                              (((uint8_t*)(x))[2]  << 16) |  \
    3 m& N8 R$ s1 X/ L8 K) x
  21.                              (((uint8_t*)(x))[1]  <<  8) |  \
    : [  R4 ?8 S' a! O
  22.                               ((uint8_t*)(x))[0])
    . K+ i6 Q+ s. f3 o

  23. 9 ^' M# E; ~, Z: t7 R' U. q  O) p7 v
  24. /*********************************************************************/; u' |1 _/ v+ M9 D5 k
  25.   P4 D- |5 _2 e
  26. /* Bit reader stuff */1 A" a4 J2 \2 q5 A4 q* u% z

  27. % k* U/ M) y% b
  28. typedef struct
    # I6 T; A6 n" F4 ~
  29. {
    0 ?7 w& b. O& B$ t! M0 Y6 g
  30.     uint8_t *bytestream;" Y" P2 M  j  d
  31.     int bytestream_size;1 E' ~1 V) P6 @% w7 T8 c+ {, e
  32.     int index;& |# V: B( T' T, j
  33.     uint32_t bits;: a$ t% u" E: ], m
  34.     int bits_in_buffer;4 g: z" D4 ]1 N. \( p# o
  35. } get_bits_context;
    0 ~; X, v+ l  A% q* p; H
  36. " W$ v+ x8 z2 ^: g
  37. static inline void reload_bits(get_bits_context *gb)
    & k0 l# R! l  h$ k" r  [
  38. {7 `3 u7 j& g% E/ {4 G+ R3 t2 ^
  39.     while (gb->bits_in_buffer <= 24)
      A0 X7 r  ~  C9 i' ~( E
  40.     {
    9 D8 M5 @/ @# }( w
  41.         if (gb->index < gb->bytestream_size)' x" W1 L3 W! E! A! \$ L
  42.             gb->bits |= (gb->bytestream[gb->index++] << (24 - gb->bits_in_buffer));
    . B( C- Z' I! ^: ?
  43.         gb->bits_in_buffer += 8;
    4 B3 N* K9 H; U. B# [) d  z$ k
  44.     }$ V+ ]- ]. `( _/ S
  45. }
    5 i+ @! l: `& G$ k

  46. 5 ]. G6 w( S2 Z0 Z1 X
  47. static void init_get_bits(get_bits_context *gb, uint8_t *bytestream, int size)
    $ x  n# l6 b' u( W! f
  48. {( B# m5 }& j- B/ F
  49.     gb->bytestream = malloc(size);# N- d  _& n  m% d8 ~: d4 P
  50.     memcpy(gb->bytestream, bytestream, size);
    - I, v$ ?9 Z- `
  51.     gb->bytestream_size = size;
    % c) z1 h1 Q- r, A
  52.     gb->index = 0;
    $ Q1 U! _% n: Z5 E2 c
  53.     gb->bits = 0;
    4 X$ s$ P! j0 e8 b% |- j5 n
  54.     gb->bits_in_buffer = 0;7 o- r# N- i# S/ i5 @% o  ?
  55. 7 T1 q7 {7 ^( s' V* `# F
  56.     reload_bits(gb);5 N) Q; a" V- r9 u9 F' Q4 R3 _- k) j
  57. }
    7 k0 b3 z8 f$ m0 M9 l, R

  58. ( Q* L+ z8 M% x. Z2 |; G
  59. /* read bits without consuming them from the stream */! Y. g( L. R- Z& i
  60. static int view_bits(get_bits_context *gb, int count)' z/ X. E; u) Y: M7 w. V
  61. {
    : T0 G! s, v' J7 W: M
  62.     if (count >= 24), t: {" [# J- Y- Q
  63.         return -1;
    9 m* ^- ^1 `+ C" d: `) G( n8 F
  64.     if (gb->bits_in_buffer < count)
    7 z+ G- _& _% r6 m5 B) y6 U. s
  65.         reload_bits(gb);
    & L5 |& _$ c, L; C5 D/ X
  66.     return (gb->bits >> (32 - count));
    6 c* i; Y  ]' x: z$ [6 o2 m
  67. }; d5 L5 e& A  \0 S8 y7 E& G8 V
  68. ( B3 d' Z, n* {7 f& J$ [% ~
  69. /* read and consume bits from the stream */
    ( J1 z8 P7 W9 E3 B3 A! I& }5 T
  70. static int read_bits(get_bits_context *gb, int count)
    * j6 X; B/ G- ?: x$ o! v
  71. {( R1 f; f: @: }9 Q3 A9 S9 T3 G. E+ p
  72.     int value;
      R% r3 [; ]* x- v; ]3 P

  73. * d3 K, z0 y+ C6 {5 m# N
  74.     if (count >= 24)
    % R9 @, `" H2 Q& h4 _
  75.         return -1;) B4 R5 N. Y$ u1 N! f2 D( ?' w
  76. 0 T. P3 p8 Z5 w+ F' X! S2 ^
  77.     value = view_bits(gb, count);
    & T: O. P& U, z; i8 p% i0 a, E
  78.     gb->bits <<= count;
      Q8 x, ?% q" j( E* H1 b
  79.     gb->bits_in_buffer -= count;0 p& O: _6 {/ U8 d' _
  80.   r  B9 V6 ~+ _/ _3 z! E
  81.     return value;
    ! H6 F; R' i+ h) f: h6 B3 w7 O! W! i
  82. }; [' a' M8 v2 T9 Z

  83. 0 L9 b  B7 o; ?0 q; M
  84. static void delete_get_bits(get_bits_context *gb)
    % z6 _3 a4 k6 X# @9 {
  85. {
      G9 Q2 D" n! A" Y; H, b! {
  86.     free(gb->bytestream);
    & A& t) ?+ ?4 j/ T2 L* v+ `3 a" E; n
  87. }/ b5 d: h6 [3 H- J

  88. . N5 i  ]2 Y! ~- _) ^2 H% O9 ~
  89. /*********************************************************************/" z! o" u; K. i. v' P$ C
  90. ; b0 C1 `' k! J) g& b' p2 i
  91. /* Bit writer stuff */
    / J* V; O- M0 C) r6 P2 H

  92. " x" _$ B7 |0 k
  93. #define MAX_PUT_BITS_BYTES 63000, p3 I' |1 t& v3 H/ H' h' j
  94. typedef struct
    9 e1 L" n' h/ z4 c; V
  95. {$ i3 u, b* s& ]
  96.     uint8_t bytes[MAX_PUT_BITS_BYTES];
    , o- h; ~: f+ o
  97.     int byte_index;
    $ s' j1 a$ y! ^; V6 ?
  98.     uint32_t bit_buffer;. J" a5 b- r; @: L) }  }3 w
  99.     int bits_buffered;
    0 c' @$ T! X" ?+ h
  100. } put_bits_context;
    1 l  Q7 j7 t1 B/ Y1 ^% w' k4 e

  101. # ?- u0 I; s3 w$ M
  102. static void reset_put_bits(put_bits_context *pb)
    4 U. \4 J1 _2 ~0 X  O; ?
  103. {
    ( a- Y* I6 r3 |. w7 \9 V
  104.     memset(pb->bytes, 0, MAX_PUT_BITS_BYTES);
    $ j9 c, U9 p7 `% }$ x" K$ f
  105.     pb->byte_index = 0;
    % D& x, t8 ~5 |% f: C) m* q
  106.     pb->bit_buffer = 0;
    4 T% n$ C  v4 w  k, I
  107.     pb->bits_buffered = 0;
    ( @3 v6 [3 A5 H6 q. i
  108. }8 K" L( {: x( S3 e3 o. A' H

  109. / C# ]: m3 E6 n3 k- L
  110. static put_bits_context *init_put_bits()
    4 |5 K  f  n: x) n0 U: Y+ F; k
  111. {
    7 I7 M  n& ^* S8 D4 w4 {8 o
  112.     put_bits_context *pb;
    3 U. s  ~! d1 H& T  O6 m! m

  113. ( T3 s% a8 m2 s# o0 f6 m
  114.     pb = malloc(sizeof(put_bits_context));/ Z/ s& h2 q4 Z4 T
  115.     reset_put_bits(pb);( f# \, p& z" J3 j) d
  116. $ C$ l$ y3 V4 k) P  @& o% R( w8 Z- a
  117.     return pb;
    6 U$ X9 G6 L5 i& Z: \
  118. }: u$ J3 d- Q3 E9 Y) S) r

  119. 6 |4 l7 i3 H1 h* V2 L% t
  120. static void put_bits(put_bits_context *pb, int bits, int count), a' [  m, e% T' m& O# A! @
  121. {5 K2 U5 M+ k& V8 D
  122.     pb->bit_buffer <<= count;& Q+ m" Y3 \3 a6 J+ \' V
  123.     pb->bit_buffer |= (bits & (~(0xFFFFFFFF << count)));
    5 [1 Y$ H. \  m9 L
  124.     pb->bits_buffered += count;
    5 V/ T* _8 z+ }. r& L6 B
  125.   s$ S# R% Q% U# N+ g
  126.     while (pb->bits_buffered >= 8)4 a' f" S. O/ ^0 y5 \5 L6 b( F
  127.     {0 f5 I* V2 Y7 }$ G
  128.         pb->bytes[pb->byte_index++] = pb->bit_buffer >> (pb->bits_buffered - 8);, \& C- Y  d+ B; X9 \
  129.         pb->bit_buffer &= (~(0xFFFFFFFF << (pb->bits_buffered - 8)));: `  S7 w2 c/ v, z* I- ~* e9 y: ?
  130.         pb->bits_buffered -= 8;. j" }: V7 X# i% S1 N
  131.     }: c5 B* {0 d  M- k0 E5 j8 F8 ^+ ?

  132. % ]  g  ^3 q! h0 h6 F
  133.     if (pb->byte_index >= MAX_PUT_BITS_BYTES)
    ! }# h9 T/ H3 U- [, Q
  134.     {
    , c; v* J1 s- d1 E
  135.         printf("HELP! Bit overflow\n");
    , j8 M1 R7 H  u  o0 T! W9 S
  136.         exit(1);
    1 c+ k% T, X. X9 h( ~
  137.     }& S& [7 D3 N8 b% r5 A& Y; _
  138. }
    0 e' M$ d+ f- \5 `8 s
  139. " S: R2 o9 d1 L7 d9 {
  140. static void put_bits_flush(put_bits_context *pb)% v6 B( K, ?( h
  141. {7 m" u- `% L. j1 L$ f$ t
  142.     if (pb->bits_buffered > 0)3 [. i  U6 ^( U
  143.         pb->bytes[pb->byte_index++] = pb->bit_buffer << (8 - pb->bits_buffered);- e5 _: Z6 i. V2 z
  144. }/ @0 F8 W* Q" U  d3 w1 ^

  145. / _/ ]+ k! ?! ]# ?1 \* c1 g6 z
  146. static void delete_put_bits(put_bits_context *pb)& a( f: k/ l6 C/ b1 z
  147. {# k6 ]+ Q0 O/ i* E2 k
  148.     free(pb->bytes);
    % G: x  n- Q- x2 b( X
  149. }
    ! u6 P2 C$ w6 H

  150. 4 F& L# N) K( F: v) G! ?
  151. /*********************************************************************/
    . g& w# }1 n2 x  r! M( }6 D

  152. + k0 {$ C; l" e' S
  153. /* RBT functions */' u( N# Q' A" w2 X5 G: y: D8 d

  154. + }) F1 ?' V3 b) z% ]
  155. #define PALETTE_COUNT 256/ ^6 J& n8 F2 G
  156. #define RBT_HEADER_SIZE 60: x3 ^7 O% m* l
  157. #define UNKNOWN_TABLE_SIZE (1024+512)
    8 A2 a2 {( {, u, y8 E: A
  158. #define SUBTITLE_THRESHOLD 0x70" C- P2 R8 k' W* }; }! ?5 U
  159. #define MILLISECONDS_PER_FRAME 100
    + @! C9 l* O( N5 P/ h) o0 ^: f# `

  160. # o3 W+ g! ?6 e. |% `4 z
  161. /* VLC table */
    / p' M0 v" a! y4 o9 P& V% t
  162. #define VLC_SIZE 4
    : P* a9 c. p9 I( e! p
  163. static struct2 q1 t0 N4 ^3 n
  164. {0 k/ {4 I/ l' B- ~. F- n
  165.     int count;' C, U' V+ t  a
  166.     int value;
    6 ^2 Q# G! e3 z
  167. } lzs_vlc_table[] =
    ' D4 ]: q9 j: H( j: v9 y. s
  168. {1 ^; P$ A6 @6 G7 X% n7 C6 `8 ~
  169.     /* code length = 2 bits; value = 2 */
    ( `# E( Y2 S: P3 @# b; b, p+ i/ h
  170.     /* 0000 */ { 2, 2 },) J% l4 c+ _) [1 ?
  171.     /* 0001 */ { 2, 2 },
    * p" L, ^4 v& ~0 O. I
  172.     /* 0010 */ { 2, 2 },: c0 Q- C& [9 S7 v
  173.     /* 0011 */ { 2, 2 },# K: f" B5 ]( H4 ?  h; A) e
  174. 8 L( f0 N8 L0 A$ X
  175.     /* code length = 2 bits; value = 3 */
    7 a! N% f# M' M* g/ _# ?+ W
  176.     /* 0100 */ { 2, 3 },% h+ \0 v7 I) A; W
  177.     /* 0101 */ { 2, 3 },( d% C8 g* N; Q; D" H, Q
  178.     /* 0110 */ { 2, 3 },
    1 y% ]* B  w  f4 ]
  179.     /* 0111 */ { 2, 3 },
    8 F* w3 O3 v$ @4 b
  180. ( k' g+ w: m' U* G/ Y
  181.     /* code length = 2 bits; value = 4 */
    ! H5 h2 C/ Z- h1 P
  182.     /* 1000 */ { 2, 4 },3 n  S% M: q% ?' T
  183.     /* 1001 */ { 2, 4 },! |8 j* M% D, J8 ^, d
  184.     /* 1010 */ { 2, 4 },' ~* q& J. t5 d& R5 ~
  185.     /* 1011 */ { 2, 4 },4 X- M0 S0 y5 E$ t7 y6 H
  186. ) E/ j5 u' L, m, T) }
  187.     /* code length = 4 bits; value = 5 */" I9 }9 k* F4 i
  188.     /* 1100 */ { 4, 5 },* w5 m" X; w* h+ {7 R2 y+ I7 ~

  189. / m6 S/ ^$ A- v9 X6 H
  190.     /* code length = 4 bits; value = 6 */! J" v: o* ~2 K+ C8 V
  191.     /* 1101 */ { 4, 6 },6 |- _2 C; U' b( j- C1 X) V6 c

  192. & I0 K  B1 f( k; _; Y
  193.     /* code length = 4 bits; value = 7 */
    4 Q" y8 s& Z% d- m0 n9 @! z
  194.     /* 1110 */ { 4, 7 },8 K+ B4 }( A; M9 r. j

  195. % ~! u  U, T" U5 {$ [
  196.     /* special case */
    $ Z: Y+ S+ a6 {3 M, m# @
  197.     /* 1111 */ { 4, 8 }: V8 O5 i3 w+ l) }
  198. };% s2 R7 E* j8 U3 T) |  s1 O
  199.   L! n7 X7 N6 ]. k4 `7 r: }$ n
  200. typedef struct6 A7 w1 R0 ?" a9 z, V' c
  201. {
    1 R; k& D7 o4 s8 T1 V, I3 R
  202.     int version;0 a6 N7 W3 m# S7 C; C4 F+ M% @8 k8 }7 b$ Q
  203.     int width;4 }" Q$ ]& Q9 \: D/ {; |! X* z
  204.     int height;
    ) M, J% ?$ X: P- _
  205.     int frame_count;
    2 ?3 S2 o* w# b
  206.     int audio_chunk_size;, n5 z% s/ c% L- S) s: }% O
  207.     uint8_t palette[PALETTE_COUNT * 3];8 c$ m) x3 v8 a% K3 f6 o
  208.     off_t video_frame_size_table_offset;5 B2 M; }7 X2 v
  209.     uint8_t *video_frame_size_table;7 G/ ?6 Y" ?. k2 L" W
  210.     off_t frame_size_table_offset;
    0 {, F: ?* V! [5 \  g' t
  211.     uint8_t *frame_size_table;
    5 o  z* Q4 o( B) n3 l
  212.     uint8_t *frame_load_buffer;
    3 [$ m* O- f5 i% U7 l- O2 i- D
  213.     int dump_frames;
    7 ?. |7 V- M( ?% c/ O0 r$ ]7 L
  214. / r5 J$ l8 A1 @0 v5 Y
  215.     /* subtitle library */
      A& w: u) g" Y
  216.     ASS_Library *ass_lib;) G. k6 ^& u5 z$ d
  217.     ASS_Renderer *ass_renderer;
    ; {$ i# J$ b0 Y$ q) S/ E6 j$ f
  218.     ASS_Track *ass_track;
    2 k& I9 m: ?3 ^" k4 f+ _" u- i1 c2 W
  219. } rbt_dec_context;' D! c( Z' F% y
  220. % O  B) C! K" o0 ]5 {  f$ K* F
  221. static void dump_pnm_file(char *filename, rbt_dec_context *rbt,
    ) X' x! z0 R% ~4 v2 W$ i" l, o
  222.     uint8_t *image, int width, int height)* J. M+ ^' {$ i0 F5 ^' e
  223. {* y/ q1 H2 @; j" M9 w; f9 O
  224.     FILE *outfile;( L( |7 |3 {0 C  B( V" D0 [" N1 N
  225.     uint8_t bytes[3];+ S4 B2 A. q1 x$ [7 t8 o
  226.     int p;
    % I/ i: P  ~! h0 l. Z2 Q4 A+ t
  227.     uint8_t pixel;
    ) F4 d. }( K/ a% `+ B1 z1 F8 v2 [

  228. % ^9 U# M6 e4 P4 }0 M, J! h
  229.     outfile = fopen(filename, "wb");& U, {! }* c' t6 B! F, H1 U3 X5 R& I
  230.     fprintf(outfile, "P6\n%d %d\n255\n", width, height);
      j4 F# [( G! ]3 v' K* z/ r9 O, h9 I
  231.     for (p = 0; p < width * height; p++): n3 J+ D- [8 i  _% Y
  232.     {
    " Z6 g% ]% \: t) n, \+ v1 n
  233.         pixel = image[p];
    + ^. Q0 R- Y" x5 l1 f; d) x
  234.         bytes[0] = rbt->palette[pixel*3+0];+ G3 h2 R8 K0 O% p8 Y) I8 m- k$ C
  235.         bytes[1] = rbt->palette[pixel*3+1];
    , ]" i, ?9 X9 V
  236.         bytes[2] = rbt->palette[pixel*3+2];8 ?3 v: w* L  e8 _$ B1 \
  237.         fwrite(bytes, 3, 1, outfile);
    & N' [% k: q$ M1 S7 B
  238.     }
    / t7 ]9 t* ?& c
  239.     fclose(outfile);5 {5 Z% g) R* c( m  H* d3 l! o
  240. }
    8 y- `; a7 E7 n0 \; Q
  241. # P. H. d5 l( g, k3 E; r3 c7 I
  242. static int load_and_copy_rbt_header(rbt_dec_context *rbt, FILE *inrbt_file, FILE *outrbt_file)0 M+ C5 w9 o! o2 \# b' ]* t
  243. {
    ) X8 o, x3 k$ c$ k; h$ m
  244.     uint8_t header[RBT_HEADER_SIZE];
    + V% R  i7 `- _! _% c8 ^- |
  245.     int palette_data_size;7 m: h% O/ f; }* H+ O5 N% j! m* \
  246.     uint8_t *palette_chunk;
    $ h* K7 I8 X, @; z( q0 y% n/ s7 |
  247.     int unknown_chunk_size;2 c5 b3 {$ f% d
  248.     uint8_t *unknown_chunk;
    : x5 F& y! y& W0 y, e' y# A4 F, u9 j
  249.     uint8_t unknown_table[UNKNOWN_TABLE_SIZE];
    ! O4 z! N8 S6 ~- A; S
  250.     off_t padding_size;
    # N" w0 C, @  V' {+ w
  251.     uint8_t *padding;
    , G, |# o8 _) U7 P8 G
  252.     int i;; u3 Y& h* t+ y1 A6 O% e
  253.     int frame_size;  b) n) K/ ~$ o2 @
  254.     int max_frame_size;
    + Q! ?: B! ]& u( d8 B, {6 @
  255.     int first_palette_index;
    ( s# e5 M8 L! v% N6 q' n& `3 O
  256.     int palette_count;. K3 W; d% k( \5 T2 q. h; L
  257.     int palette_type;
    ! N2 @2 M% v, K% s. C% t) O
  258.     int palette_index;
    9 c% Q9 k' K0 m" v

  259. # G5 m/ j. s$ g* y  X$ e1 }
  260.     fseek(inrbt_file, 0, SEEK_SET);" H2 p! ~8 A3 E1 z$ m, f: Y, V
  261.     fseek(outrbt_file, 0, SEEK_SET);6 P% y, f/ T1 C/ X/ k$ N
  262. ' ^* B% A% n$ Y( Y: u; S
  263.     /* load the header */7 E/ @, t; }7 Z$ L. N2 F
  264.     if (fread(header, RBT_HEADER_SIZE, 1, inrbt_file) != 1): x: p5 G* Z1 l+ F" R
  265.     {
    8 [; C! {; X# h; n
  266.         printf("problem reading initial RBT header\n");% l7 h* v7 k0 P0 g
  267.         return 0;7 d1 r" E9 K0 N; ^/ F( u
  268.     }9 M: h1 z8 I# D2 @8 G: }

  269. 9 M8 y" k/ p* `. j; l9 f, _
  270.     /* copy header to the output */
    . N& l2 {0 J5 a& g( p
  271.     if (fwrite(header, RBT_HEADER_SIZE, 1, outrbt_file) != 1)
    + w! J: F" I6 _
  272.     {
    1 w9 L# j6 _( I5 |; {; M5 n! J/ r
  273.         printf("problem writing initial RBT header\n");7 [8 y+ ]  i$ v# M$ U1 o$ s
  274.         return 0;" n0 O2 W7 C* s; _5 e/ T% ^+ j
  275.     }( \# X% D. O1 R0 i4 S$ A8 i- o

  276. ; Y$ _1 n. n: H; a; }% |: Z4 j
  277.     rbt->version = LE_16(&header[6]);
    4 t4 ?2 I5 a. V: e' Z
  278.     rbt->audio_chunk_size = LE_16(&header[8]);
    + n4 T1 v3 n3 h! Q9 ?
  279.     rbt->frame_count = LE_16(&header[14]);7 B, w9 N+ o+ r

  280. . ~# R1 [& R4 j1 A/ p# Z* {
  281.     /* transfer the unknown data, if it's there */
    - w# S2 u( [4 p7 a
  282.     unknown_chunk_size = LE_16(&header[18]);
    ( i  {$ |& m6 O/ U' R" M
  283.     if (unknown_chunk_size > 0)6 g; p4 `' f3 @
  284.     {
    4 j  p* A/ H5 W: W1 x7 b
  285.         unknown_chunk = malloc(unknown_chunk_size);+ S- E- U5 w, O- Z# H6 Z2 G  A
  286.         if (fread(unknown_chunk, unknown_chunk_size, 1, inrbt_file) != 1)/ h- G6 [7 Z4 M: [% n7 L6 m
  287.         {& L- }7 Q' |* c- @+ }
  288.             printf("problem reading unknown data\n");
    ! C! q/ g2 Q$ Q
  289.             return 0;/ U+ k- W( O/ a) {" z- j, ^
  290.         }
    2 m8 g- L) b' H) d
  291.         if (fwrite(unknown_chunk, unknown_chunk_size, 1, outrbt_file) != 1)
    ! w# V/ p( Z0 b3 `
  292.         {: L% z8 B1 C1 b# G, C# e
  293.             printf("problem writing unknown data\n");
    8 \2 d9 x1 R$ ?
  294.             return 0;
    7 n2 B. o6 J! A! |3 e' @% V' \
  295.         }
    * _* _1 ~/ I  f: v$ {+ b
  296.         free(unknown_chunk);7 ^! ]! D* x! n
  297.     }, E, b: F: S+ F" M
  298. 8 C% q9 V* W. H4 L1 X0 b
  299.     /* transfer the palette chunk */
    , {. r+ [/ B7 E7 _: R6 h& ?0 j
  300.     palette_data_size = LE_16(&header[16]);
    9 @1 R4 v& \# [3 y9 M1 X/ S
  301.     palette_chunk = malloc(palette_data_size);. `3 E- r8 d7 q
  302.     if (fread(palette_chunk, palette_data_size, 1, inrbt_file) != 1)
    ) F: Z5 p- e! V; G; N! H3 `  r
  303.     {
    ! l4 k) U5 n' h5 V
  304.         printf("problem reading palette\n");1 k$ C; J) `; g# Z
  305.         return 0;
    4 Y( W6 @6 X* I1 ?! v
  306.     }( O' M6 M7 f0 E5 ^/ @
  307.     if (fwrite(palette_chunk, palette_data_size, 1, outrbt_file) != 1)# J- j" Y1 N* `0 I2 V& ]
  308.     {, a) z1 _( @* ]( i+ u9 _; |
  309.         printf("problem writing palette\n");" |/ o+ \! b; H5 }
  310.         return 0;
    ! ?& {2 ~$ H) K$ a5 `
  311.     }
    8 d1 L4 r$ }( T- n
  312.     /* load the palette into the internal context */0 }# t& O' y6 l/ ~1 D
  313.     memset(rbt->palette, 0, PALETTE_COUNT * 3);
    + s5 s( C, d% @+ [  v! I
  314.     first_palette_index = palette_chunk[25];9 K1 F4 b' o- J0 s
  315.     palette_count = LE_16(&palette_chunk[29]);
      U6 p% Q1 f% q1 [: n; I
  316.     palette_type = palette_chunk[32];
    . ?2 [7 V4 S0 n3 U9 {
  317.     palette_index = (palette_type == 0) ? 38 : 37;# m8 l: h" L2 M' W
  318.     for (i = first_palette_index; i < first_palette_index + palette_count; i++)
    " R- Y: R1 F9 {5 B8 s: D6 `
  319.     {
    - O4 h$ b6 b) S( |, W; V$ u4 j6 ~
  320.         rbt->palette[i*3+0] = palette_chunk[palette_index++];
    - O/ l7 [& `9 y: h% U) Q! N
  321.         rbt->palette[i*3+1] = palette_chunk[palette_index++];9 h# u1 @& D( `% U7 j% G6 A( M
  322.         rbt->palette[i*3+2] = palette_chunk[palette_index++];( W/ |# [+ K% B5 J
  323.     }
    " s+ S% E2 ^5 r1 c; x; K
  324.     free(palette_chunk);
    $ b0 o+ i$ H- L
  325.   ]6 {7 |$ _6 h5 \" c- k2 E7 E
  326.     /* copy the video frame size table (2 bytes per frame), as a placeholder */1 A% f, I& T7 u$ X) u2 v# _
  327.     rbt->video_frame_size_table = malloc(rbt->frame_count * sizeof(uint16_t));
    $ X& N& ?4 w. L  @( ~
  328.     if (fread(rbt->video_frame_size_table, rbt->frame_count * sizeof(uint16_t), 1, inrbt_file) != 1)
    ( h1 W9 Q7 }% b1 j: U4 D
  329.     {
    8 H0 S! M0 X6 r9 m
  330.         printf("problem reading frame table\n");0 g" z& z2 k. m& e' P" O
  331.         return 0;
      Z# U% a) Y5 e6 H6 `/ c
  332.     }* |, r3 \4 A/ a: Y8 a& _$ A5 Y. L
  333.     rbt->video_frame_size_table_offset = ftell(outrbt_file);
    , e( S: H: u3 A6 x/ Y% O
  334.     if (fwrite(rbt->video_frame_size_table, rbt->frame_count * sizeof(uint16_t), 1, outrbt_file) != 1)- R( E& b# \. l' ]6 ]
  335.     {$ I" T/ T7 j7 Q* |& l0 p
  336.         printf("problem writing frame table\n");5 \: y, P' i* M/ L
  337.         return 0;: X- w# `, O' M5 w+ ]8 u" S
  338.     }
    ) m. {) A0 U6 y. p
  339. & F& X- ?  M, j9 V# B- B8 q9 p
  340.     /* copy the frame size table (2 bytes per frame), as a placeholder */
    ) T; f% B1 A" K$ X  z
  341.     rbt->frame_size_table = malloc(rbt->frame_count * sizeof(uint16_t));
    : q8 J# M. a( A3 D+ v7 l
  342.     if (fread(rbt->frame_size_table, rbt->frame_count * sizeof(uint16_t), 1, inrbt_file) != 1)
    ; I) ~2 h. \3 V' |# e
  343.     {
    ) @4 c3 g$ d- Z% j- P' f
  344.         printf("problem reading frame table\n");
    & E. e/ x, o7 ^5 g' `
  345.         return 0;) i& q. I9 L# M5 x
  346.     }. Z1 c9 w9 N  r
  347.     rbt->frame_size_table_offset = ftell(outrbt_file);1 E  F. C7 z- j; j1 t3 F# _
  348.     if (fwrite(rbt->frame_size_table, rbt->frame_count * sizeof(uint16_t), 1, outrbt_file) != 1)
    & R7 m4 [* Z  W
  349.     {: P9 @8 ?& b3 ?, R4 K  M- ]
  350.         printf("problem writing frame table\n");+ F8 y% t: i; d" o/ ?* C
  351.         return 0;! t& }9 }3 a( J  ?; U
  352.     }
    * R; Z! P3 c/ t1 h* ?; O) V7 g: X
  353. 4 {8 g: I$ `# y" r
  354.     /* find the max frame size */5 c; b2 ?1 V- a5 `. n" d5 o4 m
  355.     max_frame_size = 0;; J8 q! Q  [$ a5 M- g- i% c
  356.     for (i = 0; i < rbt->frame_count; i++)! v, w7 @$ L" r
  357.     {
    ( }  q' M) [" ]0 `+ {) K! L& R5 X+ c
  358.         frame_size = LE_16(&rbt->frame_size_table[i*2]);2 A9 L6 y0 `; G- C
  359.         if (frame_size > max_frame_size)/ P  [, ^* Y$ o6 K( O
  360.             max_frame_size = frame_size;8 d, {- k% u: [" B+ ]
  361.     }
    % l4 D3 N0 u$ `- I$ v2 i7 t
  362.     rbt->frame_load_buffer = malloc(max_frame_size);
      a& D- n) ~. \" _( l
  363. + r# N5 D4 V! d+ S
  364.     /* transfer the unknown table(s) */8 w, C0 W. Y' D
  365.     if (fread(unknown_table, UNKNOWN_TABLE_SIZE, 1, inrbt_file) != 1)) ]) M1 \& {' Y6 m
  366.     {2 G: _* [7 m4 B% F  ]: v
  367.         printf("problem reading unknown table\n");8 B& y4 A8 K: U& m7 z) [0 ]
  368.         return 0;
    8 Z5 V& |$ J/ F0 [
  369.     }
    8 D( ~0 Y0 u% j' g+ S0 K- t6 Y
  370.     if (fwrite(unknown_table, UNKNOWN_TABLE_SIZE, 1, outrbt_file) != 1)
    ) i- l+ Y* Z9 b- v  z
  371.     {' N' Y1 ]* M4 R% _$ S' Y7 E
  372.         printf("problem writing unknown table\n");
    * u4 i! {6 d- s
  373.         return 0;
    $ w0 P( o. f' L! j; v8 r0 m6 o
  374.     }
    + D3 A- B5 E# ?- l
  375. 6 d: D9 }! q% I4 r) n' \
  376.     /* copy over padding */
    . Z$ Z2 @5 W9 ?1 e
  377.     padding_size = 0x800 - (ftell(inrbt_file) & 0x7FF);, ~- d, R4 o/ y7 T% X
  378.     if (padding_size)
    ; U( [/ O6 E2 c7 S
  379.     {
    ' I  I- ^' N* k# J) g9 n/ S
  380.         padding = malloc(padding_size);
    $ W. h1 M/ T$ N2 v4 A+ h2 N
  381.         if (fread(padding, padding_size, 1, inrbt_file) != 1)0 N( W9 p/ ]7 W# b$ G
  382.         {1 s6 [" o8 M- f4 \6 R
  383.             printf("problem reading padding\n");
    . X5 r; y4 U! f+ S8 F; t
  384.             return 0;
    0 U4 i0 j9 j5 {, A2 x9 P
  385.         }
    , _: k/ Q  m1 w8 {8 J
  386.         if (fwrite(padding, padding_size, 1, outrbt_file) != 1)
    7 a0 N# m1 Z: [" c0 o/ f
  387.         {
    5 _/ g4 o* E. C9 b+ t' P$ P
  388.             printf("problem writing padding\n");* d% W' \1 V9 \; w' Q( D$ X
  389.             return 0;% q  C2 V7 [" D+ Z+ F) g) J( B
  390.         }' C' {$ [  c5 C. c
  391.         free(padding);
    & u1 ^+ W( R" B7 }' |; X
  392.     }1 h+ i& y8 Z% p8 i7 U

  393. ( b  T. `8 Z- n8 B. g* b8 }# o$ b# V
  394.     return 1;0 P" h! d1 J0 b% o: ^
  395. }$ x) B& q: `% m& _# N
  396. : U9 n: q: B4 `# l) v
  397. static int get_lzs_back_ref_length(get_bits_context *gb)
    2 g% d  e3 y9 }4 ^( q! W+ Q
  398. {! q/ R, K$ S# L( P3 K+ y* X  ^1 e
  399.     int vlc;: G% r; _3 C5 D) k9 I! i4 g
  400.     int count;! l! J% w1 v' W" g
  401.     int value;
    % k1 Z0 ]2 [* r
  402. * O; s1 h/ g3 R
  403.     vlc = view_bits(gb, VLC_SIZE);9 R7 U7 N0 o# J: h
  404.     count = lzs_vlc_table[vlc].count;+ V8 k7 O& P+ z
  405.     value = lzs_vlc_table[vlc].value;8 o. h) I! M3 M" Q

  406. " i& s3 R1 Z, b, `2 y7 T6 Z7 ]% Q
  407.     read_bits(gb, count);: i# ]' j* O0 u
  408.     if (value == 8)6 ~' D. H. f8 ^! {
  409.     {. m* p6 t) a" d0 x7 B
  410.         do& x$ Y6 c7 e6 W2 }
  411.         {
    6 o' H  ?4 a; ^: C/ u, e
  412.             vlc = read_bits(gb, VLC_SIZE);' ~# j, X2 g8 `5 ^# m" v: y9 o& r
  413.             value += vlc;
    ( h' X. v! Q; Y% I6 T
  414.         }& u8 x, u; I4 Z( V/ }' _
  415.         while (vlc == 0xF);4 q3 g7 t/ a3 N. {1 i/ Y' q
  416.     }+ d. E+ b9 F2 U9 _8 ~/ f; E2 n

  417. : O! J( g: p# M# \1 h$ v7 T' R
  418.     return value;) F5 o" c7 F, [* n
  419. }: w) q6 v5 `: t+ j

  420. , [- w  c; F6 k+ I" T' T* r
  421. static void compress_window(put_bits_context *pb, uint8_t *full_window,/ n; s0 `; o$ e  r& h  v0 n
  422.     int full_window_stride,' V6 n7 c3 y6 Z3 R  s  E
  423.     int window_top, int window_bottom, int window_left, int window_right)
    3 n" d4 {  k& H" c! [( W
  424. {
    ! F9 }4 n! }/ c' p8 D# c8 W$ G9 W
  425.     int last_pixel;
    4 T( W. v, |! J3 Q3 ?7 f
  426.     int run_size;
    1 X9 z/ E5 J7 O0 }
  427.     int x;
    1 I. w0 D+ Y8 O0 o& _: h3 ~
  428.     int y;
    5 z5 o/ _+ v3 k8 H- j& g. M
  429.     int start_index;
    ; R5 e/ z$ A1 _! v! y0 w9 w; h$ ], ~
  430.     int end_index;
    , |+ n$ ?  S" b6 D' l7 X! u
  431.     int encode_last_run;, w3 t5 q) B/ G' j( ?2 n& ]$ T* Y

  432. ( V6 M# L' p5 a
  433.     last_pixel = full_window[0];
    / k; C8 O+ i8 p8 w; {
  434.     run_size = 1;% Q( {/ t! ]: |
  435.     for (y = window_top; y <= window_bottom; y++)
    & B6 U7 N7 n( s. d8 a( i, h
  436.     {
    % N2 R5 \( a4 i' X
  437.         start_index = y * full_window_stride + window_left;7 {6 W  z2 z7 [, Z. @$ i' |! |
  438.         if (y == window_top)
    8 N- D# B1 x) r3 X+ I5 ^
  439.             start_index += 1;
    . s# H$ i! m6 ~4 W% K
  440.         end_index = y * full_window_stride + window_right;! z% G# V6 p; `; ^. F, i* X7 \
  441.         if (y == window_bottom)% Q0 j9 v- |$ @# f
  442.             encode_last_run = 1;
    7 z& f6 l* f7 S6 ]' z& ~# n
  443.         else
    2 M, X. D% T! J7 c( o8 W
  444.             encode_last_run = 0;5 ?7 A! S5 ]9 g- j% x5 F: k% g
  445.         for (x = start_index; x < end_index; x++)
    3 l4 b& m8 I: M" V9 a
  446.         {) c: u* a: j& x( J
  447.             if (!encode_last_run && full_window[x] == last_pixel)
    . u* n+ x" O' F, l' p7 ^! D
  448.                 run_size++;9 x' K* E* @9 T' F5 {4 I9 O
  449.             else
    ( s+ l1 [( ~4 {3 O- ^
  450.             {2 ~9 W" A8 M0 d
  451.                 if (run_size == 1)- W# k& S: O) Q. S. ?! e% a
  452.                 {
    4 x/ @1 T4 g0 ~4 ^0 \7 E
  453.                     /* encode a 0 bit followed by raw pixel byte */
    - p1 h' ]; V" L- Y- v3 q
  454.                     put_bits(pb, 0, 1);
      v9 g/ I  n' c$ o2 p% ?3 o' t9 n. K
  455.                     put_bits(pb, last_pixel, 8);
    $ X' Y7 D4 j5 c6 Z3 T
  456.                 }3 Y% h0 p% `0 j% O4 O
  457.                 else if (run_size == 2)5 M3 j; N4 W# M( t
  458.                 {8 o. C" A8 c/ z4 K
  459.                     /* encode a 0 bit followed by raw pixel byte */8 O3 l% X) L# B" ]' d+ e
  460.                     put_bits(pb, 0, 1);9 ~% h6 W, w+ J- N" k/ e) H, c
  461.                     put_bits(pb, last_pixel, 8);
    : Y5 h: b' {- |0 R+ r4 e$ w- k5 z
  462.                     put_bits(pb, 0, 1);
    5 D* }' x" L4 S+ V5 g: O! }  R
  463.                     put_bits(pb, last_pixel, 8);
    ! G  s; w3 S, ^9 I4 _! m3 R- P. ?
  464.                 }
    + f) V  |* f/ X3 `" B# Z: s/ e1 D
  465.                 else
    / [# J2 T/ i( z. V, _" `* n
  466.                 {
    - j6 v& U% P% R
  467.                     /* encode a 0 bit followed by raw pixel byte */
    " _( d5 i4 Q: s* r- |8 D( {
  468.                     put_bits(pb, 0, 1);. u8 p# ~' }2 ]$ Y, J7 M% E8 J1 K# Y
  469.                     put_bits(pb, last_pixel, 8);) C4 e# r3 M. M) Y4 s
  470.                     run_size--;
    3 R- k) t  L6 a  G! W$ m- Y" b( v9 v( P
  471.                     /* encode a run: a 1 bit, followed by a back reference
    0 w! g# S4 ?4 K& F
  472.                      * offset (-1), followed by a length */
    ' p! C* B) a( X' \
  473.                     put_bits(pb, 1, 1);8 t( o! z# w! n
  474.                     put_bits(pb, 1, 1);  /* 1 = 7-bit offset */2 w1 z( D, G; r! c
  475.                     put_bits(pb, 1, 7);; }( Z1 @* H% I9 g) ^  |" a
  476.                     if (run_size <= 4)
    ) ?; p9 A: K; D
  477.                     {
    7 b7 x0 j2 k4 o/ }3 h' H) t
  478.                         /* lengths 2, 3, and 4 are 2 bits */
    , j1 B( v$ \# l1 R4 I4 s. Z
  479.                         put_bits(pb, run_size - 2, 2);
    0 o/ W* Y+ [& F- ?9 n
  480.                     }" g/ R8 g3 J, k" u
  481.                     else if (run_size <= 7)
    0 @/ x. f4 ~  j8 T
  482.                     {3 E# H4 u$ a& O/ ^+ Q) b0 G
  483.                         /* lengths 5, 6, and 7 are 4 bits */
    7 f* V+ }5 n0 Q: K7 G- T
  484.                         put_bits(pb, run_size + 7, 4);
    8 B# V  m5 J  ~  l" z% R! ^4 m
  485.                     }
    & ^* U1 r, G! [( f7 |, J
  486.                     else2 Y, |3 E$ {6 f
  487.                     {0 N' q( d( s5 i, Q8 D
  488.                         /* arbitrary length; start by encoding 0xF which
    * J3 d. r# H" _) ~4 u" d0 P+ k- ~
  489.                          * stands in for an initial version of 8 */" g, t" F, c7 I% R/ F, |% \
  490.                         put_bits(pb, 0xF, 4);5 r4 X3 C7 w- `
  491.                         run_size -= 8;
    6 a. H2 j' B4 L2 ]& p

  492. - U, l% U' w  b
  493.                         /* encode blocks of 4 bits until run_size is 0 */
    ! ?4 _. \1 l3 f5 r
  494.                         while (run_size >= 0)0 y, W* P* L$ ]$ Y- S
  495.                         {4 ~) D" q2 ~1 e7 F: v
  496.                             if (run_size >= 15)
    # \0 h! S: \) v) T8 t( }
  497.                             {
    " U: F6 t- d& I+ c5 W. U
  498.                                 put_bits(pb, 0xF, 4);! R" G3 n3 Q( ^9 y( Q. g# N
  499.                                 run_size -= 0xF;( Q% v, u! m4 M
  500.                             }! A. o* D7 }( g) V8 Q6 a
  501.                             else  T! Y& z( [  G- H
  502.                             {
    * I8 l: I2 w$ K. H* E: W
  503.                                 put_bits(pb, run_size, 4);7 j! S3 U: x% @
  504.                                 run_size = -1;6 N3 s( r/ R, ]$ j) s2 E
  505.                             }
    2 A) v+ i  s% b* f  Z
  506.                         }+ {6 B$ `. F% B0 P5 Y
  507.                     }) U1 _- e' f. _' s# G$ k' k. t
  508.                 }: p, {7 R$ j$ ~$ B% j3 h

  509.   i6 F: T8 I% u
  510.                 last_pixel = full_window[x];
      b- Y0 @2 v5 m- y' D' U
  511.                 run_size = 1;
    1 P) C' _: d5 q5 p1 T$ M! q4 _

  512. ; _2 ?( ~5 X) ?
  513.                 /* this single x iteration was only here to close the final run */0 A) g1 f7 `8 k5 l+ D+ Y
  514.                 if (y == window_bottom)
      x, Y4 D- H( B, C/ `# P
  515.                     break;
    " y0 T# L* h! h* l  h- Z
  516.             }
    ' G0 ]. C( K& b1 W+ J6 s
  517.         }
      c- f& ^4 Z" V# h- }
  518.     }
    3 j; v3 p. U) H, S8 Q2 I

  519. 9 ?% W$ _4 i( I+ C4 ~
  520.     /* close the bitstream by encoding a back reference with length 0 */
    - d. i/ Q3 g/ X% x/ w( y8 c
  521.     put_bits(pb, 1, 1);  /* back reference run *// w- |7 ]- G4 x* ?3 J
  522.     put_bits(pb, 1, 1);  /* 1 = 7-bit offset */
    4 D9 H  f8 K0 w6 K1 K0 s/ J1 _+ A5 ]
  523.     put_bits(pb, 0, 7);  /* length 0 */7 j) C  n0 W7 _! ?8 o7 E0 G
  524.   \4 s9 l3 \. N/ U! v  X
  525.     put_bits_flush(pb);
    6 }- V- O8 [" j2 Y4 W$ U) n
  526. }) L( i" l7 v  p" G9 ^

  527. + g  ]* s. n9 Q- S4 F3 \
  528. /* compute Euclidean distance between an RGB color and the desired target */3 W" P9 V) _. r% R7 b
  529. static int compute_rgb_distance(int r1, int r2, int g1, int g2, int b1, int b2)
    $ X: L( O3 W* k
  530. {
    6 e4 w# d; o0 a
  531.     return sqrt((r1 - r2) * (r1 - r2) +
    $ _0 O2 r  x( ?0 c# D+ u
  532.                 (g1 - g2) * (g1 - g2) +8 X5 ^5 T  J, h4 J3 _# r$ a3 t1 L+ e8 g
  533.                 (b1 - b2) * (b1 - b2));
    . H% r, [7 f/ J0 ^
  534. }$ R! X1 t. h8 e. r2 D# z) f

  535. ; a  U9 @9 Z& l/ Q: @
  536. static uint8_t find_nearest_color(rbt_dec_context *rbt, int r, int g, int b)
    4 G+ i4 Y1 `2 ]! \9 J4 u
  537. {
    , S* S3 O3 n$ e0 N  v) x  m2 r
  538.     int i;
      N% c* q! ?' D) ~
  539.     int nearest_distance;2 O, W& M. Y" q! |4 Y
  540.     int distance;
    8 V3 P& b. Q6 t( e! ~
  541.     int rp;8 w2 W+ ~3 L2 h  c! `
  542.     int gp;2 ^/ p0 R) k7 V$ Y4 Y! o9 F# O  t( V
  543.     int bp;# H6 ?3 f1 u3 A
  544.     uint8_t palette_index;# W* F0 s- B7 H2 d) a5 u

  545. % q# [& f  w7 c$ X5 a- c; T
  546.     nearest_distance = 999999999;
    3 ^& v) `$ A& n" g7 z$ ^
  547.     palette_index = 0;
    9 X  G5 i" f& }4 L# F3 |
  548.     for (i = 0; i < 256; i++)
    ! m! i: l: ^5 ^6 _  q2 f- c
  549.     {( F  \0 s' W* N  l, O
  550.         rp = rbt->palette[i * 3 + 0];
    ) t* S4 H4 t/ F) z7 s  h
  551.         gp = rbt->palette[i * 3 + 1];8 Z& p! O1 Y% q6 _% M/ v
  552.         bp = rbt->palette[i * 3 + 2];& `  P8 u6 t- {# @6 j! o2 z) @9 k6 O" W% g
  553.         distance = compute_rgb_distance(r, rp, g, gp, b, bp);/ g, t: t' |: @
  554.         if (distance < nearest_distance)6 |+ }/ H( i* X
  555.         {6 d. q! q9 J9 I! X7 W8 U* C6 {
  556.             nearest_distance = distance;. K: T& {  z; B; [/ ?* f( \
  557.             palette_index = i;
    3 q. ]* {& D9 Q* @8 }. W4 N
  558.         }
    , W$ R3 m8 g( n/ R) H( J; ]& q/ s! L
  559.         /* can't get closer than 0; break early */  ?  Z9 _, W# U) z/ T* R
  560.         if (distance == 0)
    " ^- Q" \  u$ e. y/ ]: j, G3 Y
  561.             break;0 ?- M. M6 P. ]3 {2 ]- F, s
  562.     }0 Q# g/ Q4 w! M/ a

  563. % c, |7 I2 \8 v* Y, J- |
  564.     return palette_index;/ y3 W* r! Z/ w+ m
  565. }
    2 ?2 N: W2 v" u  U& p) p

  566. 1 l4 y2 w" W: I% |4 {  z
  567. static void subtitle_frame(rbt_dec_context *rbt, uint8_t *frame,/ S! ]8 y9 v: q0 F+ J
  568.     int width, int height, int timestamp)
    9 u8 f6 w: m. m4 u
  569. {8 D; K5 ^1 Z) A1 g  G9 K$ @$ B9 a" d9 c3 _
  570.     ASS_Image *subtitles;
    + [- R! n/ k: t: y, |$ {
  571.     int detect_change;3 J$ F+ D9 X7 }# d% s4 W
  572.     uint8_t subtitle_pixel;' l) `  ~& Q5 x
  573.     int x, y;3 N2 {7 V2 G; P4 x* d$ O& M# G
  574.     uint8_t *frame_ptr;
    . A2 A8 b' t8 L% ^! ?
  575.     uint8_t *subtitle_ptr;  h7 D4 Q6 i& O* N! g7 o2 a7 O
  576. 3 f! c+ M0 _$ ~
  577.     /* ask library for the subtitle for this timestamp */1 Y4 Z. p1 C; w& c2 E  n
  578.     subtitles = ass_render_frame(rbt->ass_renderer, rbt->ass_track,
    1 b5 }$ u1 x% g; L
  579.         timestamp, &detect_change);% X) @" l' [* ~1 T2 E! s# i
  580. 6 Z- V" y: x( p
  581.     /* render the list of subtitles onto the decoded frame */
    ; o7 M8 e6 f6 [" ]7 ]3 `6 V
  582.     while (subtitles)
    , V+ N; ?0 Z, Q4 Y, h% y- `% |2 k, F
  583.     {9 E+ c3 n% I3 @* n% M; u
  584.         /* palette components are only 6 bits, so shift an extra 2
    5 ]3 [8 A4 q! Z1 R
  585.          * bits off each component */
    ! n' _: `  d- A8 T+ _! j, z
  586.         subtitle_pixel = find_nearest_color(rbt,
    / l- g* d$ o! ^% G, E+ n5 ^) y" @
  587.             (subtitles->color >> 10) & 0xFF,( J0 r6 ], ]: D9 M0 r; @
  588.             (subtitles->color >> 18) & 0xFF,# h. s( z3 c* }/ L# G) E
  589.             (subtitles->color >> 26) & 0xFF);0 w6 ~8 |6 a6 c" _
  590.         for (y = 0; y < subtitles->h; y++)
    " X7 h4 a* G- e& `7 p
  591.         {- p. B/ {1 ?" a
  592.             subtitle_ptr = &subtitles->bitmap[y * subtitles->stride];
    ' S  _# d1 a, `' j/ H
  593.             frame_ptr = &frame[(subtitles->dst_y + y) * width + subtitles->dst_x];: G8 s( g& p$ ]) S. c+ s- U
  594.             for (x = 0; x < subtitles->w; x++, frame_ptr++, subtitle_ptr++)
    8 T+ t6 D0 v: t: r4 c" i# R4 \
  595.             {# u1 Q( m! D- ~
  596.                 if (*subtitle_ptr >= SUBTITLE_THRESHOLD)3 ]6 h3 J; g' |* J) Y" ]
  597.                     *frame_ptr = subtitle_pixel;6 e7 O$ ~0 n- n3 t3 J% T7 D0 `$ F
  598.             }" }6 b) E7 Z% Z; B0 V
  599.         }
    4 o% g( M5 H# u) a+ ]
  600.         subtitles = subtitles->next;
    % w  r7 m! y: W# F+ t8 y5 Q. f
  601.     }
    6 G* i3 V6 ?5 T" k2 }/ `% C/ \
  602. }
    3 P% a/ n% y) g7 Z" C

  603. / i! v/ b0 S* N, |4 e: u0 J7 g
  604. static int copy_frames(rbt_dec_context *rbt, FILE *inrbt_file, FILE *outrbt_file,
    , m) `9 W4 r  e# ?- M! @9 g
  605.     int origin_x, int origin_y, int window_width, int window_height)* O9 G  v. A  D- J
  606. {
    & k$ t7 P5 D7 |; |* h. H6 b
  607.     int i;3 f/ D1 n: h# A
  608.     int j;) h3 b6 l, d( x% C+ f1 k8 I& ]
  609.     int scale;9 u0 q' d+ k8 V& n5 p
  610.     int width;
    6 h' X& l9 E- _7 w! O
  611.     int height;
    6 h$ O5 W6 O( k# B. z
  612.     int max_width;
    , D$ [9 ]* [; U4 c! d: Y
  613.     int max_height;
    ) g- b- a- S# g1 y9 F* {
  614.     int frame_x;1 s9 b8 o. \/ g' ]+ ?5 M
  615.     int frame_y;& f: a- ]" g5 |9 \+ f* I) D" |
  616.     int fragment_count;' Z( q: \$ {, r) G0 G
  617.     int decoded_size;4 `( D( y1 [5 ~
  618.     uint8_t *decoded_frame;
    ; e( }' |, K" @4 h0 ?1 C
  619.     int fragment;
    * D% {  G! P( F+ N
  620.     int fragment_compressed_size;% B' ]$ [' @6 j6 I
  621.     int fragment_decompressed_size;
    " m( V- E% r2 D
  622.     int compression_type;
    8 {. k$ v/ y/ ~2 Y
  623.     int index;
    " {" |, s2 v; F1 A6 I$ o5 n  N7 f* s3 q
  624.     int out_index;
    7 C+ v& ]8 O2 e4 _  }5 H( l
  625.     get_bits_context gb;7 [' y; `- C( O: p. {; Y( v# [) C
  626.     int frame_size;
    # R0 }% w) Y" }  B3 M
  627.     int video_frame_size;
    + i7 c, |7 I% c6 M
  628.     int audio_frame_size;
    : b4 G8 T6 `0 X; W4 |4 E/ S4 v9 Z/ L) o
  629. ) w" v/ z  K# c* i9 ^% H- F
  630.     int back_ref_offset_type;. W. @$ V- F9 _5 V
  631.     int back_ref_offset;; |; E" H$ x& P
  632.     int back_ref_length;
    2 `$ z: Z9 Z! d$ E- |1 w8 i, k
  633.     int back_ref_start;
    - k& i+ ~+ D# [' k7 P; _
  634.     int back_ref_end;" p; r. }, L( w6 E' y/ ]. |9 \

  635. 2 H$ c: c7 o5 S$ U5 K0 F" o( h/ q
  636.     uint8_t *full_window;" Y7 C: Z2 w0 f# U& b* Z/ g" d- ?
  637.     int full_window_size;; q" s; S# o: d# c5 Y
  638.     int y;
    9 O1 r1 t4 g- Y# K. z6 z8 v$ t% [
  639.     int window_top;
    . U3 w: d1 L: @3 p2 ?
  640.     int window_bottom;
    # f6 b- v" p) l6 ~2 _& U
  641.     int window_left;/ Y1 v+ i, q* |8 d
  642.     int window_right;
    5 n3 [0 f1 F3 i# e# J) N
  643.     int window_size;2 c# E# E" f! H* {* y2 h
  644. ! ?9 T! ~( Y" d  S; U' l" X. C
  645.     char filename[30];& E% o* N. ]) j; H& ]9 _

  646. ! Q; W5 W0 S- A
  647.     put_bits_context *pb;" S" j# _0 C; Z* X2 @( ~* W( ?
  648. , J# N/ ]1 i+ K4 Q% j9 s  Y
  649.     full_window_size = window_width * window_height;
    # N. h1 j* {5 R
  650.     full_window = malloc(full_window_size);( F' A9 K9 I* c! [! e. k
  651.     pb = init_put_bits();- E' r$ D8 Y9 q. T, n: v2 b
  652. 9 n4 K# L1 O# ~. B) k3 b8 I+ h
  653.     max_width = 0;
    * C7 G$ R( n# |6 I0 M2 N, A/ }
  654.     max_height = 0;! x) L  k5 I5 A8 K3 v6 p* C* L- Q

  655. ) a4 @1 @& o. E  F; e, [9 |
  656.     for (i = 0; i < rbt->frame_count; i++)5 F, a# {. j2 y0 Z# y. g/ ]
  657.     {7 C" }  [- F; K. ], p6 {- i
  658.         /* read the entire frame (includes audio and video) */
    1 V* J1 `, Q  J: _1 D- }( n# L+ M
  659.         frame_size = LE_16(&rbt->frame_size_table[i*2]);
    ; T) e  _; X& O3 J! P+ d8 g/ V( q
  660.         video_frame_size = LE_16(&rbt->video_frame_size_table[i*2]);# K7 W$ y' X, }( s8 t) H8 x! h; N
  661.         audio_frame_size = frame_size - video_frame_size;8 n9 e( W  B" m- y- c6 s
  662.         if (fread(rbt->frame_load_buffer, frame_size, 1, inrbt_file) != 1)
    ) ~/ \! n3 e3 }) E+ \# p6 _
  663.         {
    * J2 b. I4 x$ g- n- d0 v
  664.             printf("problem reading frame %d\n", i);
    * h- n+ c% D. |) z+ d, o
  665.             return 0;
    $ l, r9 G6 f! D( K- Y* w3 V/ t) w/ \
  666.         }0 E3 X! W, m, o

  667. % u0 H# ~9 z( S+ l& \2 p  V1 \& m
  668.         scale = rbt->frame_load_buffer[3];: g7 a9 j. A  b9 B+ W
  669.         width = LE_16(&rbt->frame_load_buffer[4]);7 ]' ?7 y8 D3 q! `
  670.         if (max_width < width)
    3 w5 e7 z& ~3 I) N, e7 j
  671.             max_width = width;& s( n& O+ v3 {2 F* D% D! Y) h1 }
  672.         if (max_height < height)
    / B/ w; g3 }; m$ r6 [3 Z
  673.             max_height = height;
    8 ]% W# }8 a! f" X- U6 X1 L
  674.         height = LE_16(&rbt->frame_load_buffer[6]);
    1 z6 C" Y7 [3 ?" A0 D+ T* g9 b
  675.         frame_x = LE_16(&rbt->frame_load_buffer[12]);6 x. H) r! i! S4 U# e% u
  676.         frame_y = LE_16(&rbt->frame_load_buffer[14]);
    2 o6 w# ~8 W9 Q6 Y8 r7 E" a: V
  677.         fragment_count = LE_16(&rbt->frame_load_buffer[18]);
    . E6 w: |  I0 A( @  x
  678.         decoded_size = width * height;8 s+ C: g; H3 ~) h# j
  679. ) F* l4 X6 ]; I2 |/ z4 F3 o+ L
  680.         printf("processing frame %d: %d%%, %dx%d, origin @ (%d, %d), %d fragments\n", i, scale, width, height, frame_x, frame_y, fragment_count);# e* J$ ^3 K+ ]$ ]" a
  681. % V4 K6 f! \% T9 e* `! s" I4 L/ z
  682.         /* decode the frame */
    ) T+ k1 |) f( W. H% b1 F& g2 _
  683.         decoded_frame = malloc(decoded_size);% Y  k; N. d6 e6 e4 b/ W/ M
  684.         index = 24;  n" w' [8 W0 \+ ]9 Y4 B2 e* U) [
  685.         out_index = 0;% }3 _  ~5 K# d  r4 \- \
  686.         for (fragment = 0; fragment < fragment_count; fragment++)
    ) y$ {! k! n4 O
  687.         {
    # Y* @5 W# @3 o3 M3 v3 E
  688.             fragment_compressed_size = LE_32(&rbt->frame_load_buffer[index]);
    - Z" b4 l/ I+ ^& t) F! ^7 O
  689.             index += 4;( H; _  @3 Y: J% z/ k
  690.             fragment_decompressed_size = LE_32(&rbt->frame_load_buffer[index]);
    " s/ k6 J; |, p+ a& e) d
  691.             index += 4;
    ( @! c, i0 q9 U( w8 N/ J. o0 P5 W# J
  692.             compression_type = LE_16(&rbt->frame_load_buffer[index]);/ T0 a* M: a- p4 Q/ v
  693.             index += 2;; E5 J2 S; i1 J$ A& N9 K1 R  T) W

  694. 4 I8 Y8 R( C, @3 j1 A6 u* o
  695.             if (compression_type == 0)
    ) b# F2 H, n, P; i" q. w% p
  696.             {
    $ U1 y2 V" ~+ w* x2 _7 O
  697.                 init_get_bits(&gb, &rbt->frame_load_buffer[index],7 A! I- v- c$ A, @0 w" a' w& l
  698.                     fragment_compressed_size);
    * \  y6 }+ k: o4 I) ?0 ~6 f

  699. ; K  @0 ^# \8 }$ L
  700.                 while (out_index < fragment_decompressed_size)  [. n3 W* K" E
  701.                 {, }# c- d2 h" V
  702.                     if (read_bits(&gb, 1))8 C$ a5 j: A/ V
  703.                     {
    8 r, v. Q4 G, N/ Z: n& [
  704.                         /* decode back reference offset type */) H% [( c, p# K
  705.                         back_ref_offset_type = read_bits(&gb, 1);& v0 i* c' r9 l2 v: I6 M0 w

  706. 8 Q+ n, n5 s3 x) j% x
  707.                         /* back reference offset is 7 or 11 bits */
    % t5 w7 }: O9 J% A2 P3 E
  708.                         back_ref_offset = read_bits(&gb,; O1 N7 R- }# P4 Q6 M2 s+ }/ v6 A
  709.                             (back_ref_offset_type) ? 7 : 11);
    ; G! d& Q  U9 ^8 U  W4 Z3 m

  710. ) |$ G  t+ X& ]
  711.                         /* get the length of the back reference */& e% e" m" N# S( z! |% W  B
  712.                         back_ref_length = get_lzs_back_ref_length(&gb);
    / D  k! O7 V+ N; z- d
  713.                         back_ref_start = out_index - back_ref_offset;
    ' O3 @, j/ k# H' N' M) d, |
  714.                         back_ref_end = back_ref_start + back_ref_length;2 q0 G" q: p' l8 |1 {
  715.   A, O& z% y% d% `7 G) Q! u
  716.                         /* copy the back reference, byte by byte */
    8 k$ S# R6 b% @  u5 T2 p1 @, w
  717.                         for (j = back_ref_start; j < back_ref_end; j++)
    : n8 B* `/ N% `2 x
  718.                             decoded_frame[out_index++] = decoded_frame[j];5 [- Z# P: w5 G5 e4 G( s
  719.                     }' U' s9 i; D6 D$ ?1 M; r  F
  720.                     else
    9 f2 `: g) Q% R% y$ j+ f1 h- g
  721.                     {* E3 N0 x/ H$ o) F) ?: L
  722.                         /* read raw pixel byte */$ u) _$ {$ E% e# U% e8 G% k) h8 z
  723.                         decoded_frame[out_index++] = read_bits(&gb, 8) & 0xFF;0 y- `% i( m0 V% l; b+ W$ g* m# |
  724.                     }
    7 {$ E/ d) V- P- I/ J/ R
  725.                 }
    2 b2 G5 Q0 D/ T) i  Q1 x
  726. ' E# N( B% V5 k( P. S3 c
  727.                 delete_get_bits(&gb);0 S+ C6 m: x0 n) S0 y; A) O
  728.             }. Y4 a& m1 A! F& m! b* F  k9 F6 M$ h
  729. 4 q% m0 X/ Q! x, L8 I' S% [
  730.             /* next fragment */6 X) }8 T; n' k" l( N
  731.             index += fragment_compressed_size;
    - m; f1 J& K$ l1 a; H
  732.         }2 H8 F1 S, G$ B6 Y

  733. ) D( c) f" v, r, K& H
  734.         if (rbt->dump_frames)% F# L( U. f' |  x2 A8 l7 u. x
  735.         {8 Y1 M- ^4 ?6 L0 ]4 y
  736.             /* dump the original frame */
    # m7 V" ]2 b7 F' n& c3 ^0 h% d( N' i
  737.             sprintf(filename, "original-frame-%03d.pnm", i);
    % X' T/ E; ]5 ^0 t, [' y; u/ O
  738.             dump_pnm_file(filename, rbt, decoded_frame, width, height);  A. {& v+ v- x
  739.         }
    + B3 z+ [9 l- g2 G/ t' @

  740. 1 |$ w' u8 g' O; Z% W& |$ C
  741.         /* transfer the image onto the frame window */( C* R) ?$ O1 S' O' Z' J3 Q
  742.         memset(full_window, 0xFF, full_window_size);, {3 N  T; y2 G& C2 @* ]
  743.         index = 0;6 X& L! M' [  Z2 N
  744.         for (y = 0; y < height; y++)1 P- _: `' U: r+ T% H
  745.         {0 }. c; }, m2 A+ ?* S# L
  746.             out_index = window_width * (frame_y + y) + frame_x;
    ' |3 q# |1 w6 p4 Y1 {' E
  747.             memcpy(&full_window[out_index], &decoded_frame[index], width);
    7 W  r% M$ V! D( s
  748.             index += width;" ~; C% o% C) y! F
  749.         }
    ) q9 ^: d! j* m& Q! {0 D

  750. 9 h7 v7 W* B- Z2 M4 V6 A: m* a
  751.         /* write the subtitle */
    ; D: x5 g& g+ U& ]. G+ q' ?6 p
  752.         subtitle_frame(rbt, full_window, window_width, window_height,$ Q( d) b' k8 ]: S
  753.             i * MILLISECONDS_PER_FRAME);
    4 S* r7 Z9 V, |) {
  754. " Y, [8 P2 ^" m' C1 {0 G5 k1 _
  755.         /* figure out the smallest change window */
    $ ^! ^' z: g6 Y& _# L4 n
  756.         window_top = frame_y;, U! o3 {& ]3 d! Q; a
  757.         window_bottom = window_height;
    ; B4 |& p9 S4 D( U- `
  758.         window_left = 0;3 \3 x8 S  ]  U. D
  759.         window_right = window_width;& Y2 I3 v: `1 K& ?7 M1 \7 u1 U
  760.         window_size = (window_right - window_left) * (window_bottom - window_top);1 M/ U5 O4 W. I, \
  761. % s/ d: \( ]/ @6 a+ D
  762.         /* compress the frame */* o) E4 U$ N" o' p
  763.         reset_put_bits(pb);
    : n& a, U0 v- o; z
  764.         compress_window(pb, full_window, window_width, window_top,
    ' t% d2 D  O7 u6 B2 u
  765.             window_bottom, window_left, window_right);& U4 C! I$ h9 j' t

  766. 1 T$ V8 ~+ S/ s( X2 z
  767.         if (rbt->dump_frames)
    & t4 f* w0 ~# h2 d4 F
  768.         {
    6 m! j4 K1 q* D% l! F" m1 h1 a
  769.             /* dump the frame plotted onto the full window prior to encoding,
    * C, o3 a& Y* l2 I4 O. t/ R
  770.              * with subtitle */1 k, n/ t# a9 w, N
  771.             sprintf(filename, "pre-encoding-frame-%03d.pnm", i);8 @( C  z: K% g2 E
  772.             dump_pnm_file(filename, rbt, full_window, window_width, window_height);
    ' p' \! a* y  a1 ~% B
  773.         }
    / w) P9 w! T# }0 Y
  774. " v9 E/ X1 ~, F4 D' D! T7 ^, I
  775.         free(decoded_frame);! w4 m$ L9 S" h3 u) i7 y) g% V

  776. ! F2 g& \- Y# ^) C1 ]! ^% y6 l# c7 c
  777.         /* update the frame header */
    $ Q) A* @( d( o$ S0 `! Q! @
  778.         /* width */& V5 p7 }8 u3 R* ?+ H: c+ S0 U5 i( U
  779.         rbt->frame_load_buffer[4] = (window_right - window_left) & 0xFF;
    7 i: B& |5 ]4 {5 Q' D, e: A. M
  780.         rbt->frame_load_buffer[5] = (window_right - window_left) >> 8;
    % {7 Y. }5 c7 y9 U# \7 G* M
  781.         /* height */
    ' ^( H$ ?9 `0 X. R* ~1 b- v& l' r4 ]- e
  782.         rbt->frame_load_buffer[6] = (window_bottom - window_top) & 0xFF;$ i! R6 c% S2 M8 u! a* b% _
  783.         rbt->frame_load_buffer[7] = (window_bottom - window_top) >> 8;
    6 `( k8 J. E  ~4 N9 O7 S
  784.         /* origin X */$ ?* w; i2 _# b8 ?; R
  785.         rbt->frame_load_buffer[12] = window_left & 0xFF;& T  T" P2 @5 u: r$ c3 K! b
  786.         rbt->frame_load_buffer[13] = window_left >> 8;0 [, K; P) v3 i$ H: F; ^- `
  787.         /* origin Y */
    4 @: Z# ~) M: N& a$ Y6 x7 S
  788.         rbt->frame_load_buffer[14] = window_top & 0xFF;! C/ p3 A$ l; m2 |- H9 ~( y
  789.         rbt->frame_load_buffer[15] = window_top >> 8;/ Q% {9 e* d- \1 @
  790.         /* fragment payload size */: }) g$ k& h; o6 Q" o7 e, k
  791.         rbt->frame_load_buffer[16] = (pb->byte_index + 10) & 0xFF;! C- @$ K8 F' }4 z: V
  792.         rbt->frame_load_buffer[17] = (pb->byte_index + 10) >> 8;
    9 I7 f2 w8 k! Y- S' ]
  793.         /* fragment count (1) */
    ! ]8 b% u6 l( R$ c: y! E6 l
  794.         rbt->frame_load_buffer[18] = 1;
    2 t3 B  k: ?4 A/ \+ d
  795.         rbt->frame_load_buffer[19] = 0;
    , K1 c3 _1 ?  E  a/ H8 g$ v* a

  796. 7 t- I+ W5 `( y5 w# v' e
  797.         /* update the fragment header */
    8 @1 Y0 T) U6 H
  798.         /* compressed size */
    4 v- y$ V& E! ~  ^' i& W: L
  799.         rbt->frame_load_buffer[24 + 0] = (pb->byte_index >>  0) & 0xFF;+ U  d, I- m4 d+ @4 b+ N6 }7 }
  800.         rbt->frame_load_buffer[24 + 1] = (pb->byte_index >>  8) & 0xFF;
    5 `/ L) }5 o7 a+ n: Q
  801.         rbt->frame_load_buffer[24 + 2] = (pb->byte_index >> 16) & 0xFF;6 p0 [! d% ~  j4 n
  802.         rbt->frame_load_buffer[24 + 3] = (pb->byte_index >> 24) & 0xFF;+ e6 n/ G; Y; G$ s+ N
  803.         /* decompressed size */' y1 W& q0 X! ~7 F3 `
  804.         rbt->frame_load_buffer[24 + 4] = (window_size >>  0) & 0xFF;2 V  u2 A. w) X8 f
  805.         rbt->frame_load_buffer[24 + 5] = (window_size >>  8) & 0xFF;6 N( B2 u/ D  D' s7 O
  806.         rbt->frame_load_buffer[24 + 6] = (window_size >> 16) & 0xFF;! h* ?2 b  [+ U
  807.         rbt->frame_load_buffer[24 + 7] = (window_size >> 24) & 0xFF;! [4 B" X1 U: ?& j2 G
  808.         /* compression format 0 */
    + \1 v7 p3 n) e  C0 N# E+ Q7 x
  809.         rbt->frame_load_buffer[24 + 8] = 0;
    : m% T/ C1 D- h( v" C; i% R, U# O
  810.         rbt->frame_load_buffer[24 + 9] = 0;$ N/ z1 w* p& r; l
  811. 8 ~* h+ A1 j/ [- [& ^: r
  812.         /* write the 24-byte frame header and the 10-byte fragment header */1 y$ K; w  _* D! t8 F
  813.         if (fwrite(rbt->frame_load_buffer, 24 + 10, 1, outrbt_file) != 1)
    . E0 q  V6 g* C
  814.         {
    9 d8 z  u2 M9 }6 U& ^; x
  815.             printf("problem writing frame %d\n", i);
    $ d' x4 k* C# t  j4 S7 h
  816.             return 0;# m8 J. ~1 f! Q9 N* y8 {
  817.         }& S( D7 N: e7 u4 o

  818. : n9 s/ E6 |9 b% _
  819.         /* write the new compressed frame data */
    $ G0 Y6 l/ x# \1 f# j
  820.         if (fwrite(pb->bytes, pb->byte_index, 1, outrbt_file) != 1)( B) I& _0 W, u; `* T" R
  821.         {
    5 A$ X' l2 R* R* d( i
  822.             printf("problem writing frame %d\n", i);
    $ Z+ s$ j" @1 ^! f4 k) _
  823.             return 0;$ _4 S; D) F$ e# p) m
  824.         }
    $ N1 P6 R) Q8 w- L( P+ ]# g
  825. $ k( C  m2 Y( d# z2 }
  826.         /* write the audio data */. y* B9 p2 V5 V* b' m1 K; X
  827.         if (fwrite(&rbt->frame_load_buffer[video_frame_size], frame_size - video_frame_size, 1, outrbt_file) != 1)& B  @" Y* o* o. \) Y$ |- w6 }
  828.         {! W) S# ^' j# e: [. }0 I
  829.             printf("problem writing frame %d\n", i);
    3 F: x! w8 T' t
  830.             return 0;
    2 l) z( ^- W) K4 t  N' d3 [  n# J
  831.         }
    . |3 r' H5 m- W& `/ O

  832.   i0 \- X6 v3 K# ^
  833.         /* update the table entries */
    & Z' H0 W+ I' y7 v+ z/ B
  834.         video_frame_size = pb->byte_index + 24 + 10;9 u. L) V- l! ]( ^$ B4 k
  835.         frame_size = video_frame_size + audio_frame_size;, u8 d# V. T! y( v" }* p& J7 @
  836.         rbt->frame_size_table[i*2+0] = frame_size & 0xFF;
    ! v5 R# ?0 B  m
  837.         rbt->frame_size_table[i*2+1] = frame_size >> 8;1 I, c% Q  ~3 X
  838.         rbt->video_frame_size_table[i*2+0] = video_frame_size & 0xFF;
    * b  x: B' I% }* t4 y, F' @6 c
  839.         rbt->video_frame_size_table[i*2+1] = video_frame_size >> 8;* t0 C5 F. [8 D- e& f: ]4 Z! q; h
  840.     }
    5 J; R6 d8 o5 M# y$ ]5 a# A

  841. ; @6 v1 X' ]/ `* _0 o: f; ^
  842.     printf("maximum dimensions seen are %dx%d\n", max_width, max_height);
    ( j/ W7 w+ T& s% N
  843.   A4 M1 `6 s  J# w
  844.     delete_put_bits(pb);" h! w  Y- `3 q1 F0 K4 a  L
  845.     free(full_window);3 _/ j% u- h! f$ H( V: I! c

  846. % B$ H% s. S6 y! h: Z
  847.     return 1;" G) m* X+ T3 R+ t
  848. }
    7 M1 H) B: I& q

  849. ( J; [& }+ X, Y$ l- `' Z& z0 F
  850. int main(int argc, char *argv[])
    0 d! J- `) b0 S. k) [- u$ o
  851. {
    1 K4 g8 o- Q/ G# o  f; W/ Q
  852.     char *subtitle_filename;, K' p' X, m. K" Z) g" ^
  853.     FILE *subtitle_file;
    + `5 H. @# k, g: w$ \9 d6 I6 |/ I
  854.     char *inrbt_filename;% a1 g- x$ Z: u( V
  855.     FILE *inrbt_file;
    & V0 B1 A/ I" Y# b  u
  856.     char *outrbt_filename;
    + q3 Z0 G. L- p6 z7 {4 i
  857.     FILE *outrbt_file;
    9 m; V3 b( j- a0 B) d, ]6 x7 \
  858.     rbt_dec_context rbt;
    ' S7 d) k. t7 |
  859.     int origin_x;
    2 ^& k/ D/ z$ ?2 {$ y3 p0 _
  860.     int origin_y;
    ) L% J2 I$ s  v$ s
  861.     int window_width;
    , n9 n$ ]% w" S3 z  S
  862.     int window_height;! [, b' `0 S, e( Z  d0 Y

  863. , N% r! b/ p1 L% }
  864.     /* testing the bit functions */
      O) i5 f3 _; H- \0 H8 V
  865. #if 01 W" U  F9 W7 o7 V
  866.     int i;
    ( I* c( O! E9 u. a1 d
  867.     uint8_t bytestream[] = { 0x55, 0xAA, 0x00, 0xAA, 0x55, 0x77, 0xFF, 0x1B, 0x70, 0x8F };$ v6 f3 N: M% ?: Q/ K( n( u
  868.     int bytestream_size = 10;" J# d, Y6 R0 {3 Z
  869.     get_bits_context gb;
    , z2 X9 M: r- ^% T0 u
  870.     put_bits_context *pb;
    $ K9 Z: v/ ^* ?; C$ H2 l' M
  871.     int bits;
    $ t3 |* O8 I# ~0 v
  872.   m' S1 C" n3 O
  873.     init_get_bits(&gb, bytestream, bytestream_size);
    5 g- ]6 i. u! T8 ]2 F  X
  874.     pb = init_put_bits();
    * x$ [. O7 X4 p  W. @( X5 \. f
  875. 3 U. n4 K0 r' d1 A+ h- G0 A
  876.     for (i = 1; i <= 12; i++)
    & }) `  }/ P! h3 D9 Y! c/ d
  877.     {
    8 w2 q! _4 h7 S. F2 r- V8 M
  878.         bits = view_bits(&gb, i);# N! l( c: t6 D# s7 V+ ]8 c- P
  879.         printf("view %d bits: %d\n", i, bits);
    . b: ]4 u; v8 u/ u' d
  880.         printf("read %d bits: %d\n", i, read_bits(&gb, i));& S  d: N2 }- z! d
  881.         put_bits(pb, bits, i);
    9 ]  Z/ U/ }1 }8 N) u  l7 c( W3 T1 t
  882.     }- }; c- I  H0 d6 v6 z  P
  883.     put_bits_flush(pb);) S  Z% q1 L8 B- Y

  884. 3 V, m* f1 c; l, g
  885.     printf("original bytestream:\n");
    ) P- T& E$ x/ [
  886.     for (i = 0; i < bytestream_size; i++)) U; c& W7 n$ C& o7 p/ R
  887.         printf(" %02X", bytestream[i]);$ @( _" u. m( t: A$ e
  888.     printf("\nnewbytestream:\n");
    , K+ O& U& o: u' t/ l
  889.     for (i = 0; i < pb->byte_index; i++)
    6 l8 h* j, B/ y% J9 V
  890.         printf(" %02X", pb->bytes[i]);& Q! k$ ^' J# f& t) o0 t0 k
  891.     printf("\n");
    ' j, ?) o- K9 L2 Z5 Y
  892. 2 ^$ m' {1 s. V
  893.     delete_get_bits(&gb);
    - s4 q: r, M) r2 b# Z6 T5 X  z
  894.     free(pb);  P6 q$ _* ]& z
  895. #endif
    4 O. g6 T$ e* H# M: S
  896. , d( ?0 Z8 e9 S
  897.     /* validate the number of arguments */5 u/ {- J) \+ Q2 Y
  898.     if (argc != 8 && argc != 9)7 F; E0 E0 I0 a/ q
  899.     {! }3 P- ^& g! c, G3 U
  900.         printf("USAGE: subtitle-rbt <subtitles.ass> <in.rbt> <out.rbt> <origin X> <origin Y> <width> <height> [dump_frames]\n");
    $ t/ l  f; E% w2 H0 c  l$ x; x9 v
  901.         return 1;5 g" M# T6 ]: |/ h
  902.     }4 E2 W0 k. Z; @5 W
  903.     subtitle_filename = argv[1];9 g& r" T. ]* K, ^, R+ v
  904.     inrbt_filename = argv[2];
    # N  d, q1 e+ a% X) d
  905.     outrbt_filename = argv[3];
    & e( [# i: e1 R- O  t/ y
  906.     origin_x = atoi(argv[4]);
    : I# n( f; I9 o3 k2 j4 C* Z5 ~
  907.     origin_y = atoi(argv[5]);
    9 J$ F% h8 o1 _+ }0 x6 R
  908.     window_width = atoi(argv[6]);
    7 f4 |& R4 u# O/ N: }  U4 n
  909.     window_height = atoi(argv[7]);- s& Z3 R0 [7 J! B3 ~' _
  910.     rbt.dump_frames = 0;! A: N4 Z; q! N- c5 F
  911.     if (argc == 9)
    3 A. [0 R, @5 v. v
  912.         rbt.dump_frames = 1;
    8 J" a" B( L& r3 d

  913. 5 p8 Q0 q7 x  Q' R& u( C. j* n
  914.     /* verify that the specified input files are valid */
    / M3 |1 s# k7 V' b
  915.     subtitle_file = fopen(subtitle_filename, "r");
      J) Q" q; y, }4 C
  916.     if (!subtitle_file)
    6 u* G9 [9 Y; h1 Y3 J% R& h8 Z# a& s
  917.     {
    7 f( U  S- a# o9 ]* f
  918.         perror(subtitle_filename);
    + g0 ]  W4 A: [& [2 `; E( z
  919.         return 1;8 U9 f+ [5 K! ^5 U# v% C( G
  920.     }
    8 F8 T6 |8 L% V) ^. [
  921.     fclose(subtitle_file);
    4 S, t7 H: M/ F+ E9 F2 M3 d
  922.     inrbt_file = fopen(inrbt_filename, "rb");. }- G5 x# n) L3 o- q/ Q- \
  923.     if (!inrbt_file)! |" I* F1 Y& H7 q
  924.     {
    7 ~! F2 \) S2 R0 g
  925.         perror(inrbt_filename);
    . G# Y. O- g0 |; `* i3 H
  926.         return 1;4 C- J# x: d4 @5 F7 n6 Q
  927.     }+ R% Z6 q6 s. w) u( f% q

  928. - Z: D/ d+ ?# L& _/ r3 d
  929.     /* initialize the subtitle support */- M% j. G0 t, l) D+ ~5 `
  930.     rbt.ass_lib = ass_library_init();0 T3 V5 [( O, f1 z
  931.     rbt.ass_renderer = ass_renderer_init(rbt.ass_lib);
    : Y6 q4 W' _0 d8 g
  932.     rbt.ass_track = ass_read_file(rbt.ass_lib, subtitle_filename, "UTF-8");
    # Y* R, s$ u5 a' `9 z  K, v9 a+ c
  933.     ass_set_frame_size(rbt.ass_renderer, window_width, window_height);
    ' Z3 c+ w3 k0 ]  E3 u+ G$ o
  934.     ass_set_fonts(rbt.ass_renderer, NULL, NULL, 1, NULL, 1);
    % f1 k: l' a- j

  935. 4 n# J0 s- {# N$ J$ H* X) F! a
  936.     /* open the output file */
    ! _: {" }5 O) j
  937.     outrbt_file = fopen(outrbt_filename, "wb");6 z6 q" p' {. t3 {6 {" v$ n
  938.     if (!outrbt_file)
    # o4 D2 }- m6 @( L0 T$ `
  939.     {0 E6 z( w8 y- Q7 i' h5 W: i
  940.         perror(outrbt_filename);
    * n# j5 E/ f- M1 \
  941.         return 1;
    * \9 \" g$ j# n+ h! T
  942.     }/ h3 i6 `: f: i0 I/ G' [6 a' @

  943. 7 s. v% D+ R2 b0 M* h  [+ _. A
  944.     /* transfer header from input to output */
    1 Q+ Y6 G) q# F# `, e8 n' Z4 C. S3 ]
  945.     if (!load_and_copy_rbt_header(&rbt, inrbt_file, outrbt_file))5 A0 C% z6 G$ N6 @/ U
  946.         return 1;) j+ W  _! D3 ~9 ~, c1 ~
  947. - Q- r, x' X# B2 K4 P
  948.     /* rewrite the frames */
    $ L' B9 s' i8 D" K! o/ N, F
  949.     if (!copy_frames(&rbt, inrbt_file, outrbt_file, origin_x, origin_y,
    % N% _7 f7 O8 u+ e8 ^" V9 R; q
  950.         window_width, window_height))0 |  D3 o) p3 e* }0 d* j; S! L
  951.         return 1;4 t: F0 b8 m. }: ^. r- C
  952. 4 W* _" o/ j% G4 u8 K' @8 X$ d4 q
  953.     /* write the modified frame size tables back to the file */5 C* i% z/ v/ v) o# m
  954.     fseek(outrbt_file, rbt.video_frame_size_table_offset, SEEK_SET);
    & j9 O+ w0 }# C$ j; A$ Y! D1 r# _
  955.     fwrite(rbt.video_frame_size_table, rbt.frame_count * sizeof(uint16_t), 1, outrbt_file);$ \; I, q! c: k  _) l) U5 Y) f
  956.     fseek(outrbt_file, rbt.frame_size_table_offset, SEEK_SET);7 a% o, ?: z6 a5 U- A
  957.     fwrite(rbt.frame_size_table, rbt.frame_count * sizeof(uint16_t), 1, outrbt_file);  l9 [  j' W4 j6 n* s- i2 c+ g# a4 b
  958. & Z+ x) v8 x; O0 N  x" b" J% f9 L
  959.     /* finished with files *// Q& t, ~: R" `5 \
  960.     fclose(inrbt_file);8 D& t% d  a& l* l* t
  961.     fclose(outrbt_file);
    ! A, V9 b: t5 P0 P
  962. 2 e/ m: d6 q$ _6 Z+ M' N5 K/ I
  963.     /* clean up subtitle library */' k2 X* M) A7 r& n
  964.     ass_free_track(rbt.ass_track);
    # K) d$ ~- I! U, T9 o- g$ D
  965.     ass_renderer_done(rbt.ass_renderer);
    : a) R" \8 l/ v; f; l
  966.     ass_library_done(rbt.ass_lib);" {+ ?* r! ~+ w' q; D
  967. , t1 @2 f+ o( [( x% _9 O
  968.     /* clean up */
    ) S  V3 |9 ~- D/ W& d. u
  969.     free(rbt.frame_load_buffer);
    6 K& B1 H) W$ y/ U- |
  970.     free(rbt.video_frame_size_table);7 W0 u: w+ s4 m0 x
  971.     free(rbt.frame_size_table);5 w& s+ c+ K) C  x$ a, ~
  972. % B9 Z% r+ i. P2 _" R
  973.     return 0;
    4 S5 f+ R1 H) i6 S! Z
  974. }
复制代码
/ K; b) k) ~1 Y0 L, A) w; m4 [0 g
6 I! \( g( h, t
7 S( m) f- l' u4 a" d
' w3 r0 V! l: N: k5 s/ C
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 很美好很美好 很差劲很差劲
回复

使用道具 举报

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

使用道具 举报

板凳
 楼主| 发表于 2009-11-19 11:38 | 只看该作者
引用第1楼soring123于2009-11-19 11:09发表的  :/ q  r7 `& R0 z* O6 a
这游戏有字幕吗?

: h8 x! O4 @: \2 U, H9 D0 ^7 [. X1 Y好像没有字幕,我说的是给视频外挂字幕方式的汉化。
! v) n! J( [* \) [就像syberia2汉化版下面那行字一样。
回复 支持 反对

使用道具 举报

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

使用道具 举报

5#
 楼主| 发表于 2009-11-19 17:39 | 只看该作者
引用第3楼soring123于2009-11-19 17:07发表的  :  t# Q  a1 U2 j1 [( |8 J6 H
我记得是没字幕的 比较麻烦 都是视频的
; m4 n& L3 R: `0 Y3 ^
给视频外挂字幕方式汉化也许能行。) }% V' E7 Q- g" ^- W
要结合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日,是全球华人共同的冒险解谜类游戏家园。我们致力于提供各类冒险游戏资讯供大家学习交流。本站所有资源均不用于商业用途。

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