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

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

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

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

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

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

本帖最后由 shane007 于 2021-1-2 13:56 编辑 / J" s5 }& Q8 Y, v! ]
3 ?* a: ]: n. z
最近找到了一些和幽魂系列Phantasmagoria 有关的资料,' i! E7 o+ w2 C: w1 X4 f: j3 K+ S3 A
也许将来可以用于汉化。
9 V' X0 ?0 P3 b: I3 [1 I$ v
( {+ ~# V7 w2 O( {和日文版有关的信息0 a3 X: n* Y2 u0 ~
http://anthonylarme.tripod.com/phantas/phintgtp.html
5 R$ `1 m2 m3 K  G5 z8 y7 m! _, D: u, F
相关工具
' Y& N2 B8 j2 g3 `http://anthonylarme.tripod.com/phantas/phcheats.html
$ s: J/ o: D0 \$ L: B; ^-----------------------------------------------------------------------
9 d6 h& K! z: Y3 C- F3 `! R; c2012/1/2  更新
  E# h/ z8 h2 m8 M/ L" g7 ~, G! W. H关于幽魂游戏的字幕
4 J" Z8 {; i0 ?- D* OPhantasmagoria subtitles function discovered - ScummVM :: Forums0 x" M& v, h5 j; X8 M1 X

8 y! M/ ~- o: ^+ QVMD文件6 [' R" @7 m6 M1 y# X3 t0 l, _2 n
Subtitling Sierra VMD Files | Breaking Eggs And Making Omelettes (multimedia.cx)VMD - MultimediaWiki
% {+ r. ?9 T8 L1 R4 B
- a- x, r2 W+ _字幕
: D) P+ V8 l0 ^' q! Y3 ESubtitling Sierra RBT Files | Breaking Eggs And Making Omelettes (multimedia.cx)8 C4 j8 F% A, h+ c: M+ j
4 }4 A0 G0 ]- A7 x$ |
FFmpeg/subtitle-rbt.c at feature/VMD_encoder · multimediamike/FFmpeg · GitHub" D) \1 s$ K' }* k: m0 H6 f+ G  n& u
  1. /*
    $ c1 D+ D1 f9 f3 G" [# {
  2. * subtitle-rbt.c0 V% e) Q4 G& B  Y0 g
  3. *  by Mike Melanson (mike -at- multimedia.cx)
    % L3 j+ U& |8 l+ K* A1 W" F" j
  4. *; p7 P* k/ U2 Z% Q3 K
  5. * build with this command:
    4 s! h& b+ a, Q5 i; ]
  6. *   gcc -g -Wall subtitle-rbt.c -o subtitle-rbt -lm -lass
    - J# P. M1 ~: g. [+ m8 a
  7. */
    ' z1 K. a- d' q& S" c& V

  8. ) d$ p2 a% b" |$ U8 t
  9. #include <inttypes.h>
    0 U) g/ M& u! `+ w! Q; I) j/ w  W+ X8 @
  10. #include <math.h>  \0 A$ T7 o+ K/ k$ N% Y+ \5 b
  11. #include <stdio.h>* a) Q$ i# k) Y* _
  12. #include <stdlib.h>
    . R, `9 S% h0 c
  13. #include <string.h>
    - ]+ [+ j1 r  a# b' t9 p$ ^5 H

  14. & W, M" Q1 \' N) C. I, U
  15. #include <ass/ass.h>- V: b+ S3 s, i! B5 T

  16. $ U0 a( l9 i* [2 E& m
  17. #define LE_16(x) ((((uint8_t*)(x))[1] <<  8) | ((uint8_t*)(x))[0])( `- I( ^# D" O  d; z1 j
  18. 9 t6 ~- m. z$ V9 o" j5 }
  19. #define LE_32(x) (((uint32_t)(((uint8_t*)(x))[3]) << 24) |  \
    ( Z6 U) C+ t5 G% Z
  20.                              (((uint8_t*)(x))[2]  << 16) |  \
    ( v8 G0 ~5 k' A6 e2 {9 d6 [
  21.                              (((uint8_t*)(x))[1]  <<  8) |  \
    ; I/ e9 `& e9 f9 A
  22.                               ((uint8_t*)(x))[0])
    3 L0 _! F9 x8 ], G" Z9 v. Q

  23. , V. s! i0 ^8 K! P+ O
  24. /*********************************************************************/
    6 u' R& c' t1 Z/ r4 c8 \" O

  25. , n- A3 j. ~1 g* h! O
  26. /* Bit reader stuff */
    4 \/ J% W6 W" _( A* ~+ l4 h7 D! a5 [
  27. ! E: c& n9 Y& |
  28. typedef struct, H# U$ [$ K6 u: z- M0 N. R4 L
  29. {. K" B3 R0 b& x% _
  30.     uint8_t *bytestream;: \7 w8 I- J1 Z# `$ Y. K3 o
  31.     int bytestream_size;
    $ e0 V* M9 B/ D' j
  32.     int index;
    & q* J& {& u5 L8 p) [/ J$ w
  33.     uint32_t bits;
    7 S" o. ^& U. ?1 [# E
  34.     int bits_in_buffer;+ E* x6 s& H* ~" W1 x
  35. } get_bits_context;; p$ e# W2 I. f( }+ i

  36. 7 w. ?8 r' C/ c3 G/ u7 l: K
  37. static inline void reload_bits(get_bits_context *gb)5 ~; s  [, |$ A! z" J2 Q) W
  38. {( {  D; X2 Y" S9 \: L6 _
  39.     while (gb->bits_in_buffer <= 24)
    ; b' B- s+ z0 H1 T. }
  40.     {, j/ |/ x& p  }
  41.         if (gb->index < gb->bytestream_size)
    & R  W5 u2 R) p8 w: y
  42.             gb->bits |= (gb->bytestream[gb->index++] << (24 - gb->bits_in_buffer));
    ( V/ f, W; E7 s. @: [0 T
  43.         gb->bits_in_buffer += 8;
    ( w: C, i7 Z' _& Z. k: v
  44.     }
    ! I$ N9 Y8 P& ?$ ^9 v3 M
  45. }
    0 v8 w) Y3 h& F0 X
  46. . p. \3 j/ @1 f4 L" v6 M
  47. static void init_get_bits(get_bits_context *gb, uint8_t *bytestream, int size)
    ) r& L0 E7 M3 A& Z' I# B6 @
  48. {9 L0 S: i# v% \, u; [
  49.     gb->bytestream = malloc(size);) i- S& j" i- t! t4 i' a  ^4 b
  50.     memcpy(gb->bytestream, bytestream, size);: T' M5 K; W* h5 p$ |+ }- T  S
  51.     gb->bytestream_size = size;
    ! C# P" b" D+ h' v; E" t  ?- W
  52.     gb->index = 0;
    - \& [8 e6 o2 B4 \+ i
  53.     gb->bits = 0;9 x/ j' \( F/ @2 E3 R+ o
  54.     gb->bits_in_buffer = 0;6 {- b8 M1 I  w- H8 C
  55. ) B* U7 _; s. R" `& t, P9 Y
  56.     reload_bits(gb);
    7 }: g* p: [6 ]- t  Q% H9 G7 R
  57. }
    - U* W, z8 _9 O) K

  58. ) r# c9 ~1 A2 j* n  {; _
  59. /* read bits without consuming them from the stream */5 K. c0 s8 ]% k$ z: t7 r
  60. static int view_bits(get_bits_context *gb, int count)
    - D$ ?5 v: P& v* t/ t% A
  61. {
    # S: A4 e7 t' O9 Z' V& H- N
  62.     if (count >= 24)$ w4 ~3 `5 M  r0 h& b$ _- c! j
  63.         return -1;
    - b9 |7 D/ R7 Z& M
  64.     if (gb->bits_in_buffer < count)4 e, H4 v8 Y" b
  65.         reload_bits(gb);
    ! O4 e9 {. K  o) v$ U
  66.     return (gb->bits >> (32 - count));3 j' x4 N9 O) l  P
  67. }+ N1 \, E. W& K) k8 l' s2 n% J

  68. ( g6 g3 J6 b* {# Y1 I* T+ ^
  69. /* read and consume bits from the stream */+ L6 t9 o5 Z8 ], ]
  70. static int read_bits(get_bits_context *gb, int count)
    : b7 n- A8 V) o/ E; M/ I2 z6 D
  71. {
    # `1 h: ?* D; E' b( R$ s! W; m5 R
  72.     int value;  a3 R# i8 @6 _2 m2 E; f

  73. 2 M! s+ V- c  ^6 c, e
  74.     if (count >= 24)
    ( S5 [& d9 U* f: J) b  `$ E
  75.         return -1;
    4 y1 }: \* M( ]4 O

  76. ) V( n/ o( o/ D5 Q
  77.     value = view_bits(gb, count);
    8 ~- g9 |( k+ j( H
  78.     gb->bits <<= count;3 h% J% c  N! E1 {: ~
  79.     gb->bits_in_buffer -= count;
    / N" m) I: M! a$ P) _1 H

  80. " [0 h$ y: u8 g8 ]
  81.     return value;
    9 r% H" J9 W; b  [* e. }8 x
  82. }
    $ m" M, a. {+ G% N3 B7 G
  83. ) ?0 _% w, X3 M
  84. static void delete_get_bits(get_bits_context *gb)9 i0 s, c/ M) L8 V( S( d9 w$ p
  85. {  T5 w: @0 \( H, X
  86.     free(gb->bytestream);
    5 b+ [2 N" K' s/ `$ U% O" h
  87. }
    ( \6 I6 a9 `! b
  88. 3 B7 M5 n/ ?# e: D7 ?+ O1 x
  89. /*********************************************************************/
    $ w8 J: B5 u: ]/ w( \+ I; ]( V

  90. 1 Z8 `6 Y3 _' k0 c: H) {
  91. /* Bit writer stuff */
    + r6 u1 E' f  z+ d9 W/ R

  92. 4 l( w2 D' Q5 A' D, D& J' M( k- {
  93. #define MAX_PUT_BITS_BYTES 63000
    0 r6 r! Y' W4 T" U
  94. typedef struct
    " C! C! h  A5 _) E' |
  95. {
    # c1 }. F' z  ]9 f0 Y& X
  96.     uint8_t bytes[MAX_PUT_BITS_BYTES];
    % q' Q4 n& B  `
  97.     int byte_index;! U, q+ k) K, j* Z4 O7 b8 {
  98.     uint32_t bit_buffer;% I/ y2 k9 C; ?2 ]7 z0 N! I& G7 G
  99.     int bits_buffered;
    * ~  r8 Q" e; a2 G* v- Z
  100. } put_bits_context;
    : Z) ~5 f$ \' m7 I  _$ Q9 c
  101. 5 N! a! W# E4 I' U! u& P
  102. static void reset_put_bits(put_bits_context *pb)9 [! P! |+ }$ t2 h, t  y
  103. {
    4 J" e# H- j8 K5 ~. L0 r7 T7 I' `
  104.     memset(pb->bytes, 0, MAX_PUT_BITS_BYTES);
    3 K3 I- I' Z! ^& o* F
  105.     pb->byte_index = 0;
    / z5 Q( a, J' x3 z! G4 P& q
  106.     pb->bit_buffer = 0;
    2 q7 O% ?. S; @8 K: J! i4 t5 |; K
  107.     pb->bits_buffered = 0;7 P+ [. ~* T6 {6 i  c7 Z1 a
  108. }$ R, o4 y0 R, A
  109. * Q! \* W$ j" f. [" ~/ {3 ?7 R+ H
  110. static put_bits_context *init_put_bits()
      S1 K3 x) T/ W. a$ d
  111. {
    5 ]1 \7 l5 N5 [4 }
  112.     put_bits_context *pb;
    & P5 Q2 N+ x  V5 G1 ]

  113. % v, |6 F# @$ G
  114.     pb = malloc(sizeof(put_bits_context));/ N& }1 e+ A! h
  115.     reset_put_bits(pb);% r6 L" n& _( M' |: A2 b5 y8 ]

  116. 8 b9 U8 C7 x! y: l  I
  117.     return pb;! s9 i) w4 V8 i  G, g3 q+ r# a& H
  118. }7 k+ Y/ d% t# ~# h) g# \% B

  119. , v' ]9 p  A; S$ _
  120. static void put_bits(put_bits_context *pb, int bits, int count), `+ O# N# }6 R# I. E
  121. {+ P& Q# B$ Y) k# W6 q
  122.     pb->bit_buffer <<= count;; f/ _4 g  E& Y6 o2 k* R$ t+ v( q, z; `
  123.     pb->bit_buffer |= (bits & (~(0xFFFFFFFF << count)));
    1 ]- i" h% H0 t' X" ?: _  X
  124.     pb->bits_buffered += count;# \1 w2 {6 |2 u( `& p
  125. - G2 c% Z+ j* J, o( G) A
  126.     while (pb->bits_buffered >= 8)
    & A5 `7 M; k9 l  ?+ \. P
  127.     {
    0 r) Y) L  q' U- `& k& [5 }9 A
  128.         pb->bytes[pb->byte_index++] = pb->bit_buffer >> (pb->bits_buffered - 8);0 F* s) k7 `# }+ t
  129.         pb->bit_buffer &= (~(0xFFFFFFFF << (pb->bits_buffered - 8)));
    ' Q3 U1 C. q+ P
  130.         pb->bits_buffered -= 8;
    / L$ Z6 N' z4 @, s% Q/ E
  131.     }
    9 N2 k# E' t1 s9 K

  132. * b1 t6 y( q. j2 V! n
  133.     if (pb->byte_index >= MAX_PUT_BITS_BYTES)( H! u2 \% r- t
  134.     {: b% ?) w. M- U
  135.         printf("HELP! Bit overflow\n");% W& x+ t: w1 |! D$ b) _8 T
  136.         exit(1);
    ! k! D* B* y2 D
  137.     }2 M0 |( L4 {' v+ S2 t* F) r
  138. }0 J; h( E1 r- r5 l) ~* J7 r+ ^

  139. 8 F$ @  z+ `$ l- H
  140. static void put_bits_flush(put_bits_context *pb)
    5 l! u. g( ~/ H1 I+ W
  141. {* V: {+ p" _! f) Z$ w
  142.     if (pb->bits_buffered > 0)
    4 M7 ?  J9 H1 F- H5 n! Z
  143.         pb->bytes[pb->byte_index++] = pb->bit_buffer << (8 - pb->bits_buffered);
    + a1 j4 x& o- M" ?8 B; e/ v
  144. }4 c) F/ u$ y4 d% ^) W7 t- m% C9 M
  145. 5 d. h/ f, c8 t) f. }9 w
  146. static void delete_put_bits(put_bits_context *pb)
    6 [; I& M( R- T. h' Z1 A4 v
  147. {- D  q; t% T, E0 I/ t/ n, D
  148.     free(pb->bytes);: c2 d3 N) w  Q
  149. }0 h0 s3 C2 ], W9 K! ?

  150. & U( I! K# r' J0 N' L* S7 U
  151. /*********************************************************************/& Y7 u; X: e! c  h$ f1 A+ D

  152. % r& }" h! m* H  m: W7 v
  153. /* RBT functions */
    3 A3 Q: i/ [0 Z- [0 I0 \$ {

  154. ' M9 `9 H# P! }9 a- i
  155. #define PALETTE_COUNT 256
    ! a8 _, i9 v+ ]( Y6 {4 X
  156. #define RBT_HEADER_SIZE 60
    ! x, N" V2 E( ~0 r
  157. #define UNKNOWN_TABLE_SIZE (1024+512)
    ) p5 k1 V3 r) T6 `' J" J' Q# S
  158. #define SUBTITLE_THRESHOLD 0x70
    0 x% r) H% [" ?" o
  159. #define MILLISECONDS_PER_FRAME 1002 T9 X# l" i# o0 ?2 O- X
  160. 2 q& K+ o" |2 ]6 `5 L! J* l; I
  161. /* VLC table */
      R* n4 N1 @6 k; M1 \
  162. #define VLC_SIZE 46 y4 @$ l0 z  v/ E  ?
  163. static struct
    + R, p  y& @4 }1 m: y- e
  164. {) Z( R, v2 _" s9 z" m5 b2 h
  165.     int count;
    $ n4 ?6 ~' E0 ~- ~0 b
  166.     int value;' X, ^; P+ ?, z! Z6 w, b! J! C
  167. } lzs_vlc_table[] =9 r* Z, j& T% y/ B+ t7 @
  168. {. V8 u% `4 N3 j* i
  169.     /* code length = 2 bits; value = 2 */
    5 x1 A4 j$ A. P& p' r) a
  170.     /* 0000 */ { 2, 2 },
    ( S0 a3 _% x0 o3 F/ `' G
  171.     /* 0001 */ { 2, 2 },1 i# _* s, D; b8 C
  172.     /* 0010 */ { 2, 2 },6 d- |1 P$ a; j% A+ X
  173.     /* 0011 */ { 2, 2 },2 \. E- H9 ?" h  E

  174. ! y: _& z! f# V" i
  175.     /* code length = 2 bits; value = 3 */
    5 N& [. B) T8 u2 N2 P# q
  176.     /* 0100 */ { 2, 3 },
    5 u6 Q# ?1 {' K5 L6 g) H
  177.     /* 0101 */ { 2, 3 },+ S9 @* n7 l! A: m1 h
  178.     /* 0110 */ { 2, 3 },/ D- e) _9 R  R. q! o4 d8 O- {
  179.     /* 0111 */ { 2, 3 },7 W, F. Y! g) \" n9 V( k3 A; k

  180. $ Z- X0 l& y) ~0 v* Z6 y
  181.     /* code length = 2 bits; value = 4 */! ], f- ~6 }* {1 i) ^; |
  182.     /* 1000 */ { 2, 4 },
    2 x, w, U, r% z( w
  183.     /* 1001 */ { 2, 4 },
    % t6 ]9 v0 d0 W7 z6 s8 h
  184.     /* 1010 */ { 2, 4 },
    + J$ y. u4 W  g; {. x# x
  185.     /* 1011 */ { 2, 4 },
    ( k1 t' ^0 g8 S( s, C( Y2 S

  186. $ q0 O  R' Y! i
  187.     /* code length = 4 bits; value = 5 */
    5 c1 w" a4 B$ V  @# c, x7 x& Q
  188.     /* 1100 */ { 4, 5 },
    + c% I2 A- m8 y3 q
  189. 3 S6 g* e, s2 `
  190.     /* code length = 4 bits; value = 6 */, K9 P' U6 H( f) W
  191.     /* 1101 */ { 4, 6 },8 N- Y: m; }9 h/ Q: R
  192. " k  x& q8 _+ E. O, f0 z
  193.     /* code length = 4 bits; value = 7 */
    # h( s9 m$ _8 }* q% p9 _
  194.     /* 1110 */ { 4, 7 },' e: u4 P: v" Z4 A- z7 q2 [
  195. + ?" Q6 [( V* m. i
  196.     /* special case */
    ( P5 ^' u1 u, Y7 Y
  197.     /* 1111 */ { 4, 8 }9 V# h! q4 S& S1 g
  198. };
    $ D( j* s: G3 t

  199. 9 f/ A# t  n3 e+ D1 }7 }/ H6 a
  200. typedef struct
    + n4 }: U' N! m' D$ p. Y: r
  201. {$ d/ t5 c: u% V% }
  202.     int version;; T: @* n) M9 Q
  203.     int width;
    * h3 G* ]+ n7 }/ l
  204.     int height;& l. \0 _  P" y. M3 H8 |
  205.     int frame_count;
    3 d: ]  s* W- a5 k8 O
  206.     int audio_chunk_size;- |0 H7 a) B+ C4 O6 j
  207.     uint8_t palette[PALETTE_COUNT * 3];
    . P1 a8 Z# V0 g) c
  208.     off_t video_frame_size_table_offset;
    5 Z7 a, m( b. l" \* [
  209.     uint8_t *video_frame_size_table;1 o5 _% w  Q3 \2 n) I
  210.     off_t frame_size_table_offset;9 Z$ S. \# l% Q
  211.     uint8_t *frame_size_table;* j% |- e5 q" K% }' [
  212.     uint8_t *frame_load_buffer;
    # B8 N  k6 D! `  U: z
  213.     int dump_frames;
    2 D% L$ b! Y8 x- X$ |! K3 B

  214. ( k2 b+ }- D' e& z5 @$ j5 S
  215.     /* subtitle library */
    * c3 c- H9 ?! Q, V, a5 L* f
  216.     ASS_Library *ass_lib;, M# o% Q5 T3 U, j
  217.     ASS_Renderer *ass_renderer;
    $ w. h: X8 l1 d# F
  218.     ASS_Track *ass_track;5 K" R4 `+ l9 @% M# l5 Z
  219. } rbt_dec_context;
    ( S, V, ]" m" i' e

  220. , J; ?; K  A* p3 R3 j4 d7 _. L
  221. static void dump_pnm_file(char *filename, rbt_dec_context *rbt,
    ) `1 K& A4 t% |
  222.     uint8_t *image, int width, int height)
    ' J: |' D/ U. r  G
  223. {; y( D6 ]4 @3 z3 P8 x& S+ Q0 b
  224.     FILE *outfile;
    8 o! P3 e  z4 b
  225.     uint8_t bytes[3];  n4 u9 s- V% }% U+ {2 M) ?
  226.     int p;
    : u9 X/ D: @* h  q5 k6 ~$ u
  227.     uint8_t pixel;
    / ?& {5 l2 a4 z4 h! C- f! q& k
  228. 9 ^4 n7 I1 w8 ~/ C; j. O
  229.     outfile = fopen(filename, "wb");$ o* k8 A) h8 y7 L& J- E2 j
  230.     fprintf(outfile, "P6\n%d %d\n255\n", width, height);" [: m/ r6 ~/ M0 G4 y$ ~
  231.     for (p = 0; p < width * height; p++)
    ; \! p$ g  }, T8 r
  232.     {8 W/ {$ k' p- o5 {7 j+ M
  233.         pixel = image[p];
    ( g% u+ v- W9 y) S
  234.         bytes[0] = rbt->palette[pixel*3+0];
    0 ]: U5 L( _( l" j1 P3 h2 a* Z
  235.         bytes[1] = rbt->palette[pixel*3+1];/ I/ S+ y7 B3 z# K% }* O7 M" j% H
  236.         bytes[2] = rbt->palette[pixel*3+2];; W1 o0 R( J( {6 N$ @/ ?6 j! i
  237.         fwrite(bytes, 3, 1, outfile);' C4 d1 P8 U) s
  238.     }
    ( I1 \$ Q& n' A
  239.     fclose(outfile);
      [5 b( y- c; v! J" Y
  240. }
    % n& f# x) f# h- e

  241. ' y5 v) |4 O' f: l; |5 |
  242. static int load_and_copy_rbt_header(rbt_dec_context *rbt, FILE *inrbt_file, FILE *outrbt_file)
    , ~3 t/ p$ Q4 W$ ]  D. G/ P
  243. {
    # R9 d5 c. U9 p+ {
  244.     uint8_t header[RBT_HEADER_SIZE];3 ~( P' b9 }$ A0 ^
  245.     int palette_data_size;4 j- ^  t# `" A  I2 T
  246.     uint8_t *palette_chunk;
    6 p5 f8 a9 x; z+ p& M/ T& E5 N- p8 v
  247.     int unknown_chunk_size;, }# s0 a! D1 o& ^5 u7 y! I  P) G
  248.     uint8_t *unknown_chunk;3 F- q/ w" Y7 p  M' G8 Z' y0 k- A
  249.     uint8_t unknown_table[UNKNOWN_TABLE_SIZE];" p2 q# @' i  ?
  250.     off_t padding_size;
    0 h& c3 G0 v& c# j
  251.     uint8_t *padding;
    9 U0 w) n4 P" f9 v( C5 l
  252.     int i;
    # A2 T# S  V/ U8 F+ q) n8 j6 w
  253.     int frame_size;7 E' |$ N2 P  o" m
  254.     int max_frame_size;
    3 Q) F: ]; Q3 v* O+ I% M
  255.     int first_palette_index;) r+ |5 M- a+ |
  256.     int palette_count;
    / v" s* F2 u9 {% r3 J) w+ m5 o
  257.     int palette_type;
    6 A& E0 }. b! r% b3 L' C
  258.     int palette_index;  S6 c; c- A! B2 A  y) `

  259. 9 _4 K5 ^% d; Z* d, I
  260.     fseek(inrbt_file, 0, SEEK_SET);
    3 y9 X: \3 F# h) _
  261.     fseek(outrbt_file, 0, SEEK_SET);
    8 H5 ^, F5 \- c  r. h( g& K
  262. ! E3 [2 M; x+ r4 p( v
  263.     /* load the header */
    : m/ T) c5 P' b1 m4 S
  264.     if (fread(header, RBT_HEADER_SIZE, 1, inrbt_file) != 1). d& B' k6 p: v6 v$ ]1 K8 Y9 `) v
  265.     {& l5 L) `8 E! |$ p- I
  266.         printf("problem reading initial RBT header\n");* N) w. R8 d% u) I2 h
  267.         return 0;5 u" R' y6 ~0 n& S: g( U, @
  268.     }0 N8 ~1 P# \* t6 k  p9 J$ u4 Q
  269. 1 Y6 V) }; V# O# j
  270.     /* copy header to the output */
    $ ]* K7 \" b2 C3 C4 N9 m) }% I
  271.     if (fwrite(header, RBT_HEADER_SIZE, 1, outrbt_file) != 1), f/ n' s6 C$ b
  272.     {6 o. N! ?& F& A( Y* @4 g2 P
  273.         printf("problem writing initial RBT header\n");# j+ T/ C: c4 s, g
  274.         return 0;& W5 K: N8 a+ s+ n
  275.     }$ F. F  e" f6 y! u3 N
  276. 6 W* k  L- g3 ]# E" n: y
  277.     rbt->version = LE_16(&header[6]);. k( d% K3 d# E; d1 w% c9 c
  278.     rbt->audio_chunk_size = LE_16(&header[8]);8 A4 a7 c8 m; \; l# v
  279.     rbt->frame_count = LE_16(&header[14]);
    * o6 d' k4 z' p. k* S  d4 y* a1 B
  280. 8 E4 \; s, a% ?0 \
  281.     /* transfer the unknown data, if it's there */& D9 g- p& C1 B0 h( `# m! N- d
  282.     unknown_chunk_size = LE_16(&header[18]);: v5 _+ \7 N2 k5 n+ n
  283.     if (unknown_chunk_size > 0)
    9 D0 m: m2 ]9 F* m, S
  284.     {
    . N' F& T2 F) m' ?1 \0 a2 p
  285.         unknown_chunk = malloc(unknown_chunk_size);- A* Z: P" I: P( V. a
  286.         if (fread(unknown_chunk, unknown_chunk_size, 1, inrbt_file) != 1)
    ! b7 c' K1 ~' r$ j, C( Z
  287.         {
    , y( f5 c7 D0 k7 q# N: u9 i
  288.             printf("problem reading unknown data\n");; o& R: z; q7 s0 s
  289.             return 0;
    ' G- k) W% M; {' V# R  G& P' K
  290.         }2 W# z6 I! D  `7 E, ^
  291.         if (fwrite(unknown_chunk, unknown_chunk_size, 1, outrbt_file) != 1)
    ; U5 y' J' U6 r6 V. A( \' g( D
  292.         {; r& X* E9 y& L' i, G% s4 r
  293.             printf("problem writing unknown data\n");: s. |' ?; c$ R7 O/ x
  294.             return 0;$ M4 c0 K' ?) P; K: y
  295.         }' C  x! `7 `% _
  296.         free(unknown_chunk);4 ?( i8 T( W6 e% i
  297.     }
    1 i  H* X, A3 Q2 Q3 w

  298. 9 }2 p/ z* j7 G" [: m' c
  299.     /* transfer the palette chunk *// F: z- g, V  L
  300.     palette_data_size = LE_16(&header[16]);9 @( i3 X. `6 [1 K6 U
  301.     palette_chunk = malloc(palette_data_size);' Q' o: i3 D' B" o
  302.     if (fread(palette_chunk, palette_data_size, 1, inrbt_file) != 1)
    , B, k* M) u" |. C; p! d7 ?
  303.     {  x; b* y; q# |6 w. o
  304.         printf("problem reading palette\n");. f* ]: \+ g6 f7 z0 W6 G/ R
  305.         return 0;
    ! m3 ~, M( i  @; S: c! Y3 [
  306.     }" T" ]4 T. `" O1 f$ X: t
  307.     if (fwrite(palette_chunk, palette_data_size, 1, outrbt_file) != 1)- ^6 P+ q' I% s; W: x
  308.     {- S9 g/ c& c9 d8 w; B
  309.         printf("problem writing palette\n");* k# k- I, f; \' {( `+ o) I
  310.         return 0;* ~6 G% b9 O8 ?
  311.     }! J% Q' n5 ]1 e0 ]6 u: U
  312.     /* load the palette into the internal context */
    # ~: O* Q/ E% k3 I
  313.     memset(rbt->palette, 0, PALETTE_COUNT * 3);6 x, s+ f" i# ]# i0 d1 u+ C# c
  314.     first_palette_index = palette_chunk[25];& d: H% x: R- n7 D
  315.     palette_count = LE_16(&palette_chunk[29]);
    8 B  {# c  ]) k/ g/ b
  316.     palette_type = palette_chunk[32];4 Y6 f0 r2 i$ R8 l
  317.     palette_index = (palette_type == 0) ? 38 : 37;) A3 G& V4 ^3 s
  318.     for (i = first_palette_index; i < first_palette_index + palette_count; i++)8 r* E; W' I" S, F" W/ G* g9 O
  319.     {
    1 U% B' i% \7 u# h
  320.         rbt->palette[i*3+0] = palette_chunk[palette_index++];* C, `/ E( W# A& |$ l5 h
  321.         rbt->palette[i*3+1] = palette_chunk[palette_index++];
    : p* o& r( p: v- ^- f
  322.         rbt->palette[i*3+2] = palette_chunk[palette_index++];1 j1 J7 \# p8 g% n# \  S
  323.     }
    * y" o  a# j/ Z: _7 a* M3 O
  324.     free(palette_chunk);
    + ?  D' v+ |+ S

  325. : y5 P. t7 C' I$ U* u0 c& T
  326.     /* copy the video frame size table (2 bytes per frame), as a placeholder */% O+ h$ C: Z7 u6 `! i. e% N
  327.     rbt->video_frame_size_table = malloc(rbt->frame_count * sizeof(uint16_t));# E: Z4 y$ ]1 u2 A( w
  328.     if (fread(rbt->video_frame_size_table, rbt->frame_count * sizeof(uint16_t), 1, inrbt_file) != 1)( I$ G- z9 m+ s
  329.     {2 ~$ ?2 g2 h* [
  330.         printf("problem reading frame table\n");# s% a6 |5 U" X, }+ l! Q
  331.         return 0;
    / O* |# P) i- r, k! S+ j3 ^, f: ^
  332.     }
    9 d8 D0 l& F- d8 H6 i
  333.     rbt->video_frame_size_table_offset = ftell(outrbt_file);
    . ~/ I. ^  _+ @& S7 F: t; N3 I' ]0 I
  334.     if (fwrite(rbt->video_frame_size_table, rbt->frame_count * sizeof(uint16_t), 1, outrbt_file) != 1)0 F9 E' p- e& @: u
  335.     {) R" v6 X2 \4 \3 R: V% e* I& V% Q
  336.         printf("problem writing frame table\n");$ X3 M  ~" _% a% a# C( f$ e
  337.         return 0;
    $ a4 g' }: E6 s5 R: c9 v4 c4 P4 M1 X
  338.     }
    " Q8 H2 \! d5 D- P

  339. 4 `" r: A* l' P% N) D/ m; Y! }
  340.     /* copy the frame size table (2 bytes per frame), as a placeholder */1 e. d# C$ Y. n9 D6 z
  341.     rbt->frame_size_table = malloc(rbt->frame_count * sizeof(uint16_t));8 B) O3 F* O! D  w, U- C
  342.     if (fread(rbt->frame_size_table, rbt->frame_count * sizeof(uint16_t), 1, inrbt_file) != 1)3 [% `4 a( r4 c' B
  343.     {
    9 H6 i! [: h! h/ Y/ p0 c
  344.         printf("problem reading frame table\n");, n' l* b5 X- C6 i6 J- I
  345.         return 0;
    ; I1 A) A) J6 q* {) e2 _
  346.     }
    ) I% q( B1 R6 D6 {# _6 j1 }( M; c
  347.     rbt->frame_size_table_offset = ftell(outrbt_file);
    2 K$ ~* c# f6 X  l$ p
  348.     if (fwrite(rbt->frame_size_table, rbt->frame_count * sizeof(uint16_t), 1, outrbt_file) != 1): h8 i6 X5 U; _, Y3 t: l
  349.     {1 J+ J; E4 v+ n" j) _' o9 |
  350.         printf("problem writing frame table\n");% E3 s) ^/ n4 |, G
  351.         return 0;
    $ t% b. T& W  F( @2 K# D9 v7 g! x
  352.     }
    / m' q( T- b% Z& }. r+ G
  353. ( U( Q$ [( R; |" o: D
  354.     /* find the max frame size */# e0 \* u7 R& _0 Z
  355.     max_frame_size = 0;; C- @+ P; w# t: ~. X: G
  356.     for (i = 0; i < rbt->frame_count; i++)
    . d" C' T( X8 h  P6 H  Q
  357.     {$ v$ L& c3 b1 o# Q$ X9 s
  358.         frame_size = LE_16(&rbt->frame_size_table[i*2]);
    - e; w$ F9 S  [6 a# O. _/ ^
  359.         if (frame_size > max_frame_size)% E% g. P( A7 v+ ]
  360.             max_frame_size = frame_size;% e+ i/ h8 G* c! g) L# y) l' x" u! _
  361.     }) O- S. }& f% g% ~( R& R* I# L+ l+ C
  362.     rbt->frame_load_buffer = malloc(max_frame_size);
    & T- h( d2 Y- x$ @1 N
  363. * o' a, b: W' Q; v9 x7 z
  364.     /* transfer the unknown table(s) */
    / C" J0 _" y$ v/ \" k6 K- S
  365.     if (fread(unknown_table, UNKNOWN_TABLE_SIZE, 1, inrbt_file) != 1)7 P' Z' q4 i. h/ y7 m! @
  366.     {
    + F. r& ~+ }, @) }. m
  367.         printf("problem reading unknown table\n");
    ( ?; h! u7 }, `. \: }$ s/ e1 R
  368.         return 0;
    1 ~3 m; g7 U& D# o# q
  369.     }
    " G- }8 g; ]6 V2 h6 l
  370.     if (fwrite(unknown_table, UNKNOWN_TABLE_SIZE, 1, outrbt_file) != 1)
    / S& Q" W' U9 R3 X6 A* ?
  371.     {5 G4 v5 i7 t( A, q# o; M
  372.         printf("problem writing unknown table\n");* @2 ^1 {9 T% Y" T& O
  373.         return 0;  w/ L/ ]$ b6 k1 d1 }
  374.     }) X" ^4 x3 g" b0 R; X: U' O8 D

  375. # h0 Y* E4 I% A  d: M7 A* z
  376.     /* copy over padding */
    ) l& P1 G4 n  R( G) j4 J+ ?/ I
  377.     padding_size = 0x800 - (ftell(inrbt_file) & 0x7FF);9 q0 _! a' `# D& y- a$ j' T
  378.     if (padding_size)# L; h3 u) B( |
  379.     {& N/ ^1 \5 R1 _/ Y1 o
  380.         padding = malloc(padding_size);
    1 Q2 I! u$ t8 P; N) l6 `7 v
  381.         if (fread(padding, padding_size, 1, inrbt_file) != 1)
    0 E1 F1 `1 O& N
  382.         {
    0 x- l) P# l& [8 Q/ p+ O
  383.             printf("problem reading padding\n");/ g& m/ W& v' h4 _
  384.             return 0;7 v  e! \& Y. o: y; V
  385.         }, d( _' Y) K6 |. O# V  I+ M! N
  386.         if (fwrite(padding, padding_size, 1, outrbt_file) != 1)
    " B" o% z. m& T' i0 N3 `" ]% T3 K; d; h
  387.         {% M1 L- g* ^4 R& m
  388.             printf("problem writing padding\n");9 c6 B$ j" V" r5 o7 Y3 c
  389.             return 0;) P% Z  R- X: ~: S0 ]
  390.         }
    * {& n  a9 d- v
  391.         free(padding);1 A9 W% k4 E4 q+ F: G( J/ `. _" z
  392.     }4 ?8 a, G4 V% h: }, Y' L

  393. # s; q# x5 S: H0 @5 ]* M
  394.     return 1;
    ; ]" s3 D7 v- F6 `! x& ^
  395. }' P" T6 W8 h, |& {
  396. ) L9 P5 |9 `. j% Z
  397. static int get_lzs_back_ref_length(get_bits_context *gb)
    & s$ d; y0 p4 Z& t* ~
  398. {
    ! V5 f/ R! P! w2 b
  399.     int vlc;
    * f4 C. a+ _, k
  400.     int count;, j( s" w5 M7 c' P
  401.     int value;/ ?- {4 @0 X5 k. M; ?; o

  402. + y$ C  c3 l; V1 M' ~
  403.     vlc = view_bits(gb, VLC_SIZE);
    ! }. d( I! e( }6 N) F5 Z/ e
  404.     count = lzs_vlc_table[vlc].count;4 Z% b; ^% h+ J0 [5 |
  405.     value = lzs_vlc_table[vlc].value;, }, C" `  }1 d+ J* Z5 u8 v

  406. 1 ^) N4 Y; X$ C3 Z1 v) }: _
  407.     read_bits(gb, count);
    " e5 H( I% V( X5 n' ~) O) j, E9 b. c& |
  408.     if (value == 8)) G/ X; f  a7 H! u
  409.     {9 p' e9 I2 L$ K5 a1 a( |" ~
  410.         do4 w' A6 }9 s4 C/ r- Q1 y) R8 }
  411.         {
    + a/ T- \% n4 T& m- D) u
  412.             vlc = read_bits(gb, VLC_SIZE);. ~3 v7 c; `, J6 s+ ~' Y# U& g
  413.             value += vlc;9 A$ K: v3 M2 C& n- Q+ d( @
  414.         }
    5 Q  v/ H8 G0 U3 e1 J, V
  415.         while (vlc == 0xF);
    0 h$ ]9 b$ I9 k
  416.     }$ r* V5 Z/ ]# W4 d1 K$ s
  417. 2 L7 v8 E, [" k8 w& X
  418.     return value;  z0 x. E' s; ^* J4 m
  419. }
    & a' I: F& x" n4 h# b
  420. ! z/ h" p  f1 c
  421. static void compress_window(put_bits_context *pb, uint8_t *full_window,# B8 R/ y- l% p; \, e+ `
  422.     int full_window_stride,2 m! J7 T$ u/ f3 J
  423.     int window_top, int window_bottom, int window_left, int window_right)
      U3 F8 v  A0 r+ H
  424. {8 F7 H8 F) [) h' e2 _- {1 F4 k4 S
  425.     int last_pixel;
    5 G$ C1 b+ ^! g6 f1 [
  426.     int run_size;
    : Y2 T9 V6 q) T, l
  427.     int x;* h; ~; _# k  e' Q4 s" {
  428.     int y;/ t* v( Y0 n/ w) r- @! G8 g
  429.     int start_index;
      v* _8 ~% ^; L
  430.     int end_index;
    # U5 `* r# x9 @/ ]& ~" Y
  431.     int encode_last_run;, Z5 ]& `, `2 k# w2 H

  432. 9 }8 i! Z" I% _8 o( i
  433.     last_pixel = full_window[0];1 b1 D! M' T8 Q2 c. \% r
  434.     run_size = 1;  Q8 O. g$ \! `4 B% A, b. ^$ C. l
  435.     for (y = window_top; y <= window_bottom; y++)4 O  m6 E* W# R: V: q7 d4 Y
  436.     {! v. z' d) F4 U5 u- |
  437.         start_index = y * full_window_stride + window_left;
    / {. H- g) d) o& t2 N& L" D
  438.         if (y == window_top)
    7 q" s. ^; G0 z- n- @
  439.             start_index += 1;
    . B' j, s2 F8 R
  440.         end_index = y * full_window_stride + window_right;
    , h* h  y+ D2 |- i$ f8 \
  441.         if (y == window_bottom)
    5 o3 m+ K+ S( I
  442.             encode_last_run = 1;% @* Q' S; @5 ~, p
  443.         else
      L$ [  m# @) u) T4 n8 j; ~
  444.             encode_last_run = 0;
      C6 y* b* [$ d
  445.         for (x = start_index; x < end_index; x++)& R/ X1 z9 w  y: p
  446.         {3 u+ L# D# c0 I5 j# v  z% w
  447.             if (!encode_last_run && full_window[x] == last_pixel)# Q3 a2 K. T3 r9 @1 ?
  448.                 run_size++;6 L  z0 Y7 X, T( E+ [2 H. R7 A
  449.             else
    # b% b0 p5 @! s7 R5 {
  450.             {
    % O" }1 U' \! J6 `) ~
  451.                 if (run_size == 1)
    # N2 v$ k3 M  E8 b- E9 M; q! D; K3 C
  452.                 {) j$ t# [, B) V5 z& n( H
  453.                     /* encode a 0 bit followed by raw pixel byte */
    & d' K7 {+ ~& E+ u- U. y! d& U1 t
  454.                     put_bits(pb, 0, 1);! {/ `% {  F7 w* W* }4 c
  455.                     put_bits(pb, last_pixel, 8);* F, a  [$ }  t. j7 k
  456.                 }
    + k$ e1 U6 N, c: C$ }
  457.                 else if (run_size == 2)$ H9 n: L" k7 V" o& i
  458.                 {$ v( D% \8 M( a/ A* {
  459.                     /* encode a 0 bit followed by raw pixel byte */
    ( z. D6 X5 m4 z) i7 r
  460.                     put_bits(pb, 0, 1);- d* {- K. f' g# q; _! V" E& Q
  461.                     put_bits(pb, last_pixel, 8);
    8 g% f! D  p& m' F6 H5 x9 F) u
  462.                     put_bits(pb, 0, 1);2 }, J1 L  v: ~% D% o3 G
  463.                     put_bits(pb, last_pixel, 8);
    / ?1 E% U8 m" P% h
  464.                 }: a. A! Z  m9 V( e3 t4 x; I
  465.                 else# ]# \4 K: S$ X9 x( i
  466.                 {
    . K3 k- i7 M: `6 ]) }6 m: b
  467.                     /* encode a 0 bit followed by raw pixel byte */+ B9 J1 m* r) s% ?5 S: E" n5 O9 K1 ]
  468.                     put_bits(pb, 0, 1);
    ) }! K1 p/ ^1 S
  469.                     put_bits(pb, last_pixel, 8);  w, r# V$ b0 J  T! A
  470.                     run_size--;
    - n) f- ?' H2 Q
  471.                     /* encode a run: a 1 bit, followed by a back reference; ]. X2 P! k! F; T. x2 m
  472.                      * offset (-1), followed by a length */
    0 o- A2 W2 n% r% a( n% ?
  473.                     put_bits(pb, 1, 1);2 Q+ B* b  M+ ~: Z( ~7 G! W
  474.                     put_bits(pb, 1, 1);  /* 1 = 7-bit offset */. D, |( b5 a, Z+ n' V- d! z/ q2 l
  475.                     put_bits(pb, 1, 7);
    1 {. [) x7 o5 S+ u/ ^: c
  476.                     if (run_size <= 4)
    5 i7 H' b& k! A: k4 B0 [. c7 O- Y
  477.                     {) j3 A6 C/ ~8 U
  478.                         /* lengths 2, 3, and 4 are 2 bits */' s1 V. @( A+ k; x2 b2 B
  479.                         put_bits(pb, run_size - 2, 2);
    ; L$ V# {2 |2 q) P, Z: A8 V7 Y! r5 ~
  480.                     }# y9 H7 a1 s. d9 Q2 a3 `
  481.                     else if (run_size <= 7)
    * q; {: |3 F: G; l; H  s
  482.                     {
    3 Y9 y' `8 U3 S7 [/ p& N6 Z( s
  483.                         /* lengths 5, 6, and 7 are 4 bits */7 B% l# l% C4 }* D4 x; L
  484.                         put_bits(pb, run_size + 7, 4);
    ! u' L4 e0 U1 ~  X  L! A9 O  e5 h
  485.                     }  |4 Z4 n! g0 G# ?. h4 {
  486.                     else
    3 n2 R$ W# p0 L8 w3 P
  487.                     {
    5 D9 d& P6 \$ g! ^" L" L1 C& k
  488.                         /* arbitrary length; start by encoding 0xF which7 Y  y% Z' Z6 b6 L- g
  489.                          * stands in for an initial version of 8 */! v3 }) t3 n- k* V6 g& o" T' u. b
  490.                         put_bits(pb, 0xF, 4);% e) s5 w6 n, |  {4 [
  491.                         run_size -= 8;# r$ I; c/ V" z8 f1 Z' H' u9 g

  492. $ D/ D5 c& Y1 U
  493.                         /* encode blocks of 4 bits until run_size is 0 */
    * |7 Y$ q) _- \: j% @
  494.                         while (run_size >= 0)
    % i9 Q+ l! q+ o% A" Q) T
  495.                         {
    & f$ \) m; Z  v, a; O
  496.                             if (run_size >= 15)( M9 |. S& j2 [, d* L
  497.                             {3 ?: U( z/ ]- e1 Y2 b4 ?
  498.                                 put_bits(pb, 0xF, 4);5 A; r) U$ t' ~0 A/ o3 X
  499.                                 run_size -= 0xF;: n: T5 u! H6 l8 R" q5 H3 r- V6 t1 V
  500.                             }4 }1 O8 H- d# a  w' d. Z1 d
  501.                             else+ [6 J9 c- D% x8 b. C1 P* T
  502.                             {1 O7 L$ w, k5 _7 O# g/ u
  503.                                 put_bits(pb, run_size, 4);- c2 ~% T6 V7 ^2 m' ?7 F
  504.                                 run_size = -1;' y4 a/ U- F. y/ s* s0 a1 x
  505.                             }2 N6 J, h0 m8 E; L+ d/ ?+ ^% [
  506.                         }5 T: h* v. ^7 \( h; K+ A, @$ q- K
  507.                     }6 e& D( b/ u. Q* a4 w
  508.                 }
    7 n- H* ~7 C  s) H- t# Q& h/ L) R% Q/ s8 ~( o

  509. ' t9 i6 K& `! b
  510.                 last_pixel = full_window[x];
    0 o! ?8 X8 m6 A4 M% \: o
  511.                 run_size = 1;% @  Q+ i8 F1 W2 R
  512. 5 G! A  Y4 R) B: M/ }" u& G* r+ ^
  513.                 /* this single x iteration was only here to close the final run */
    1 L7 @& W2 J% |! o% Z
  514.                 if (y == window_bottom)* R) Y3 q) Y# m1 w
  515.                     break;
    / N4 h5 w$ g5 x
  516.             }  y5 l# D% X8 C# J2 [$ y  i
  517.         }0 p6 ~* X1 ?; O' M
  518.     }$ ^' r* X- R1 E
  519. 8 T& t' r; A2 L( ^$ \7 s' @
  520.     /* close the bitstream by encoding a back reference with length 0 *// a- }* V! r: o. s9 C
  521.     put_bits(pb, 1, 1);  /* back reference run */$ z( y7 S3 r2 P1 ^) q; {
  522.     put_bits(pb, 1, 1);  /* 1 = 7-bit offset */
    ' z5 {% D( y" }; X# j; P
  523.     put_bits(pb, 0, 7);  /* length 0 */2 r. {7 M* }$ x) b( `

  524. 3 L0 B$ x5 W1 v) b8 U. o" i
  525.     put_bits_flush(pb);/ S* O) m4 r; w/ P
  526. }$ F; n! b! O; c& J) a" Q! N6 _8 x
  527. - i5 h" H% e5 S3 p3 U$ ?7 `4 B
  528. /* compute Euclidean distance between an RGB color and the desired target */$ r  D: C9 e, U! Z7 e1 X
  529. static int compute_rgb_distance(int r1, int r2, int g1, int g2, int b1, int b2)
    1 n7 S7 F& e" y( P3 U
  530. {
    7 _" c7 L3 a  v  g! H. C6 O
  531.     return sqrt((r1 - r2) * (r1 - r2) +2 K; }0 \& I$ ^, k, G8 E% J! c
  532.                 (g1 - g2) * (g1 - g2) +
    * ~# x1 G$ d3 @; q0 Z8 ?
  533.                 (b1 - b2) * (b1 - b2));
    . j3 \2 u' \( H4 a) y. B/ H
  534. }4 l: U9 O( j; A; w: s
  535. 7 V& u1 i& e% B+ q8 f  I  G0 `+ h
  536. static uint8_t find_nearest_color(rbt_dec_context *rbt, int r, int g, int b)
    ( E" U% e; O' n3 m; c  X; T; O
  537. {
    ( P- n! T% I; t% S2 C
  538.     int i;8 {& B7 i4 b$ Q5 v' b
  539.     int nearest_distance;
    # I* p' L* ?6 u1 K8 f# q5 o$ W( H* J7 u
  540.     int distance;% `7 i" c% B, Q
  541.     int rp;4 B' M+ x2 {' s$ T9 V4 n' S( G9 }
  542.     int gp;6 s# y; e% O( ]" o
  543.     int bp;
    0 V- l; g, V8 G6 _  Z$ f
  544.     uint8_t palette_index;3 o% L% [( n* I# R- c
  545. 2 S% u1 `* {" r: A1 Q8 G
  546.     nearest_distance = 999999999;
    $ ^/ |2 l# c+ A8 o& I
  547.     palette_index = 0;
    3 `2 {+ l9 m0 O7 n1 l% {, ^
  548.     for (i = 0; i < 256; i++)
    - v7 w. Q* i, U$ R' T* U9 Y
  549.     {
    ! R8 }4 O6 t; x. w, a0 H
  550.         rp = rbt->palette[i * 3 + 0];1 }2 B. _' b4 h. K
  551.         gp = rbt->palette[i * 3 + 1];
    + u+ A0 ?2 {( y1 g# t0 G, W( _* b8 B( h
  552.         bp = rbt->palette[i * 3 + 2];
    5 y' p: v; J9 j8 S# N) l
  553.         distance = compute_rgb_distance(r, rp, g, gp, b, bp);2 l$ l2 v( o$ q  F+ S/ }' |
  554.         if (distance < nearest_distance)9 Z4 P2 `" Q3 h7 ?
  555.         {* A/ s" K* E3 V; y2 N9 {0 r% w
  556.             nearest_distance = distance;
    . e0 f6 m# s2 {& S
  557.             palette_index = i;. A8 w9 r# x6 Z6 ~) Z1 M
  558.         }
    3 ~5 B$ {6 S  D. F4 `1 Y: T
  559.         /* can't get closer than 0; break early */
    6 I. }' O% w' h: o9 z* @
  560.         if (distance == 0)$ k8 v; H2 P; n, n. T5 v
  561.             break;8 |$ h2 v( }; \: N& Y! j: ^
  562.     }
    2 Z# B* q' Q5 h& h8 t2 I

  563. , `: j5 V! ]' }' ~% M* }
  564.     return palette_index;, ]' k) f0 Y8 ]1 C! ^' k
  565. }
    ( _: W* W9 [  D  f7 u* i( o
  566. - _3 f8 j& R9 m2 @6 s9 R5 Q, ?0 T
  567. static void subtitle_frame(rbt_dec_context *rbt, uint8_t *frame,7 Z# e% u, k9 C! n$ a
  568.     int width, int height, int timestamp)
    2 W, V, P# |9 D+ Y, `: \7 |$ z
  569. {
    5 b' b( J* g9 T
  570.     ASS_Image *subtitles;
    ' J& t! `: n. c* t( N+ y. |3 ~0 @4 L' g
  571.     int detect_change;
    - K+ ]8 q, d9 j2 P( W% E
  572.     uint8_t subtitle_pixel;7 H( M  a9 n; F: J' u' o
  573.     int x, y;
    1 y6 n/ l% m! c' j6 s
  574.     uint8_t *frame_ptr;7 f1 n" V9 }: Z7 v" h+ X' e
  575.     uint8_t *subtitle_ptr;1 J% x  z6 c0 R; X" Q4 W
  576. ; r2 k9 l* m" j+ R) Z7 K4 I
  577.     /* ask library for the subtitle for this timestamp */
    9 a& u( G2 d1 T& n7 ^. w
  578.     subtitles = ass_render_frame(rbt->ass_renderer, rbt->ass_track,
    : ^7 v+ P- X- c) ~
  579.         timestamp, &detect_change);+ r1 m6 a$ q& |+ C; \

  580. 0 z) ^- A3 v6 n8 t: t- ]+ N2 k
  581.     /* render the list of subtitles onto the decoded frame */
    5 }; l  a; s, e
  582.     while (subtitles)5 `( E# f# X- Z
  583.     {
    ! L1 _5 j; g4 d* J( d( x9 v
  584.         /* palette components are only 6 bits, so shift an extra 2
    : r9 ]9 j. e( `# j
  585.          * bits off each component */
    , i  }7 V. S! Z+ }
  586.         subtitle_pixel = find_nearest_color(rbt,
    $ m$ m' M2 \4 v  H
  587.             (subtitles->color >> 10) & 0xFF,
    7 R/ U: n4 q( P) t4 h
  588.             (subtitles->color >> 18) & 0xFF,) S& T/ _9 {3 x7 I# @/ f
  589.             (subtitles->color >> 26) & 0xFF);
    - `+ i5 g. x( k! I7 e* d
  590.         for (y = 0; y < subtitles->h; y++)# J, j  U3 E0 M% u0 O" B
  591.         {
    ) _$ \% }) F$ K" y/ V1 h
  592.             subtitle_ptr = &subtitles->bitmap[y * subtitles->stride];2 i4 S1 b0 q% r% P' D- }
  593.             frame_ptr = &frame[(subtitles->dst_y + y) * width + subtitles->dst_x];
    ( f# S% y* j% E' i0 T
  594.             for (x = 0; x < subtitles->w; x++, frame_ptr++, subtitle_ptr++)" U, [5 f; A% I% x
  595.             {
    & e; F! k) d/ s% B% S* N8 y
  596.                 if (*subtitle_ptr >= SUBTITLE_THRESHOLD)* i! z* y) n0 d
  597.                     *frame_ptr = subtitle_pixel;
    5 E# I/ Z9 M$ p
  598.             }# D2 j# n4 }% F
  599.         }2 s; W, o0 b( G( Z  }6 t1 d% J
  600.         subtitles = subtitles->next;
    5 I4 W0 R+ \' s3 H9 z9 R
  601.     }) C' v4 @5 m2 Y3 c
  602. }) u9 [! u  ^/ z. i! ?9 [
  603. ! Y5 E# f8 \- M+ y& a# z6 N  e, M. D
  604. static int copy_frames(rbt_dec_context *rbt, FILE *inrbt_file, FILE *outrbt_file,; v- r% T6 T7 b
  605.     int origin_x, int origin_y, int window_width, int window_height). W4 ~0 A3 O2 }0 z/ A( m" h
  606. {
    * h, N. E. k3 c0 z$ d! e
  607.     int i;
    7 L5 P/ c6 p( z4 f7 o# i
  608.     int j;% R7 N8 i% J8 i
  609.     int scale;; [3 b, \5 x9 i! A
  610.     int width;! L8 S3 T, x, y; U* a) z
  611.     int height;8 a2 z- G' J6 l( y5 F
  612.     int max_width;
    ' A5 y% p- ?+ x
  613.     int max_height;: Y$ M7 |6 ^* J5 ?, M! g2 U
  614.     int frame_x;
    " \! |! r; N9 `$ \
  615.     int frame_y;
    - i' F& s$ b" D2 m3 ~  B
  616.     int fragment_count;' t$ Y9 J5 H2 s/ n! |
  617.     int decoded_size;
    8 K& Q. m% D, z: Q6 N8 T
  618.     uint8_t *decoded_frame;. H4 i- e  ?; y. Z8 z9 h
  619.     int fragment;9 h; Z! M5 J# `" z& x: @
  620.     int fragment_compressed_size;0 `; K5 v  g* ]
  621.     int fragment_decompressed_size;2 j  e; F6 e( ]/ n! _8 H, ~0 R
  622.     int compression_type;' Z' q' F6 {& L. |3 J2 b
  623.     int index;8 u: g& t2 ~9 C$ i% d) b
  624.     int out_index;% R' f7 l1 v: A9 M
  625.     get_bits_context gb;
    ( ?  P5 @1 ~1 u# G
  626.     int frame_size;0 C6 g5 F  e2 T! c$ C/ D) N* L; d
  627.     int video_frame_size;
    - l, n# b8 q4 ~; z' w
  628.     int audio_frame_size;  V1 V. C- O+ z. ^3 {9 k8 i& N" U

  629. . X4 t" t1 e3 P  ?6 v% ]; b. ]; B0 {
  630.     int back_ref_offset_type;5 `* t$ P- g6 Z! I1 w6 h# k9 u
  631.     int back_ref_offset;
    : S; c6 s' f" X! t; l3 X7 ]7 F
  632.     int back_ref_length;
    ) `% U. c+ c+ D
  633.     int back_ref_start;
    6 {+ \5 B- p0 _, [* M5 l7 {
  634.     int back_ref_end;
    ! \# E! o9 p  T& [4 `
  635. + h$ n. @4 B& g
  636.     uint8_t *full_window;; d6 {% e% c$ N! s2 a& y; F" ^  u8 `: A
  637.     int full_window_size;; J) e, X0 V  v/ Q- [4 p
  638.     int y;
    5 y( ?0 c) k( z% w$ l
  639.     int window_top;8 k. \, v9 v5 H- J+ \1 q! v
  640.     int window_bottom;" S& B- P1 f3 v
  641.     int window_left;
    & ^" a: I. h; E2 c4 H8 ^
  642.     int window_right;
    7 O- L7 ?8 |+ c
  643.     int window_size;+ M+ L9 i$ r  J, W7 `
  644. 8 I: ]7 {1 S+ C
  645.     char filename[30];
    6 S, Q) [4 e6 Z5 _( q7 J& F

  646. # \2 A2 _8 M' J
  647.     put_bits_context *pb;
    5 b3 f& E' [0 |' T! W
  648. 4 a( U" D" x6 A7 M+ E- p
  649.     full_window_size = window_width * window_height;4 |0 `1 Z! {: x8 u3 W. @
  650.     full_window = malloc(full_window_size);6 N8 B& e9 |/ k7 f" U7 v1 ?$ y: S
  651.     pb = init_put_bits();
    1 w; {* S) k' ~. l5 I: D' ]6 I! Q

  652. % U! J: Q' {1 h! B
  653.     max_width = 0;
    - {+ z- y7 [' v; _" ]/ O, a
  654.     max_height = 0;- F/ ?8 G( C3 N* o  t1 n. K- ]
  655. 1 b7 W1 |" V, M6 s; E" d
  656.     for (i = 0; i < rbt->frame_count; i++)
    # [* h" U3 o2 ^& q! H
  657.     {: l; D) X0 ~) I7 G$ u4 R
  658.         /* read the entire frame (includes audio and video) */0 U1 q( X" C" k- }2 T$ B' C# f
  659.         frame_size = LE_16(&rbt->frame_size_table[i*2]);, w) U' A' l5 k& G/ y; U( J- ^( r
  660.         video_frame_size = LE_16(&rbt->video_frame_size_table[i*2]);. O# f/ X% \/ m& F
  661.         audio_frame_size = frame_size - video_frame_size;- H, R* c/ L6 `. }0 Y8 _0 x8 o
  662.         if (fread(rbt->frame_load_buffer, frame_size, 1, inrbt_file) != 1)4 C* F, U7 g! c' t+ _9 i1 F
  663.         {8 H, ^7 w. l) M, B) u  P
  664.             printf("problem reading frame %d\n", i);
    5 |/ k  n5 J8 s4 e$ r! x
  665.             return 0;
    ' c* y! Y' T+ S
  666.         }
      R$ Z5 d$ ~$ ?

  667. 1 x3 Y2 U( G+ ]) d* ^0 s+ Q
  668.         scale = rbt->frame_load_buffer[3];
    ' h5 [- h2 J8 k3 I8 X; W2 p
  669.         width = LE_16(&rbt->frame_load_buffer[4]);, S; ~/ y6 _+ |2 @
  670.         if (max_width < width)
    7 e- R1 h/ Q0 ~/ s
  671.             max_width = width;) f$ g3 s* P6 g* e& |" r/ _  w+ k! X
  672.         if (max_height < height)1 Q5 A1 D$ o3 A& f- `% x+ ~* p- t/ C
  673.             max_height = height;: U, I, |$ `5 S0 K& h7 E3 N
  674.         height = LE_16(&rbt->frame_load_buffer[6]);! R; T. m! G& ~8 P+ H
  675.         frame_x = LE_16(&rbt->frame_load_buffer[12]);
    / C: T7 ~! U3 m- G
  676.         frame_y = LE_16(&rbt->frame_load_buffer[14]);
    ) o; j' a8 Q! ~
  677.         fragment_count = LE_16(&rbt->frame_load_buffer[18]);8 i% B4 k$ u% ]1 A8 \2 w1 K3 l
  678.         decoded_size = width * height;
    , k$ e8 }6 \' X+ k1 L

  679. 6 Q: [5 R5 S7 ]/ W) Z. A
  680.         printf("processing frame %d: %d%%, %dx%d, origin @ (%d, %d), %d fragments\n", i, scale, width, height, frame_x, frame_y, fragment_count);& O  V( M) k$ J( Q* B: C4 r$ I

  681. & l2 Q2 w/ J9 f; P. a" q. m
  682.         /* decode the frame */
    ! e+ ?) j+ c( D3 U% b6 G4 N. b
  683.         decoded_frame = malloc(decoded_size);6 m  |7 {6 U3 G( V8 J* f
  684.         index = 24;% i; ]' Z- i1 E
  685.         out_index = 0;0 f) \4 v7 l! _8 v6 R$ E5 C& R
  686.         for (fragment = 0; fragment < fragment_count; fragment++)
    7 ^$ t0 ^4 w& {! Q/ D+ q
  687.         {
    5 @2 G) I( T5 R% N9 x
  688.             fragment_compressed_size = LE_32(&rbt->frame_load_buffer[index]);
    # Z- B3 B: L$ N3 m4 ]. C& c; g) t
  689.             index += 4;
    9 g# X; F# Z- N, X9 }+ @
  690.             fragment_decompressed_size = LE_32(&rbt->frame_load_buffer[index]);
    . Y& @4 y* u0 T5 x/ U
  691.             index += 4;
    " l8 d' _8 d0 r, R) [& J$ a
  692.             compression_type = LE_16(&rbt->frame_load_buffer[index]);
    5 G0 o/ u3 G: ^3 S
  693.             index += 2;! D0 P2 O& F. z' W# U9 z- j3 X

  694. 9 O5 F% A! @* b* [! J
  695.             if (compression_type == 0)% k& f# c, y/ i2 F# O& A4 \. J7 N2 W
  696.             {7 O* {, B" Q. N" e5 E1 D: B: \7 D
  697.                 init_get_bits(&gb, &rbt->frame_load_buffer[index],  \+ t' U2 r9 |; A1 }
  698.                     fragment_compressed_size);5 S; V4 P* l5 e& Z/ D4 F
  699. 7 K0 z& N* p5 f' G3 a# R
  700.                 while (out_index < fragment_decompressed_size)
    ( V, ^% P/ U$ @
  701.                 {
    8 }& C: Q1 n$ Y3 U/ F4 i
  702.                     if (read_bits(&gb, 1))# _* A# p/ h; _* }7 M
  703.                     {  B  \8 O) Y6 d" J- H( @; n
  704.                         /* decode back reference offset type */
    ' O  a5 @( U9 ~3 N
  705.                         back_ref_offset_type = read_bits(&gb, 1);2 v4 a4 u# k# F' _6 K
  706. 9 d0 W9 H. ^, ^- }2 K' {7 m2 }: H
  707.                         /* back reference offset is 7 or 11 bits */8 F& w$ j- H2 s" D# W. E+ d
  708.                         back_ref_offset = read_bits(&gb,
    , y8 S9 ~- Y% t& H
  709.                             (back_ref_offset_type) ? 7 : 11);/ p- m5 t- ?6 u- [* w2 I' q/ U4 x
  710. 8 u% a6 j( n5 ~6 g
  711.                         /* get the length of the back reference */$ d3 o# K! ~, Z3 }  F5 F
  712.                         back_ref_length = get_lzs_back_ref_length(&gb);
    , o2 f! ~+ d7 U: D0 _
  713.                         back_ref_start = out_index - back_ref_offset;
    . R0 C) b8 T. u& F' w( a& p8 ]
  714.                         back_ref_end = back_ref_start + back_ref_length;" b: l6 Q- U  _* {) z. d1 d2 H
  715. & l8 E. ~5 p" ?* Y. T4 }+ u
  716.                         /* copy the back reference, byte by byte */: ]4 J. t: b+ ]
  717.                         for (j = back_ref_start; j < back_ref_end; j++)3 S: b0 _" T+ U1 D# R) M
  718.                             decoded_frame[out_index++] = decoded_frame[j];
    9 h1 I' d  m9 C
  719.                     }
    4 R* n* t& y7 g# ~) t
  720.                     else
    ! V6 U7 S2 z+ q3 ^) J
  721.                     {9 e" A0 E/ t. J+ M! e7 b1 _
  722.                         /* read raw pixel byte */" Z, B! V# p9 m3 _
  723.                         decoded_frame[out_index++] = read_bits(&gb, 8) & 0xFF;: \- S; s* }% ~8 e2 w
  724.                     }6 Y' u1 F  V4 W7 L( _: V4 h
  725.                 }
    : i9 [' Z4 X. L' W7 l

  726. 0 ]: ]1 e* ?5 p3 Y, B; A2 B$ J
  727.                 delete_get_bits(&gb);
    9 u; ~' \4 C% _2 V
  728.             }
    , p  a4 N8 J1 d& ^  P

  729.   X/ j8 w. J( T2 w6 U$ X" ~
  730.             /* next fragment */+ {$ C- K6 s6 J8 W$ n/ U
  731.             index += fragment_compressed_size;0 V- d* D1 b" H1 r4 [  V3 p
  732.         }* y0 \5 D% n! L. i; ~( _" f, b! i
  733. " T( P; B( ?# @! ?: [
  734.         if (rbt->dump_frames)
    ) l* x! k  m9 }0 M
  735.         {
    3 p* P  q3 h  ?. w% S  \+ d4 ?% t- N- c
  736.             /* dump the original frame */' q0 D- M% r" y' M4 A
  737.             sprintf(filename, "original-frame-%03d.pnm", i);" ~. D6 @0 G: B" C5 a  b: Q
  738.             dump_pnm_file(filename, rbt, decoded_frame, width, height);: g+ d' e0 w# k
  739.         }; \/ O9 D8 D  A! ?: H( K
  740. 7 ~* L8 x3 a1 x9 b' P' t
  741.         /* transfer the image onto the frame window */+ r: ?4 A) u: F; f6 \# v
  742.         memset(full_window, 0xFF, full_window_size);/ H5 s9 s- F3 ~" ?( X% `" X. X
  743.         index = 0;. M/ S5 \9 B0 W/ X
  744.         for (y = 0; y < height; y++)
    ) f" I% e6 x7 D1 N% Y4 P
  745.         {0 K4 d" [% B$ z
  746.             out_index = window_width * (frame_y + y) + frame_x;
    - F6 T* O  E1 n& B
  747.             memcpy(&full_window[out_index], &decoded_frame[index], width);
    " h. l/ F3 A0 n' _, r+ Y# A
  748.             index += width;! a8 F" l5 B8 |- D% H' M! b  L
  749.         }' o+ C, A6 U. o1 R

  750. 0 l* V2 o* H0 ?' I- a! X
  751.         /* write the subtitle */
    / P& J# v9 a2 ^. l
  752.         subtitle_frame(rbt, full_window, window_width, window_height,% s1 G  f8 a$ N( R& B+ t
  753.             i * MILLISECONDS_PER_FRAME);6 J- B$ B0 G! H$ K! e1 R
  754. % k, C; C+ H0 p( ^/ a# o# F
  755.         /* figure out the smallest change window */
    ) B! @- U! W3 ^  N2 h$ N
  756.         window_top = frame_y;: F; R+ Z, d5 g0 L
  757.         window_bottom = window_height;
    5 t5 j+ L* N+ V" X# ?, l
  758.         window_left = 0;5 A' I$ l: e: O: N+ ]( i
  759.         window_right = window_width;
    ! G. n2 O" G( E& _
  760.         window_size = (window_right - window_left) * (window_bottom - window_top);+ |) Y1 w+ _/ B* Y5 x

  761. 7 v) }9 ~7 X9 J1 H
  762.         /* compress the frame */
    ( z9 _- z1 @2 ?1 r. ~
  763.         reset_put_bits(pb);
    ; Y5 s' h1 N) L! M$ |
  764.         compress_window(pb, full_window, window_width, window_top,$ t  Y. Z" m( n0 G
  765.             window_bottom, window_left, window_right);$ o6 B9 b. i- e& f
  766.   Q: G& y; n) b/ j% o' G
  767.         if (rbt->dump_frames)9 |( u  q5 R3 l
  768.         {" ^+ t% f% K! i6 u( u
  769.             /* dump the frame plotted onto the full window prior to encoding,
    + y- C6 i7 n: k
  770.              * with subtitle */5 \3 i" Z" x; n& \
  771.             sprintf(filename, "pre-encoding-frame-%03d.pnm", i);
    ) m& C6 G7 g: A% I6 K7 R' M
  772.             dump_pnm_file(filename, rbt, full_window, window_width, window_height);2 S1 s6 N7 {8 \& }
  773.         }
    5 N" d* b9 Q5 R3 ~" c
  774. / S$ o0 X/ _1 [, _; X5 ]8 H& \3 U
  775.         free(decoded_frame);. g0 M, @4 w# |7 X
  776. , R4 v) Z( c1 Q, U) q. l
  777.         /* update the frame header */
    2 u7 R9 r* ~) s# [: f
  778.         /* width */9 D" P: P  n" A' }6 x2 R
  779.         rbt->frame_load_buffer[4] = (window_right - window_left) & 0xFF;# w1 e1 L% R. A( A) @# B
  780.         rbt->frame_load_buffer[5] = (window_right - window_left) >> 8;: q! o! S$ {/ J7 o8 c9 H# d
  781.         /* height */- z4 d( }* ?# ]
  782.         rbt->frame_load_buffer[6] = (window_bottom - window_top) & 0xFF;
    + D" s. y4 z, G! _) ]
  783.         rbt->frame_load_buffer[7] = (window_bottom - window_top) >> 8;7 J, X1 g! w8 p( u7 l
  784.         /* origin X */8 B& e, `: u3 ~7 d
  785.         rbt->frame_load_buffer[12] = window_left & 0xFF;. o0 f5 d  f& k) }0 _3 |3 Z
  786.         rbt->frame_load_buffer[13] = window_left >> 8;
    2 Y4 e8 z6 ?0 w
  787.         /* origin Y */! E: t4 C6 c. [5 ]
  788.         rbt->frame_load_buffer[14] = window_top & 0xFF;8 C/ ?! ?8 V4 {* N4 h
  789.         rbt->frame_load_buffer[15] = window_top >> 8;3 j4 A; i$ v5 g9 H; J7 Y
  790.         /* fragment payload size */
    1 ^7 N6 j2 [+ D- m- h
  791.         rbt->frame_load_buffer[16] = (pb->byte_index + 10) & 0xFF;- P* }( o( f1 G8 w8 I4 ?5 E
  792.         rbt->frame_load_buffer[17] = (pb->byte_index + 10) >> 8;
    # _9 N9 B9 Q& h# K( P
  793.         /* fragment count (1) */7 A) |/ i* ?( {- n8 ~" P
  794.         rbt->frame_load_buffer[18] = 1;
    / ?( B& E  [8 L" G* C
  795.         rbt->frame_load_buffer[19] = 0;
    0 l6 F3 |1 U" y, N
  796. ( r1 i( B. R# B( m+ |
  797.         /* update the fragment header */+ O! M; }7 G: L/ I- y. P5 H3 ~
  798.         /* compressed size */" b' V% U! y4 Y- z
  799.         rbt->frame_load_buffer[24 + 0] = (pb->byte_index >>  0) & 0xFF;
    ' m% J. z5 A4 F$ j' X' O  ]
  800.         rbt->frame_load_buffer[24 + 1] = (pb->byte_index >>  8) & 0xFF;
    + ^, E- H9 W% i3 T
  801.         rbt->frame_load_buffer[24 + 2] = (pb->byte_index >> 16) & 0xFF;
    % t  d) S" y2 }+ R8 p8 d
  802.         rbt->frame_load_buffer[24 + 3] = (pb->byte_index >> 24) & 0xFF;
    & v; s$ z5 s* O( m8 ?
  803.         /* decompressed size */
    ) C- B; j0 i* P, S) m
  804.         rbt->frame_load_buffer[24 + 4] = (window_size >>  0) & 0xFF;
    - R, X7 d5 ^  _# O9 m2 U/ @1 C; ?
  805.         rbt->frame_load_buffer[24 + 5] = (window_size >>  8) & 0xFF;. r9 l! y( Z: n1 l. ?! h, X
  806.         rbt->frame_load_buffer[24 + 6] = (window_size >> 16) & 0xFF;
    ( y2 K% H  e2 h0 w0 {
  807.         rbt->frame_load_buffer[24 + 7] = (window_size >> 24) & 0xFF;& x& i# d- F0 d" c% ~
  808.         /* compression format 0 */1 |4 e+ Y4 Z% B4 d" T
  809.         rbt->frame_load_buffer[24 + 8] = 0;: E$ Z# b8 X( W5 T, q5 p5 P4 C* O3 F
  810.         rbt->frame_load_buffer[24 + 9] = 0;& ?- c* E- s1 {) K# `6 M

  811. 5 M! ]0 P) g- L# B/ r4 s. M
  812.         /* write the 24-byte frame header and the 10-byte fragment header */
    & e0 C& G* F  P! v! G( I
  813.         if (fwrite(rbt->frame_load_buffer, 24 + 10, 1, outrbt_file) != 1)4 b0 H" F) \+ N" X+ J7 d; Q
  814.         {
    - W% E3 h8 l! u: [
  815.             printf("problem writing frame %d\n", i);) ^5 r7 g5 U2 W' o, N6 L! f, l. C
  816.             return 0;" i* B$ U) r& f) l
  817.         }! }$ g3 A( f7 ~7 s% p7 d
  818. ( _* U% Y# c" z$ u
  819.         /* write the new compressed frame data */& g& T+ P2 `5 d: a) C8 D
  820.         if (fwrite(pb->bytes, pb->byte_index, 1, outrbt_file) != 1)
    . ?2 }0 \6 P( `
  821.         {. r: \) c! ~; w1 d7 g6 ^4 {7 ?3 @+ c
  822.             printf("problem writing frame %d\n", i);9 o4 ~2 |1 D$ A0 o
  823.             return 0;
    # w4 Y& L1 d4 m3 t5 S3 [& |
  824.         }
    2 I6 t# w$ s; S  D2 @. x

  825. / x; P# e" O6 b) p% Y* a6 P9 C
  826.         /* write the audio data */" r1 d4 Y: g* A5 K! T9 a: I
  827.         if (fwrite(&rbt->frame_load_buffer[video_frame_size], frame_size - video_frame_size, 1, outrbt_file) != 1)
    6 @: Z2 B' j  _  W/ {$ _
  828.         {, C5 U$ V6 J/ w" b
  829.             printf("problem writing frame %d\n", i);
    - I6 K# K- I: v) S2 F
  830.             return 0;) z; e# Z9 r) v  p
  831.         }/ m5 x6 b) h  Z
  832. ) ]) b! T; Q1 O  Q1 I) E. W, l
  833.         /* update the table entries */( H# T$ `( S- \. |. b  D& w  _) n/ M
  834.         video_frame_size = pb->byte_index + 24 + 10;
    ) E  P+ a  t, e/ C' ?
  835.         frame_size = video_frame_size + audio_frame_size;
    9 k" Z6 C0 I2 ^) L3 H5 q
  836.         rbt->frame_size_table[i*2+0] = frame_size & 0xFF;; S1 o7 n" ~* ^" J
  837.         rbt->frame_size_table[i*2+1] = frame_size >> 8;
    4 H# F' y- W2 y; O& C5 v4 H6 P" O4 C
  838.         rbt->video_frame_size_table[i*2+0] = video_frame_size & 0xFF;6 i- b; @4 X  Y# B
  839.         rbt->video_frame_size_table[i*2+1] = video_frame_size >> 8;4 _/ V9 G( w% P0 |
  840.     }
    6 g7 k4 \0 U; w; o1 _* g# R
  841. , ?0 P) O6 s6 I' h
  842.     printf("maximum dimensions seen are %dx%d\n", max_width, max_height);
    * h- W3 q: F- C+ H4 X8 m

  843. % Q6 n% I+ A& G$ z
  844.     delete_put_bits(pb);5 |6 |0 U7 S8 c* Z
  845.     free(full_window);: l7 B7 T( B& [  H
  846. - Q8 Y4 H- B) T' j
  847.     return 1;
    5 y4 {5 U7 N0 S1 d- S: I1 ^
  848. }
    7 \* J5 k% O. f. T  n7 i. S" C1 a5 s. {
  849. # v' N1 K/ d+ X, S+ l7 d% U$ x
  850. int main(int argc, char *argv[])
    0 f, e& E* [* p4 ]$ B
  851. {3 j$ E+ b, H7 @( P
  852.     char *subtitle_filename;, R0 S3 {* A7 g7 U+ [7 @0 D
  853.     FILE *subtitle_file;
    1 s) s" G0 H( j9 R* Y6 L  l
  854.     char *inrbt_filename;% z! R$ f0 W# X$ l  L
  855.     FILE *inrbt_file;& ]' X5 v  ?9 W; Q. W
  856.     char *outrbt_filename;
    4 R) o% P* n4 C2 H/ t! j1 D
  857.     FILE *outrbt_file;
      ~. m$ R* B: t. S* L
  858.     rbt_dec_context rbt;
    ( Y/ C) _" W) A+ ~. G  P
  859.     int origin_x;
    : H' @- ^% n7 u, R
  860.     int origin_y;
    ! ^+ @8 d" f, c; |( D2 q% b% W: T
  861.     int window_width;: h( q" x" @/ l+ c
  862.     int window_height;$ b! k+ Q" K( I* e/ q

  863. % |& c% S6 l3 c
  864.     /* testing the bit functions */# u2 X: A, n. H( p% c
  865. #if 0
    % y) v$ X: i: j9 j
  866.     int i;: E) N; ?: r- E! r
  867.     uint8_t bytestream[] = { 0x55, 0xAA, 0x00, 0xAA, 0x55, 0x77, 0xFF, 0x1B, 0x70, 0x8F };2 ~$ d. R/ h2 V# L- p+ G
  868.     int bytestream_size = 10;' G: }8 |* u/ V
  869.     get_bits_context gb;3 D! Z& o. v% \0 f3 P$ i6 p9 z
  870.     put_bits_context *pb;% F& T: u- ^; }2 \
  871.     int bits;$ Q$ W$ y! e) U% B( ~( R" A, \) h

  872. % I: y# B: F& p9 m7 |
  873.     init_get_bits(&gb, bytestream, bytestream_size);. O% ?( K1 ~+ o0 r4 e+ L  ]
  874.     pb = init_put_bits();
    " o' `$ W, ^& y. l/ j

  875. ( j3 T( D& E# O/ E: d
  876.     for (i = 1; i <= 12; i++)
    4 g# z# c3 l. [
  877.     {$ }3 {1 A: A- ~, l- M1 U1 _
  878.         bits = view_bits(&gb, i);
    ; m. w" D* T$ q; @
  879.         printf("view %d bits: %d\n", i, bits);8 ?. E/ p6 _& [' c. a: m' I
  880.         printf("read %d bits: %d\n", i, read_bits(&gb, i));
    3 N7 h' d/ Z: S0 Z3 V
  881.         put_bits(pb, bits, i);
    % A% R7 Q  z! w% r: B# ~
  882.     }6 S. r  y% j: R/ W+ K
  883.     put_bits_flush(pb);
    2 ]9 W/ V9 {* @- N
  884. 4 Y6 G, Y0 t6 Q' Z" ?* w1 t
  885.     printf("original bytestream:\n");4 Z8 z+ T- Y$ a/ v. a0 g% Q7 Y
  886.     for (i = 0; i < bytestream_size; i++)8 _! B- x7 _4 n; D5 m3 b' |
  887.         printf(" %02X", bytestream[i]);2 P( h9 z" c8 M' H0 D1 M
  888.     printf("\nnewbytestream:\n");
    ! s$ o+ S& `8 Y+ v
  889.     for (i = 0; i < pb->byte_index; i++)
    8 z9 t8 S- X3 v
  890.         printf(" %02X", pb->bytes[i]);4 v* [% i/ G$ G+ e5 b) C$ b4 p
  891.     printf("\n");6 P; Y% M$ R- k7 u" i0 A. W. v

  892. * o" S6 B& }6 k6 n
  893.     delete_get_bits(&gb);
    1 `0 I- _5 t9 _( r
  894.     free(pb);. |+ y% D8 ^  u4 i& N) d# U6 V
  895. #endif
    $ c" j# z8 C0 T
  896. ; r% ]' }1 S. o( _8 Z5 ^9 ^
  897.     /* validate the number of arguments */5 B4 H- P; N6 B) `
  898.     if (argc != 8 && argc != 9)! `2 Q/ ?0 Y( e. v
  899.     {
    - U* W: V$ j6 a5 R* `
  900.         printf("USAGE: subtitle-rbt <subtitles.ass> <in.rbt> <out.rbt> <origin X> <origin Y> <width> <height> [dump_frames]\n");
    * r1 A9 x; Y9 p, q8 ?9 {
  901.         return 1;( ]8 u( z1 j. m; U" w/ ^
  902.     }6 u( B7 R* u" E4 {
  903.     subtitle_filename = argv[1];9 _; w, K/ x7 Q" E
  904.     inrbt_filename = argv[2];
    8 q0 ^6 {& n" I0 A3 _
  905.     outrbt_filename = argv[3];
      ]9 \6 |" u9 c
  906.     origin_x = atoi(argv[4]);- o0 O! g+ {* n3 d
  907.     origin_y = atoi(argv[5]);
    * W4 R5 |3 n; m* y% X# A' K
  908.     window_width = atoi(argv[6]);9 \: D+ |# K  k
  909.     window_height = atoi(argv[7]);
    ( f; g" K3 W1 n3 }) c3 Q& I# B
  910.     rbt.dump_frames = 0;8 N5 g* O7 d& T3 W) i9 s
  911.     if (argc == 9)
    , |- V! p) v( W5 m" U! I
  912.         rbt.dump_frames = 1;
    ( ~% K: l9 ], Y9 c' i
  913. 5 k' s/ b1 \2 }. R0 m$ w5 x3 m
  914.     /* verify that the specified input files are valid */* x" O" w5 [. P/ `4 T
  915.     subtitle_file = fopen(subtitle_filename, "r");
    , y: l$ ~1 [+ j
  916.     if (!subtitle_file)* Z' A' H/ i1 u' _2 |) {' `
  917.     {
    ' u1 Y( A5 J  ]$ W6 ?; t3 ^* \- a4 K
  918.         perror(subtitle_filename);- ^8 N  D1 @4 O. X* p' x# R' J
  919.         return 1;
    $ o" ^8 }: k0 X. O
  920.     }* K+ [2 d7 s9 B' K7 q3 @
  921.     fclose(subtitle_file);
    9 r- e, ?7 I( V: u, e/ r
  922.     inrbt_file = fopen(inrbt_filename, "rb");, _3 m; b% f6 t% V8 \  u
  923.     if (!inrbt_file)
    $ F# r+ q" H+ e! e; O+ V* K4 a/ M# E
  924.     {
    4 v; I4 k4 J1 H/ P6 t
  925.         perror(inrbt_filename);
    ! F3 V8 Q6 E" h; a* t
  926.         return 1;
    " K. M9 x$ r* i0 W
  927.     }
    7 y( x. e" n  r
  928. / E5 e5 l) X' A5 U7 @0 \! V
  929.     /* initialize the subtitle support */
    9 z" _% ]) \* }7 k; ?4 ~
  930.     rbt.ass_lib = ass_library_init();' O' g% {$ a- P$ k* N. C0 Z: z
  931.     rbt.ass_renderer = ass_renderer_init(rbt.ass_lib);
    ) }+ \, {8 b, Z, }+ ^. Y
  932.     rbt.ass_track = ass_read_file(rbt.ass_lib, subtitle_filename, "UTF-8");1 Y3 w( P+ y2 n* A4 C. ]3 o
  933.     ass_set_frame_size(rbt.ass_renderer, window_width, window_height);4 g- m% b: {' `8 w; F  M; q  S( S
  934.     ass_set_fonts(rbt.ass_renderer, NULL, NULL, 1, NULL, 1);$ I4 q. x/ H; k+ i9 a5 A1 }

  935. % q5 C8 _+ `' s- C( \
  936.     /* open the output file */# v8 r0 l# X% ~( E" o( f. S
  937.     outrbt_file = fopen(outrbt_filename, "wb");
    ! q/ Z+ S1 I+ T# b! Z
  938.     if (!outrbt_file)1 t& Q6 X4 z1 u" G; m4 [; z" E8 i
  939.     {' y! c- Z% o! f/ r3 N1 T/ p5 i4 c
  940.         perror(outrbt_filename);$ W/ u( a' f0 t" `' j# n3 y
  941.         return 1;. Q/ E1 p# h& `# L. W# v
  942.     }
    5 d! C* U! T0 r  s# P0 {

  943. # t) k7 C$ S: D6 Z8 P, t; [
  944.     /* transfer header from input to output */
      m# ~4 `5 O0 o5 l( l( `4 e+ k
  945.     if (!load_and_copy_rbt_header(&rbt, inrbt_file, outrbt_file))* e- G5 ^, b. d
  946.         return 1;
    3 O' @, |/ O) }" C5 f

  947. $ A& ]7 \1 S4 Y8 }9 K/ J" Z( |
  948.     /* rewrite the frames */( \; ~; b& j; O4 R2 c
  949.     if (!copy_frames(&rbt, inrbt_file, outrbt_file, origin_x, origin_y,
    ( p. p9 g( S( D# U) W
  950.         window_width, window_height))$ G9 ^$ Q8 |& U- ?: i0 e% \2 Z
  951.         return 1;7 A' G0 _% ?- B1 Z4 m: n$ S( `/ R* S
  952. - b' x1 v8 `% `* f; S) l. y: N# e
  953.     /* write the modified frame size tables back to the file */
    ' _; e3 O- n! k! }1 t; v# m7 a" [
  954.     fseek(outrbt_file, rbt.video_frame_size_table_offset, SEEK_SET);
    9 Z' ~6 k( k$ k9 _
  955.     fwrite(rbt.video_frame_size_table, rbt.frame_count * sizeof(uint16_t), 1, outrbt_file);; ^: Z( W7 l5 {
  956.     fseek(outrbt_file, rbt.frame_size_table_offset, SEEK_SET);
    5 o: g/ A! {; E* v
  957.     fwrite(rbt.frame_size_table, rbt.frame_count * sizeof(uint16_t), 1, outrbt_file);. m8 m8 A' j  m+ m9 D/ \+ t$ R3 d% g
  958. 8 X+ L0 l1 h; u' v
  959.     /* finished with files */" ]' P# w) H; K& O2 H
  960.     fclose(inrbt_file);
    ! N( |4 f7 ~& h7 r* `
  961.     fclose(outrbt_file);
    / M( x, i  m6 D. P1 J
  962. : E/ l# T( H3 h0 H, k, E4 n+ d
  963.     /* clean up subtitle library */
    " B' ]: A, w6 |/ Y& M( Z; p& M. ~
  964.     ass_free_track(rbt.ass_track);
    ) G9 V" J3 T9 Q' p1 \
  965.     ass_renderer_done(rbt.ass_renderer);4 g5 `, X5 v0 A+ A( I# x
  966.     ass_library_done(rbt.ass_lib);" [1 R5 Q$ e8 e" D+ n6 w
  967. 8 V& ~9 {" Y; D: h% p$ Z: e
  968.     /* clean up */
    - L  l3 d# D6 C1 U! e2 B# j" X3 I9 l
  969.     free(rbt.frame_load_buffer);
    % P0 y8 D1 D* E, J/ ?# M* \
  970.     free(rbt.video_frame_size_table);1 f3 Z1 V$ f' f: r! e! ]7 G0 s' P8 r
  971.     free(rbt.frame_size_table);
    % N+ q3 Z2 J4 }" i, Z
  972. 0 k1 o- S6 f5 M  }. Z2 B
  973.     return 0;
    ! r" l' }3 }* T
  974. }
复制代码
5 a, W& ?4 s% {' |

4 h2 V( N# {0 }
( z$ S+ \: z3 u* \. M' z: u
4 J1 }' n$ [0 Z, t+ S; q# t
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 很美好很美好 很差劲很差劲
回复

使用道具 举报

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

使用道具 举报

板凳
 楼主| 发表于 2009-11-19 11:38 | 只看该作者
引用第1楼soring123于2009-11-19 11:09发表的  :
: R5 E# F& ~8 A9 a2 H这游戏有字幕吗?

% Y  q4 x* ^# Q0 i好像没有字幕,我说的是给视频外挂字幕方式的汉化。' y) P5 K5 y/ N
就像syberia2汉化版下面那行字一样。
回复 支持 反对

使用道具 举报

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

使用道具 举报

5#
 楼主| 发表于 2009-11-19 17:39 | 只看该作者
引用第3楼soring123于2009-11-19 17:07发表的  :
( ]. Q  _, q& c) P! Y我记得是没字幕的 比较麻烦 都是视频的
* a; X" Q2 i- }( D# o1 k
给视频外挂字幕方式汉化也许能行。: J' m8 h& I0 K- v7 C0 ?; 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日,是全球华人共同的冒险解谜类游戏家园。我们致力于提供各类冒险游戏资讯供大家学习交流。本站所有资源均不用于商业用途。

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