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

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

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

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

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

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

本帖最后由 shane007 于 2021-1-2 13:56 编辑 * }! b' k& o* S4 K! i. t7 g/ Q

- Q+ X% k8 I5 L/ H最近找到了一些和幽魂系列Phantasmagoria 有关的资料,7 l6 j( L7 a( X4 \  E' B  s% M
也许将来可以用于汉化。
  X! |3 N# _( ]$ Q
+ _- p# c1 T: t: e5 j- {和日文版有关的信息1 a$ R: w2 y0 x; f* i' y3 c; j$ q
http://anthonylarme.tripod.com/phantas/phintgtp.html" A! m. [! h. o
! s3 j/ G. W# |; b& M
相关工具$ s: H% G9 X' V: l% S+ b2 Y. f
http://anthonylarme.tripod.com/phantas/phcheats.html
  c" w& n1 O% a% D-----------------------------------------------------------------------% R0 E. t3 y. G) X) G
2012/1/2  更新9 n( ^" z5 H" M
关于幽魂游戏的字幕7 s$ v2 I- @3 B8 X; x7 a0 S3 S# h
Phantasmagoria subtitles function discovered - ScummVM :: Forums
2 R2 Z# z+ j  L/ b$ Q/ u9 ^! x% |
VMD文件; J) G. {  r: j$ H1 ?
Subtitling Sierra VMD Files | Breaking Eggs And Making Omelettes (multimedia.cx)VMD - MultimediaWiki
* K9 `) @# I/ {* z5 j6 H
7 p, i5 |- ?1 s' U( P字幕7 R, v' E: Q* {# U  `6 m! ?/ ?
Subtitling Sierra RBT Files | Breaking Eggs And Making Omelettes (multimedia.cx)  g/ d" P- s+ v, D
3 u4 O8 Q7 M& L% |. q! F. o* f8 J: R* `
FFmpeg/subtitle-rbt.c at feature/VMD_encoder · multimediamike/FFmpeg · GitHub5 D% K8 S% X1 v/ D  o  P% s
  1. /*
    ! f9 u1 K- ?5 ]1 _7 O
  2. * subtitle-rbt.c
    0 J& i" o; W2 o: S: ^0 k
  3. *  by Mike Melanson (mike -at- multimedia.cx)- W. Y' i; f) e6 g
  4. *
    + \) u( [% T5 _' j. A3 p
  5. * build with this command:
      g* G* q! l' V/ y
  6. *   gcc -g -Wall subtitle-rbt.c -o subtitle-rbt -lm -lass
    ' ?& x# a# f, g
  7. */
    % T6 W9 ]* `1 o
  8. / M4 Y7 V& W7 ]( z) H
  9. #include <inttypes.h>
    4 ^6 L/ j! |+ A% }
  10. #include <math.h>
    ; u  ^2 V. P! e2 g. K* O/ K
  11. #include <stdio.h>+ P1 _* g" D  {( @+ o' E
  12. #include <stdlib.h>
    / O' h9 K8 u  g/ |' R
  13. #include <string.h>5 F4 |. j2 A4 B7 x; L1 q0 Z2 }# f" f

  14. 8 T2 F) D; b" A6 {' i& I9 e3 e% J' }( I
  15. #include <ass/ass.h>
      B- x2 C# D8 \7 F4 {2 t/ U

  16. 6 b* ~' i1 v$ W9 J7 G* e8 ?" V
  17. #define LE_16(x) ((((uint8_t*)(x))[1] <<  8) | ((uint8_t*)(x))[0])
    6 q+ h4 Z" ]- r4 [. Q- V
  18. 9 U, r: @; _% a/ N$ k- R
  19. #define LE_32(x) (((uint32_t)(((uint8_t*)(x))[3]) << 24) |  \9 l& o# W7 ^  ]! j7 E
  20.                              (((uint8_t*)(x))[2]  << 16) |  \
    ! X* w/ \) ~$ G8 C$ p  h2 ^% H
  21.                              (((uint8_t*)(x))[1]  <<  8) |  \' B1 k+ s" i( o+ ~/ z
  22.                               ((uint8_t*)(x))[0])5 O! f2 _9 L  [- Y. I6 H& j1 f

  23. , M7 E, N2 \% B) l# z
  24. /*********************************************************************// u7 C# b6 e2 _( D; z6 p
  25. 1 T/ y6 D3 o- u- \0 S4 ?3 d
  26. /* Bit reader stuff */3 M0 v. t* Q+ S4 h1 U
  27. ; p, S1 C0 y- N! W' P/ x
  28. typedef struct. l9 a2 `  T6 T# X+ E  V
  29. {) J) ^2 o4 j9 ~5 _
  30.     uint8_t *bytestream;1 l* B# w/ c5 N( ~' W
  31.     int bytestream_size;
    4 T3 Z- i  }8 V) r4 [
  32.     int index;
    , [& |" w& l, @- W
  33.     uint32_t bits;( r8 ?4 i: c# n# D, o
  34.     int bits_in_buffer;- }' r: Y/ @4 `( [
  35. } get_bits_context;3 v( g1 S' k7 w. E" |
  36. 4 l" K3 u) D: J/ D8 U$ J; h
  37. static inline void reload_bits(get_bits_context *gb)
    & l2 N* F& _2 ?/ Q* K
  38. {
    7 w0 |1 @- {& p, g
  39.     while (gb->bits_in_buffer <= 24)7 N) a0 x5 z3 _1 a
  40.     {
    . P3 i, [0 e7 b. _9 \# N: j5 O
  41.         if (gb->index < gb->bytestream_size)
    ! C8 F; e4 {' c5 P! q/ n
  42.             gb->bits |= (gb->bytestream[gb->index++] << (24 - gb->bits_in_buffer));0 h/ y3 @2 A" J& x- G  O1 B
  43.         gb->bits_in_buffer += 8;% z; c+ {+ P5 d# @! j! j3 N
  44.     }2 g8 H2 `; m: F) ]1 s$ \9 V
  45. }
    & U7 h) M! y1 E' p3 q3 k7 n
  46. ; t" M( ]4 @+ p& E( W4 G0 N
  47. static void init_get_bits(get_bits_context *gb, uint8_t *bytestream, int size)
    ( Z; t: I! p) b( W; H
  48. {
    4 f  |1 H  N, k7 {
  49.     gb->bytestream = malloc(size);- S& a$ q9 Z( K- T  f, R  C
  50.     memcpy(gb->bytestream, bytestream, size);4 @" B# _1 l# k. C" p
  51.     gb->bytestream_size = size;
    % h4 r0 \- F+ j$ V7 O) A) k" `- n
  52.     gb->index = 0;3 J3 o' u4 K( ^6 Z3 h
  53.     gb->bits = 0;
    * }3 @$ n$ g# d& q& r
  54.     gb->bits_in_buffer = 0;2 L( y% l1 u4 k$ Z# t( ~: v
  55. 4 t  ?8 {+ d; w7 k1 }
  56.     reload_bits(gb);
    9 k, _: w' \$ c- a1 X* N4 Y# o5 B
  57. }
    ( s2 V+ Z+ j6 w$ C

  58. , R8 {1 O, P' l: M) q0 ^
  59. /* read bits without consuming them from the stream */1 L) r3 b- S2 L
  60. static int view_bits(get_bits_context *gb, int count)
    8 A# G. _/ y. E$ s2 O$ D
  61. {
    - T; B& t8 U$ v+ x4 F9 |$ \" K* P0 G
  62.     if (count >= 24)( c0 ~1 d, X4 I  I$ V
  63.         return -1;" x! E& ?) B0 u2 m
  64.     if (gb->bits_in_buffer < count)8 p! q6 k3 ]* i9 `& l
  65.         reload_bits(gb);( E7 P+ p, l" z, \# f! v
  66.     return (gb->bits >> (32 - count));
    / l& W6 z. I+ ]0 ?/ V/ L" A
  67. }
    9 ^( [; t. n2 D* f
  68. 3 U. F7 Q+ p: A+ A
  69. /* read and consume bits from the stream */
    4 R& B4 b2 |! ^5 W8 s
  70. static int read_bits(get_bits_context *gb, int count)9 c1 _$ [- p5 n
  71. {. @, |( l$ B3 _, J
  72.     int value;) f3 w& _. J' x3 E6 N4 R6 {7 j

  73. / H- t% W9 l2 H& P4 g; W# A( I
  74.     if (count >= 24)
    ' c' {7 D, w, `
  75.         return -1;
    - q0 V" b9 t! {% R8 X
  76. 1 i# P2 k3 I- v; N' O) F
  77.     value = view_bits(gb, count);
    $ m7 @5 k: K1 E4 }; B
  78.     gb->bits <<= count;% j( g5 @2 g; h/ y6 o
  79.     gb->bits_in_buffer -= count;
    + X, E5 B( L9 ^$ O4 t
  80. / d& i5 y4 _6 ^- t; E
  81.     return value;
    9 q3 W9 b0 t8 R6 w( G' |* P% [
  82. }
    , W8 e2 y" A( A, {3 O  a

  83. ! F7 E8 u% d" z  w) Y4 e
  84. static void delete_get_bits(get_bits_context *gb): n, S) }7 E2 H: E7 g+ P/ R: j
  85. {" ~, q. `  b# q* u/ F
  86.     free(gb->bytestream);/ t- X- O& l- ]: u0 C  {4 I. w
  87. }
    0 k" a: }+ z9 t
  88. 8 y- m0 }, {0 M/ u
  89. /*********************************************************************/; _3 F3 a% w% W/ e+ S$ ~7 C) q* X0 }
  90. $ E- `* d, n' y& Q
  91. /* Bit writer stuff */& o/ B0 W' n% X; Q9 ?

  92. * e! R' Y: S0 o- t4 b
  93. #define MAX_PUT_BITS_BYTES 63000
    / a; ~! G$ n/ P3 n, q
  94. typedef struct
    0 j4 F+ t8 [/ c8 I3 ^
  95. {) Z- J. z* r% K5 z( u2 m( b$ g
  96.     uint8_t bytes[MAX_PUT_BITS_BYTES];
    . `6 ]* P" W( C& U! s
  97.     int byte_index;0 T: f0 s: K& R
  98.     uint32_t bit_buffer;: h9 z" m- j6 Q  b
  99.     int bits_buffered;
    ; [9 X; C0 h8 G: V9 ~& @5 G
  100. } put_bits_context;7 g5 `- R+ ?+ J2 `

  101. " `' {- ^/ o$ t& z& J; R
  102. static void reset_put_bits(put_bits_context *pb); M$ w; X: w4 r" r
  103. {
    . T: }9 }% c# \( ]! O$ d
  104.     memset(pb->bytes, 0, MAX_PUT_BITS_BYTES);
    2 j1 q' p  t- S2 j' p' ]
  105.     pb->byte_index = 0;
    4 o, I3 T/ e1 m5 |. D* g
  106.     pb->bit_buffer = 0;
    0 Q* h( {! W, c8 }
  107.     pb->bits_buffered = 0;
    . B! p# r$ E! U# p5 m  [+ g! ]
  108. }
    : C2 R( C& [8 x+ ^8 q
  109. 5 N5 w6 c" j1 J; F& y
  110. static put_bits_context *init_put_bits()
    " D6 p# [( t& r( ?1 t* d9 y
  111. {* f/ e9 [2 U. \4 ~1 h& _) `) L
  112.     put_bits_context *pb;6 W# s7 {( D* o# }
  113. 6 p; X5 e0 B; a! F  x3 G
  114.     pb = malloc(sizeof(put_bits_context));8 A( i* J6 G( y3 X0 ]/ ]
  115.     reset_put_bits(pb);
    8 J- F1 n! D# D( H% a$ Y/ Z* }

  116. & ^8 ]" ]$ p) {5 n
  117.     return pb;9 X' T% L  S( D1 B. F
  118. }
    ( f8 L/ j  g' ?) ~0 M' ^" B5 s+ T

  119. * k/ T* q: P- T* ^' T' v2 r
  120. static void put_bits(put_bits_context *pb, int bits, int count)- \; Q# Q& ^3 Q; I
  121. {. a) @4 p' m, t# K
  122.     pb->bit_buffer <<= count;
    7 U) {( C0 ~) C1 O5 ?+ B9 r
  123.     pb->bit_buffer |= (bits & (~(0xFFFFFFFF << count)));- k9 k! H9 {' W) [/ v
  124.     pb->bits_buffered += count;& ^+ x& ]0 O/ h& G

  125. 4 V' O8 T# `% r2 w) }( o4 Q
  126.     while (pb->bits_buffered >= 8)
    ) ~' u( E) s5 P4 M/ M; [& \
  127.     {
    : n0 R5 I5 C. p1 N7 v
  128.         pb->bytes[pb->byte_index++] = pb->bit_buffer >> (pb->bits_buffered - 8);
    , g! A6 o6 Z6 Q
  129.         pb->bit_buffer &= (~(0xFFFFFFFF << (pb->bits_buffered - 8)));
    & @8 y7 @3 L1 l1 p) ]- s: j" Q
  130.         pb->bits_buffered -= 8;- c# A8 N& J6 I7 k
  131.     }
    : O- d/ A7 N( {8 D, K% \1 J6 x+ E8 ]1 I
  132. / E8 O8 ?; f6 S; w. v  ^( f1 G
  133.     if (pb->byte_index >= MAX_PUT_BITS_BYTES)
    8 p! Q1 a$ k6 G
  134.     {
    ' H3 G' L% O7 T* i
  135.         printf("HELP! Bit overflow\n");
    $ f  k3 M. @8 P. G" C9 X# I1 X
  136.         exit(1);8 j. m0 z/ C( R( y
  137.     }
    - G: g! U( Z' H# K  N5 y+ j6 N
  138. }0 g/ F' m9 a1 }" g  O) S

  139. 0 j5 m! x: Q1 Q0 ~! E  W1 k
  140. static void put_bits_flush(put_bits_context *pb), A7 i- M+ `/ M) `6 ^
  141. {
    4 s& h. r% w$ e$ i8 q5 P
  142.     if (pb->bits_buffered > 0)5 X. B+ y0 r8 @5 D: y% m4 [
  143.         pb->bytes[pb->byte_index++] = pb->bit_buffer << (8 - pb->bits_buffered);! i5 R7 c! M5 m" I" X% Z) |8 `
  144. }# e8 k8 D/ ]" m0 @- ]4 p; E+ D* E5 |
  145. 3 u6 F) C: i! `
  146. static void delete_put_bits(put_bits_context *pb)
    8 J" [2 a. e% s1 g( V) j0 a" J
  147. {+ Y( t6 u9 C# {
  148.     free(pb->bytes);
    9 o$ E6 O% j# y7 c$ g' F6 U
  149. }  O- R2 \9 I) N

  150. . U/ S, G! Z5 x' f' i8 x3 i
  151. /*********************************************************************/: _" P. x4 V/ a, x& N% M6 n
  152. / e2 S- U6 q, z1 g
  153. /* RBT functions */
    . G  X+ j5 _# L7 e! i' A
  154.   x% x# Z5 a( h& R5 D
  155. #define PALETTE_COUNT 256
    - W; ^% L7 J1 I5 G+ z  z5 C9 i
  156. #define RBT_HEADER_SIZE 60& H9 ]! E% E7 D2 }
  157. #define UNKNOWN_TABLE_SIZE (1024+512)
    * t' [1 ]  z& }  s  [6 I
  158. #define SUBTITLE_THRESHOLD 0x70
    ) w& a3 X+ H2 s8 H. a/ a
  159. #define MILLISECONDS_PER_FRAME 100; `: G' e! }' Q  z" D% R
  160. , l3 t) b% q' A, h- M9 E* M( ~4 t
  161. /* VLC table */* M6 f8 v# p- Y3 E2 i
  162. #define VLC_SIZE 4
    . c0 B3 E6 }0 M5 Y
  163. static struct# L" N8 @) i6 R9 ]; r
  164. {
    ! e( H2 m0 k! M) c9 p8 E# U  r4 N
  165.     int count;  F* D# h+ R4 f+ Q. \& |9 f
  166.     int value;
    : j" Y5 E/ i/ S0 i- \; {" O( \. ?7 d
  167. } lzs_vlc_table[] =
    ; b% T6 V/ J; K. {
  168. {' u+ {8 q, T6 V* s
  169.     /* code length = 2 bits; value = 2 */* E/ F) B+ ?& o* n* r
  170.     /* 0000 */ { 2, 2 },- W1 @8 o: B  [/ _$ M) \
  171.     /* 0001 */ { 2, 2 },
    5 h! q% G) j4 a6 e
  172.     /* 0010 */ { 2, 2 },
    # b: S1 A$ a$ b
  173.     /* 0011 */ { 2, 2 },9 k3 V6 t+ Q/ u! F& e# P

  174. & F; Q+ c  `4 T/ t# J' ^# d; `5 _
  175.     /* code length = 2 bits; value = 3 */
    . d5 U/ d# q% c9 u2 P/ v; d% p; t
  176.     /* 0100 */ { 2, 3 },
    . S7 B, r$ O* t7 s1 O7 s
  177.     /* 0101 */ { 2, 3 },+ @$ d% }1 H9 Z' ~; b
  178.     /* 0110 */ { 2, 3 },/ i) h, Q+ j+ |* x
  179.     /* 0111 */ { 2, 3 },, k! y/ r0 ?9 S/ V

  180. . Y9 L( ~$ a# g0 Q/ Y8 R9 N- b/ E
  181.     /* code length = 2 bits; value = 4 */# s" x. M$ \6 z; M# l
  182.     /* 1000 */ { 2, 4 },) u( i1 u) u; M" h, i; q/ t
  183.     /* 1001 */ { 2, 4 },' z0 E9 F: B, _7 b4 s" G1 D. O8 A
  184.     /* 1010 */ { 2, 4 },
    " U; O9 T) R8 L6 m+ u4 ~
  185.     /* 1011 */ { 2, 4 },
    . H# M* ?) m; S0 Q
  186. 2 ?, |. a# z7 k! s
  187.     /* code length = 4 bits; value = 5 */4 j" m" J& Q( n8 _7 j! y9 P" _
  188.     /* 1100 */ { 4, 5 },4 R3 r! x* `: i. [8 x

  189. 3 V- s! e) x4 D1 k
  190.     /* code length = 4 bits; value = 6 */+ I5 n; v5 B/ i: ~9 d
  191.     /* 1101 */ { 4, 6 },# L% t- c/ T* E0 V& s

  192. $ a9 w. T4 V. `6 [$ `8 c
  193.     /* code length = 4 bits; value = 7 */
    5 c( O+ e+ L# c/ }
  194.     /* 1110 */ { 4, 7 },
    & a7 _, j9 h# X

  195. 0 n; x8 O; z3 i# O! s
  196.     /* special case */, `% I3 |' x( n
  197.     /* 1111 */ { 4, 8 }
    3 g9 F. S- O* s0 x6 H7 z
  198. };
    5 Q; d9 |7 w) @% w' n
  199. 0 x# K. M3 C0 H
  200. typedef struct% {  K" E* ~6 h; g" L$ Y/ {3 X" i7 a
  201. {; y0 {3 J* z$ a, ^
  202.     int version;; q# J( s# y5 A- U3 G
  203.     int width;
    ( R- F3 ]& I6 q6 c
  204.     int height;  Q( a0 B; L5 g- @
  205.     int frame_count;
    7 L% c7 N1 u7 e8 @4 W& `
  206.     int audio_chunk_size;3 o  C% Y; @/ J' D' ]" u- R6 Q
  207.     uint8_t palette[PALETTE_COUNT * 3];$ m- u, f9 z1 o& h' T
  208.     off_t video_frame_size_table_offset;2 D5 X) F- K0 e. W- C
  209.     uint8_t *video_frame_size_table;
    1 [- }$ C/ I4 x# W0 E
  210.     off_t frame_size_table_offset;
    . V1 a6 t& K/ E4 S$ H; @4 Z1 e  d
  211.     uint8_t *frame_size_table;
      H6 z  |& |. L! u9 Z7 d$ S
  212.     uint8_t *frame_load_buffer;* @  L7 a# d9 h; w5 c6 ^
  213.     int dump_frames;
    5 m# |; R' d  [1 ]

  214. 0 y& a1 p$ Z4 U: _$ @% P
  215.     /* subtitle library */% i% K' _" C; W1 R0 b
  216.     ASS_Library *ass_lib;8 {& H+ J- M: V7 G9 O# F$ g+ B
  217.     ASS_Renderer *ass_renderer;
    0 B0 @- H& n! H; N7 h. _
  218.     ASS_Track *ass_track;5 {1 U# P' I( O; X
  219. } rbt_dec_context;
    & @% N/ ^6 h  M! _( B) [: O' i
  220. 6 f! Y& ~. `" ~) t1 c% D5 v8 I
  221. static void dump_pnm_file(char *filename, rbt_dec_context *rbt,/ A' o) c$ L5 d4 H( h
  222.     uint8_t *image, int width, int height)6 {# J! q: D+ \$ d4 N' b  S0 w
  223. {
    ( v* z# `* g+ ~5 |
  224.     FILE *outfile;
    * g% w+ b( U7 E& b7 u
  225.     uint8_t bytes[3];" j  E  j6 }& D9 e
  226.     int p;1 D4 r2 C7 `* V( n3 \
  227.     uint8_t pixel;
    0 l$ h- a* j+ \9 S+ y
  228. 2 c' ^' i# v: a1 \! O& ?0 K
  229.     outfile = fopen(filename, "wb");9 V3 n3 M( E; N( V1 A
  230.     fprintf(outfile, "P6\n%d %d\n255\n", width, height);
    . Z0 V- \8 D4 C5 B
  231.     for (p = 0; p < width * height; p++)
    : y+ `! g9 f+ V5 p; ~, |, }- B3 e
  232.     {
    / l3 M8 Q3 j1 q) ]) J+ ]
  233.         pixel = image[p];1 Y, T8 s: ~. l4 r
  234.         bytes[0] = rbt->palette[pixel*3+0];" U3 J; `5 \, l0 N9 I2 B/ q
  235.         bytes[1] = rbt->palette[pixel*3+1];, \4 q) V- y0 [' y3 X
  236.         bytes[2] = rbt->palette[pixel*3+2];  {) A5 c- V) Q1 G
  237.         fwrite(bytes, 3, 1, outfile);& f" Y# I* n+ O. P6 B
  238.     }
    2 _' c1 _0 e: `/ `( W7 B! {
  239.     fclose(outfile);
    7 v' F2 l3 x0 y5 R- F
  240. }
    + }  M$ v0 X+ Z9 {0 x: L  d
  241. * D) ?5 w& k' R, J3 [3 g
  242. static int load_and_copy_rbt_header(rbt_dec_context *rbt, FILE *inrbt_file, FILE *outrbt_file)
    . S$ B4 P- i: R) R
  243. {6 f6 L; i  Q* h' n* h
  244.     uint8_t header[RBT_HEADER_SIZE];5 C1 v) ~( R, t+ t% O/ X9 L+ F$ _  ~
  245.     int palette_data_size;
    , g6 c: l# Q- F) E! _/ Z4 c
  246.     uint8_t *palette_chunk;
    3 M1 o3 ^) T) s/ h  P( ~* J
  247.     int unknown_chunk_size;0 k6 t. X, D; I3 X. ~* X6 [
  248.     uint8_t *unknown_chunk;
    1 ?* C$ f; M) `5 i; D' T: [* C
  249.     uint8_t unknown_table[UNKNOWN_TABLE_SIZE];! Z* f0 z( [6 j9 q
  250.     off_t padding_size;
    ( h7 n$ e. ]1 \9 [. }
  251.     uint8_t *padding;
    5 v( V, |. M" j- L
  252.     int i;  b; K/ O( s6 f5 o. v+ T  g
  253.     int frame_size;
    ! p. ^  S, ^: w% o
  254.     int max_frame_size;
    0 h7 i( i% `+ s1 f
  255.     int first_palette_index;7 j# x3 c  E: e. b: v* p% L( H
  256.     int palette_count;" R9 u' ?# p1 t( [" n% @% ~
  257.     int palette_type;5 }- Y% w& c( l) l- C
  258.     int palette_index;
    2 M8 Q( A2 u  b+ b* d

  259. ) l# i5 b4 P4 [, e. E# X& {3 ?
  260.     fseek(inrbt_file, 0, SEEK_SET);
    9 P4 J9 O% G' b. v: ]: u: D
  261.     fseek(outrbt_file, 0, SEEK_SET);
    : ~8 x. `9 m) y( w6 f) L. f

  262. / k/ L/ T7 l; {+ C  S: ]
  263.     /* load the header */
    - @+ h- j0 B! x7 V' O% U5 Y# d
  264.     if (fread(header, RBT_HEADER_SIZE, 1, inrbt_file) != 1)  ~! \( Q1 E5 D; t- U
  265.     {! V- j1 U/ G4 p0 c' t, q; v
  266.         printf("problem reading initial RBT header\n");# y! M* x6 k8 {2 r
  267.         return 0;' i# o! J* N6 O1 `$ p& U% J
  268.     }1 T6 Y6 g; ^$ r

  269. ; T) }' c2 Y! u) H- i% t3 Z
  270.     /* copy header to the output */
    & ?+ v& `4 w& G/ [" T( t( E, r
  271.     if (fwrite(header, RBT_HEADER_SIZE, 1, outrbt_file) != 1)
    $ i- y* ^& D& Z3 H. Y: R+ w
  272.     {: ]& s; \0 @, u! Y8 N  p
  273.         printf("problem writing initial RBT header\n");1 X1 D4 @0 L) m, u  b5 i2 }
  274.         return 0;7 x6 u! f( k: r: O+ Z( D* N
  275.     }% ~  |6 z' {& F$ _- t6 M5 Q% e( N5 |3 @

  276. 3 O) u+ }' o0 \4 w4 ^1 ]
  277.     rbt->version = LE_16(&header[6]);) b! N& I* `% `4 }$ k6 x+ O0 y! Y. f
  278.     rbt->audio_chunk_size = LE_16(&header[8]);
    2 g) [, D9 Y) g5 r' g' i
  279.     rbt->frame_count = LE_16(&header[14]);
    3 T7 w; ~: S+ C  X8 C
  280. + [8 h1 _; w  ^  Z# J( U. H7 \* L
  281.     /* transfer the unknown data, if it's there */$ q0 P0 x" r8 u" n  I
  282.     unknown_chunk_size = LE_16(&header[18]);
    4 Z* v; Z$ l) ~2 W6 [. U
  283.     if (unknown_chunk_size > 0)1 R$ O: E* \" W5 t9 \
  284.     {
    4 Q: e- f9 ^! Z* L
  285.         unknown_chunk = malloc(unknown_chunk_size);
    6 e  T9 ~! J8 j1 ^) }, B
  286.         if (fread(unknown_chunk, unknown_chunk_size, 1, inrbt_file) != 1)- P! L2 _4 G1 _0 [) T  @2 h
  287.         {3 `* u# t  ]) E' m
  288.             printf("problem reading unknown data\n");! Y4 y5 J$ l1 ]* x" K" M1 L
  289.             return 0;2 d; o( y* _! G$ C
  290.         }
    8 P3 C8 q( q% x4 H5 _
  291.         if (fwrite(unknown_chunk, unknown_chunk_size, 1, outrbt_file) != 1)
    / ^7 V) s4 n' h1 q% _; [4 J
  292.         {
    # @/ @2 e4 x3 }6 W% {: i9 p
  293.             printf("problem writing unknown data\n");" L1 `+ r, C9 g
  294.             return 0;. C+ e6 M  S1 ?9 i. S
  295.         }
    $ [, S5 Y. _3 k* N9 O- o: O
  296.         free(unknown_chunk);
    / h7 e& a3 ^' o6 [  c: Y
  297.     }' D9 ^$ h2 q, D, s- @! a

  298. $ y! L) ~9 t6 [- ~: ]& ^
  299.     /* transfer the palette chunk */) _% ^/ m. R+ T3 M1 E
  300.     palette_data_size = LE_16(&header[16]);6 M4 Q) \3 v4 [
  301.     palette_chunk = malloc(palette_data_size);% Q6 M* O% j: E6 X
  302.     if (fread(palette_chunk, palette_data_size, 1, inrbt_file) != 1)3 X1 l1 |& p- R# R( E# m
  303.     {  T# y4 U  a4 U: |" |) z! I
  304.         printf("problem reading palette\n");  I* p3 H  `9 o9 o+ j
  305.         return 0;
    . P% k# I6 ?3 V
  306.     }% b' S; ^* i  P& E8 q6 M2 _
  307.     if (fwrite(palette_chunk, palette_data_size, 1, outrbt_file) != 1)9 i4 P! z+ d" n2 G/ }
  308.     {
    / W$ ~: q$ ^8 {, K
  309.         printf("problem writing palette\n");
    ! l! A9 a6 P. _& ?( o( X( [; @7 [# B
  310.         return 0;
    & P3 j/ s2 [# |
  311.     }; I7 m0 o4 D3 f4 k
  312.     /* load the palette into the internal context */& [7 ?, T1 q) n7 f* p$ ~: _) L, ~! s
  313.     memset(rbt->palette, 0, PALETTE_COUNT * 3);
    9 B4 ]* j8 i' f& }' m( H) K
  314.     first_palette_index = palette_chunk[25];
    , u: O! ?+ ~/ J" D' p9 J
  315.     palette_count = LE_16(&palette_chunk[29]);( [. Y& Y% q2 I
  316.     palette_type = palette_chunk[32];- [0 R9 h: R) A
  317.     palette_index = (palette_type == 0) ? 38 : 37;
    ' `7 u) M/ G1 Y' W" J
  318.     for (i = first_palette_index; i < first_palette_index + palette_count; i++)# b" R  F8 c0 E: f
  319.     {" T0 W+ y* h, S' A' d8 e. t
  320.         rbt->palette[i*3+0] = palette_chunk[palette_index++];+ ]0 l9 u7 i& N6 t
  321.         rbt->palette[i*3+1] = palette_chunk[palette_index++];
    ! ?# y% A3 c* j: i2 o0 n7 }
  322.         rbt->palette[i*3+2] = palette_chunk[palette_index++];* G: H3 e# j* U- }
  323.     }
    ( X7 J' c9 a+ p) f0 o
  324.     free(palette_chunk);+ A7 P0 G* y1 L0 k5 O: _# @

  325. 9 \: u+ x$ I: P* _% i2 O+ A
  326.     /* copy the video frame size table (2 bytes per frame), as a placeholder */
    9 I) g( p9 `: J
  327.     rbt->video_frame_size_table = malloc(rbt->frame_count * sizeof(uint16_t));
    ( W5 j, i# A9 @7 `6 g" s
  328.     if (fread(rbt->video_frame_size_table, rbt->frame_count * sizeof(uint16_t), 1, inrbt_file) != 1)5 L; G7 h+ E) S# a1 v/ L7 Q* x
  329.     {" `) L4 x6 t4 P- ^) g
  330.         printf("problem reading frame table\n");- u9 C0 }+ e1 A  I/ f3 u3 ~$ N9 H
  331.         return 0;
    ' B' ]& a8 @& {: s, P/ C  W
  332.     }  R+ `% O) E! @( d$ k0 i
  333.     rbt->video_frame_size_table_offset = ftell(outrbt_file);, C1 M7 n- C; t4 j  ~
  334.     if (fwrite(rbt->video_frame_size_table, rbt->frame_count * sizeof(uint16_t), 1, outrbt_file) != 1)9 u. r( ^9 {, [, _0 a  n' h) f
  335.     {4 X2 D# A5 [% Q3 [: o! L; c$ s
  336.         printf("problem writing frame table\n");- C. N  I6 q; i1 r2 f
  337.         return 0;, X, d4 ?+ |4 b( j( M
  338.     }
    ) H/ `$ C; A3 N+ ^% O7 q- ~

  339. / C- U# b, S: Z/ c
  340.     /* copy the frame size table (2 bytes per frame), as a placeholder */
    ' a, J1 O: W/ G9 z, ~& d
  341.     rbt->frame_size_table = malloc(rbt->frame_count * sizeof(uint16_t));
    7 G2 N+ l- l+ W% O0 q! c! o2 c# Q
  342.     if (fread(rbt->frame_size_table, rbt->frame_count * sizeof(uint16_t), 1, inrbt_file) != 1)# o* t! L% \4 X
  343.     {
      k9 s+ D2 r7 H/ y, z5 [
  344.         printf("problem reading frame table\n");
    & |! w/ m, \; S' g: Z6 d/ B
  345.         return 0;
    , d. U/ q" @7 t% b( s# k/ O1 i0 E( Q) j
  346.     }
    - B( }2 W  U  w1 ~
  347.     rbt->frame_size_table_offset = ftell(outrbt_file);
    : L6 ]# p- t% S( x* I0 x
  348.     if (fwrite(rbt->frame_size_table, rbt->frame_count * sizeof(uint16_t), 1, outrbt_file) != 1)
    - @1 k! w( L6 z# F+ z4 t
  349.     {
    * t# V0 I" H; _: |0 M+ S& D+ m, D
  350.         printf("problem writing frame table\n");/ m3 P7 @3 W/ j: ^+ g
  351.         return 0;
    " L- n/ p( I6 ]" C: N/ ~
  352.     }0 w6 h; K+ g, o  o" S1 U

  353.   g& b( F. o9 L9 }2 b- @' ?% m( |
  354.     /* find the max frame size */
    : y2 F" B8 L- Z  P. V5 J9 A
  355.     max_frame_size = 0;. q* i8 ^4 ~- S# r8 ~
  356.     for (i = 0; i < rbt->frame_count; i++)- w7 ~( T- p: l$ j* s2 o2 w! n
  357.     {
    " _3 b* _6 P; o" z
  358.         frame_size = LE_16(&rbt->frame_size_table[i*2]);
    ; f, c  R$ k/ s  Q
  359.         if (frame_size > max_frame_size)5 @2 V: K- i8 u9 d& \& I
  360.             max_frame_size = frame_size;0 H, D4 M: e/ E6 u) Y: |
  361.     }( Z8 O! S% F% q7 g. L! W
  362.     rbt->frame_load_buffer = malloc(max_frame_size);
    6 S. x2 G. n' x+ l# R
  363. 1 x4 H: j  b0 P% c4 v! O- K) k; \2 P
  364.     /* transfer the unknown table(s) */
    4 _% ]3 ~  D/ S! N2 R
  365.     if (fread(unknown_table, UNKNOWN_TABLE_SIZE, 1, inrbt_file) != 1)
      {' d( C9 O  `, O6 @# |* C: Q
  366.     {
      a  }/ d$ X* n5 i& k
  367.         printf("problem reading unknown table\n");& }) t" B' {- ~+ `4 H( X. i
  368.         return 0;
    7 W! [  S. P, m) D
  369.     }6 U) [% G2 l, R; s6 b/ f4 Z
  370.     if (fwrite(unknown_table, UNKNOWN_TABLE_SIZE, 1, outrbt_file) != 1)2 a1 u7 x4 @. Y. d& z+ Q
  371.     {
    7 N' x9 F8 v4 o& ]4 @5 q/ C
  372.         printf("problem writing unknown table\n");2 c; Z3 f) S0 L( A8 Q, |1 t& w
  373.         return 0;
    4 z: u# z' j% v! T8 A* E
  374.     }5 ]$ \/ m# {3 q3 D7 t/ k$ k( @6 F3 [+ i

  375. ! E2 W; Q: }9 N3 K4 D$ _' y! D: c$ s
  376.     /* copy over padding */
    + [7 `6 q8 |4 T4 X2 @7 y/ @* L9 f+ H
  377.     padding_size = 0x800 - (ftell(inrbt_file) & 0x7FF);
    : A1 n  ~4 Y( A/ C7 Z! F( q! c
  378.     if (padding_size)' i( i2 c2 z+ v$ l- y6 u2 M# q) k% @
  379.     {
    9 B4 a/ A+ w( N" J. ~: G3 _
  380.         padding = malloc(padding_size);
    " d% X  ]- ?7 a) x. S0 T
  381.         if (fread(padding, padding_size, 1, inrbt_file) != 1)- r3 {& y$ P3 R0 R1 E; I
  382.         {
    . T! m+ G( _) {2 K
  383.             printf("problem reading padding\n");
    6 w% k8 }# x9 c  C9 L
  384.             return 0;
    ! G6 s+ r% b) G/ `
  385.         }5 N% ]( N; }0 h/ ?4 Y) h
  386.         if (fwrite(padding, padding_size, 1, outrbt_file) != 1), ]4 v7 ^7 `- d( h
  387.         {, t2 m2 \7 v& v* ]4 u% I
  388.             printf("problem writing padding\n");) z- r: M& O% l. e) C, ~
  389.             return 0;9 L, D# V  b  @/ q8 ^# ^& h
  390.         }% q' G' C9 e( |) I) n
  391.         free(padding);. K0 f5 N, K3 z) w7 M
  392.     }
    4 I0 _0 d. Z5 L1 m" {, e

  393. % a- f- |" `: }* B
  394.     return 1;4 p: p; o6 t; l1 f
  395. }% I( y2 e6 I! ^  O

  396. + O  ~. V+ H' d* z; b6 |
  397. static int get_lzs_back_ref_length(get_bits_context *gb)
    - g2 O7 }2 D8 w+ _- F4 n0 U
  398. {' P! o0 s, p! M+ ?
  399.     int vlc;% P7 [) M' X9 i7 k
  400.     int count;$ _' f% D% h6 }2 M$ o# X
  401.     int value;
    * V) S% V! k; H1 T0 ]& i8 V5 a- O
  402. " x9 u3 E- ]* }% g8 k
  403.     vlc = view_bits(gb, VLC_SIZE);
    - z  |& o5 v8 k% Y
  404.     count = lzs_vlc_table[vlc].count;; O) B0 p) N- A& ]
  405.     value = lzs_vlc_table[vlc].value;  x7 G3 }+ q& {  P

  406. : V, k8 v! `6 I- D* ^( O* j* q
  407.     read_bits(gb, count);' l3 ~$ a, v' L# y
  408.     if (value == 8)' e: m2 r; x+ `" k, z) V
  409.     {- |6 u4 g6 P1 g' T& Z
  410.         do: V3 y8 C. d6 o7 s0 E& S
  411.         {
    4 T$ N( [$ A, Z0 ~% d% i
  412.             vlc = read_bits(gb, VLC_SIZE);0 v; @- m& G$ r- p( s8 ]" I, k. ?  p  G
  413.             value += vlc;
    8 O. \4 G1 F3 s
  414.         }6 N' ~: u0 t, l- `
  415.         while (vlc == 0xF);8 [/ f) W+ N% d: @
  416.     }
    ' x2 i0 |9 U9 M# ~6 s

  417. & J5 `4 I9 q% j0 I8 V/ l
  418.     return value;
    ; r  x+ a  m9 D; T- O/ B( F- D, K% ^
  419. }
    ; e6 x, ^; [0 W% [4 m( l' d: `8 [) U

  420. ) v! ^% G/ M. D& Q0 @
  421. static void compress_window(put_bits_context *pb, uint8_t *full_window,
    ; Z% E2 W/ ?4 M( B1 K
  422.     int full_window_stride,0 Q# T7 k2 ^' B; i1 q
  423.     int window_top, int window_bottom, int window_left, int window_right)2 T1 j: y& P; @8 H
  424. {
    . ]4 c3 W/ u) f1 l5 F7 r) p
  425.     int last_pixel;
    - t# Z2 s, J2 }2 `
  426.     int run_size;# G8 C, |/ _+ ]: e, l
  427.     int x;
    - r: M% q8 ^8 W/ t
  428.     int y;; S. O3 J! I' Q
  429.     int start_index;
    1 @; v2 f* N7 y: h' p$ f, W
  430.     int end_index;# N$ @. t0 P3 H0 F0 V* v
  431.     int encode_last_run;
    4 f: L  c. K- w" a( X" }0 S5 U
  432. ; R  T+ S2 u7 K- D! W1 f) S
  433.     last_pixel = full_window[0];
    % h' _* X' {9 o' |
  434.     run_size = 1;
    , b3 ]- K7 `( e3 P( [4 @+ E
  435.     for (y = window_top; y <= window_bottom; y++)* s8 z  }* T; j$ b
  436.     {
    ; E) O6 F8 h; I* |3 v2 Q
  437.         start_index = y * full_window_stride + window_left;% W' v$ H* w  ^
  438.         if (y == window_top)
    8 O1 @. H! j) W: w
  439.             start_index += 1;
    1 K3 m. M3 W( g2 Y- N
  440.         end_index = y * full_window_stride + window_right;7 R7 x' S* Y+ S% ~( D! f( ?: T* k
  441.         if (y == window_bottom)/ J/ y7 V4 }* a  N6 F0 L
  442.             encode_last_run = 1;
    3 n) {& ^! V- Z# _" A" I5 r
  443.         else: X1 C' O; N- x! B: }
  444.             encode_last_run = 0;
    / f/ `: Q; r  n2 F  b6 ]
  445.         for (x = start_index; x < end_index; x++)1 s% y5 \; W9 Z& z$ D
  446.         {& R$ Z9 e; G1 }  w: `
  447.             if (!encode_last_run && full_window[x] == last_pixel)
    . Y: `" T2 Z; O) k* S8 v6 n
  448.                 run_size++;" {( I& J! Z- s2 ?- K- @$ K! N2 g
  449.             else' m/ z( o6 f" k6 E9 a1 X5 f8 _
  450.             {2 Z) ^- ]5 n+ h1 x. R2 n5 _
  451.                 if (run_size == 1)
    / U7 Q, T5 Z& A' y/ z" H0 |9 O9 J
  452.                 {8 B. i! d' [$ }7 Z& N+ k4 A
  453.                     /* encode a 0 bit followed by raw pixel byte */$ i* u# b3 g, a
  454.                     put_bits(pb, 0, 1);
    " |6 }2 K* v; H" ?2 K$ n
  455.                     put_bits(pb, last_pixel, 8);
    $ \5 q# }/ [7 p! s9 C
  456.                 }  X) q" ?( l1 E( t) ?
  457.                 else if (run_size == 2)" z6 o* K0 h- C# I
  458.                 {' K1 B* Q' e  K/ b% P
  459.                     /* encode a 0 bit followed by raw pixel byte */
    0 M+ M# G9 d- X/ s+ `2 ~6 K
  460.                     put_bits(pb, 0, 1);
    + t# S- l6 `. _9 D2 t
  461.                     put_bits(pb, last_pixel, 8);
    " s6 N/ L/ v# ^" M
  462.                     put_bits(pb, 0, 1);7 E  D& a" R/ [, O' `9 H
  463.                     put_bits(pb, last_pixel, 8);
    + n+ T: F  q& L; U4 l, E$ P6 g4 a* H
  464.                 }
    ! P* @7 k8 ]' ]: W% Q
  465.                 else- o+ v+ f! _# _/ G, d$ B
  466.                 {
    / H9 V5 J; X1 h6 v! |1 v
  467.                     /* encode a 0 bit followed by raw pixel byte */% O' o$ R! F* `2 z: t, d
  468.                     put_bits(pb, 0, 1);
    + p  A- K7 M/ l5 b- [  e# D
  469.                     put_bits(pb, last_pixel, 8);1 b- E3 M2 O( K  d$ \. }) `9 f
  470.                     run_size--;
    9 d: X$ k0 Q$ ^( t$ T1 j
  471.                     /* encode a run: a 1 bit, followed by a back reference' ~; p6 L# N! k( S
  472.                      * offset (-1), followed by a length */" Z7 T2 g: S+ a1 R  D! m7 U
  473.                     put_bits(pb, 1, 1);) m8 b/ j- N) G) |! T1 s/ m# t: z
  474.                     put_bits(pb, 1, 1);  /* 1 = 7-bit offset */; R' ]7 L% r' M  q4 E7 y5 t
  475.                     put_bits(pb, 1, 7);
    6 S) ]8 v9 Q" z; i0 R4 A
  476.                     if (run_size <= 4)+ @; A  o$ v( W6 }+ {0 M4 `
  477.                     {7 p- G0 q8 `0 D9 F2 N' N, {( p$ U
  478.                         /* lengths 2, 3, and 4 are 2 bits */! G, C3 H% `$ }; ?
  479.                         put_bits(pb, run_size - 2, 2);
    7 x9 p4 `! y2 H) P" P) b" O( a* y
  480.                     }
    - H) _( y3 p) m% R/ N- A
  481.                     else if (run_size <= 7)
    9 z- `; Y, N2 t0 Z7 N
  482.                     {
    ) e$ d% j! B( C: ?7 u
  483.                         /* lengths 5, 6, and 7 are 4 bits */; o$ Z( `+ v1 N( I; M/ z% E
  484.                         put_bits(pb, run_size + 7, 4);
    % U( e. Z& f0 p9 g
  485.                     }6 I/ u3 H4 @* H9 ?% R
  486.                     else
    ! g; t' R- S& z/ E7 U8 |) p7 U
  487.                     {
    9 M5 N9 D) U; O; J8 p
  488.                         /* arbitrary length; start by encoding 0xF which
    , H5 b& O! u6 F" v5 c
  489.                          * stands in for an initial version of 8 */
    , N: @2 h( h( R! m
  490.                         put_bits(pb, 0xF, 4);. N$ }/ [+ W) c3 m4 M/ ]( |( d1 A
  491.                         run_size -= 8;0 W. r+ F; T0 {! }/ |
  492. ; X# h! ^( L  ^. i& C
  493.                         /* encode blocks of 4 bits until run_size is 0 */
    . s2 S0 Q5 R0 w) a: P0 ]- t4 Y; ?  O
  494.                         while (run_size >= 0)
    * m2 r8 B- U, c
  495.                         {' i& k0 v+ a9 J7 o
  496.                             if (run_size >= 15)/ l7 a- x3 c$ b" u. J- P6 l1 Q9 D
  497.                             {/ s% D" `  A* U7 o  i2 h
  498.                                 put_bits(pb, 0xF, 4);
    ; x9 Y) w% `2 F. Z4 S8 f9 T
  499.                                 run_size -= 0xF;6 h4 z& Q. Q" O2 a( l$ A' K. w
  500.                             }9 A' J2 l1 V& B/ ~+ F" Y
  501.                             else
    5 u4 Q+ l! r7 l) M; K; T
  502.                             {9 i1 |# {& e/ b; g
  503.                                 put_bits(pb, run_size, 4);
    " j. i  X, w9 t: i  ^* e
  504.                                 run_size = -1;; m/ G) e+ a! |$ J: e. _
  505.                             }9 H! R0 Y$ E9 Y; {6 x# [( G7 c
  506.                         }
    / k9 F$ j. i- P
  507.                     }
    6 K( ~  S+ H. A5 g! J0 O
  508.                 }
    1 \8 x) ?( u1 e6 {0 [. r
  509. + T* b9 b" P. u
  510.                 last_pixel = full_window[x];) T- z, K& q9 e/ ]' k$ ~, ?
  511.                 run_size = 1;+ R$ x9 m; d- h. n( f0 N) K+ O
  512.   Z- ~# @, f. g$ T
  513.                 /* this single x iteration was only here to close the final run */
    8 A7 {$ ?, i$ _( o, B
  514.                 if (y == window_bottom)( n. R( ]8 ^7 B5 k% G
  515.                     break;) r+ X5 R- s& h
  516.             }# o! I' e0 B4 t+ z) ~; D3 g
  517.         }& f" ~$ f$ m4 E% J
  518.     }, f% o2 l' U; }- G6 Z% ^2 c
  519. . W2 Y5 Y8 N/ U7 X; D
  520.     /* close the bitstream by encoding a back reference with length 0 */5 H+ Z& D5 a* b- }- p6 S9 [; h
  521.     put_bits(pb, 1, 1);  /* back reference run */& x' `8 t. f( u$ i! }
  522.     put_bits(pb, 1, 1);  /* 1 = 7-bit offset */
    1 P, X1 x  z# {! I7 E
  523.     put_bits(pb, 0, 7);  /* length 0 */! V0 S) n" ?* ]  c; C. `! j/ j

  524. 1 M; A1 [$ y1 _" M( O
  525.     put_bits_flush(pb);9 z4 W4 Y% d7 L& o! e) T
  526. }
    + m, m, b) `, U2 D/ y
  527. . b4 {- v! V* i2 \+ [2 b
  528. /* compute Euclidean distance between an RGB color and the desired target */
    8 w" p& k/ x' k! [* M
  529. static int compute_rgb_distance(int r1, int r2, int g1, int g2, int b1, int b2)
    & \2 ~8 v* ?7 s
  530. {& E0 o' N) S2 u  [% t3 @+ z* z* k
  531.     return sqrt((r1 - r2) * (r1 - r2) +
    % ^  h7 g" h& g! b8 _; g2 X
  532.                 (g1 - g2) * (g1 - g2) +8 ]2 i1 e4 n  N8 ^( J/ a
  533.                 (b1 - b2) * (b1 - b2));9 [8 Z$ W  t/ P" `
  534. }- s% ?- K5 \; ?! m
  535.   c# d9 d! r' Z* F+ U% b5 T
  536. static uint8_t find_nearest_color(rbt_dec_context *rbt, int r, int g, int b)
    & y4 h) J& Q- q1 s: j, |, o
  537. {' Y' e0 T2 {# w
  538.     int i;. O: i/ A+ \1 ?5 t, }
  539.     int nearest_distance;
    * z  V7 x# U+ P- P* {; S4 J& y6 T0 H8 f
  540.     int distance;7 m' }8 R2 K  q. y* H
  541.     int rp;
    - o. j, i% o6 W5 S2 a) r
  542.     int gp;! y/ L) E; {/ {; h/ I( K& V
  543.     int bp;; H8 ^. r* w  ~/ m" \# B
  544.     uint8_t palette_index;
    + O2 F& w7 H! Z+ m/ c! F/ J

  545. ' V2 T4 F* ]5 B& s. |
  546.     nearest_distance = 999999999;4 V1 ~3 ^; M" M: C4 @
  547.     palette_index = 0;
    & f# F& `$ R. H) r7 p1 ~, t6 L/ m
  548.     for (i = 0; i < 256; i++)
    ; h0 q' f% c( _& p* {
  549.     {$ F/ b' t5 O( Y
  550.         rp = rbt->palette[i * 3 + 0];
    % c5 T4 u4 s% M& y
  551.         gp = rbt->palette[i * 3 + 1];% L4 d) d: p" v. `( Q" j
  552.         bp = rbt->palette[i * 3 + 2];
    + v# r  F( P! q2 a8 u
  553.         distance = compute_rgb_distance(r, rp, g, gp, b, bp);
    6 ~* v2 q1 @3 e$ W, b5 I, B# {
  554.         if (distance < nearest_distance)/ \0 e0 ?3 V* q: l" e
  555.         {+ l7 c% n* G2 `: u/ J
  556.             nearest_distance = distance;! l- w5 x" u# p4 @* K
  557.             palette_index = i;
    6 q) h6 u4 ]5 ^
  558.         }: E$ z$ w/ p  y5 p' M8 b2 j
  559.         /* can't get closer than 0; break early */% b& o% M3 B! h' i2 N
  560.         if (distance == 0)0 O$ c6 \* o' _1 l6 k
  561.             break;: p$ \7 Z% F* S" p
  562.     }
    9 S. @6 m/ h3 z; K$ ?$ U' J
  563. / Z7 W9 F; a" v
  564.     return palette_index;
    " `) H( T% _- I
  565. }
    ) ?" o) F+ t  k% s* p, |6 k5 b* K* u7 R

  566. ' G) f6 U% C* J, k
  567. static void subtitle_frame(rbt_dec_context *rbt, uint8_t *frame,& d) _' ?7 `1 N5 c2 e8 b3 `
  568.     int width, int height, int timestamp)
    7 m7 p9 L3 ~4 H. D3 b6 [' P& O1 s! y  v
  569. {
    0 E3 J8 U! c4 }; \' a$ f
  570.     ASS_Image *subtitles;
    ( j# C# Z1 i  E
  571.     int detect_change;
    , P4 L" F* E; u7 O1 j5 B
  572.     uint8_t subtitle_pixel;
    ! e3 h% T' O; G+ p) a
  573.     int x, y;
    ! Q; p! ]2 S( t0 ~9 Z5 i( Q
  574.     uint8_t *frame_ptr;
    ( @9 v/ G( R' ~% x+ J9 d/ o! f# @
  575.     uint8_t *subtitle_ptr;' X$ Y) ~- o$ z7 N2 K
  576. 8 h7 t0 u* Q: V8 N& @
  577.     /* ask library for the subtitle for this timestamp */# t9 ~( Y+ v& h
  578.     subtitles = ass_render_frame(rbt->ass_renderer, rbt->ass_track,
    & O) e( `1 j3 F4 Z/ a
  579.         timestamp, &detect_change);
    ' H' X% i0 j8 L, x4 a
  580. $ b) X  W/ n* k: r7 K; z$ U
  581.     /* render the list of subtitles onto the decoded frame */& i! w# Z% K  ?
  582.     while (subtitles)
    ( ?4 H. c$ x$ m) Z8 Z% N
  583.     {
    ' J2 u* I% b+ \( W
  584.         /* palette components are only 6 bits, so shift an extra 2
    0 l' P3 c5 I1 p$ b' a8 A# \- w
  585.          * bits off each component */, v8 y6 c  W9 y& \% b
  586.         subtitle_pixel = find_nearest_color(rbt,
    ! w3 h" P$ P1 D& `+ ]
  587.             (subtitles->color >> 10) & 0xFF,
    8 `7 ^) \/ ?: [" R2 }
  588.             (subtitles->color >> 18) & 0xFF,% b* A$ q% X8 H
  589.             (subtitles->color >> 26) & 0xFF);
    % o$ x5 p/ Y' e1 G) s
  590.         for (y = 0; y < subtitles->h; y++)% w7 ~, q% J: l4 U' i
  591.         {6 Z- S% a$ L* l6 ~/ G
  592.             subtitle_ptr = &subtitles->bitmap[y * subtitles->stride];9 N8 h& `' m! {, T3 k
  593.             frame_ptr = &frame[(subtitles->dst_y + y) * width + subtitles->dst_x];" W2 p5 w+ g/ F5 @# h
  594.             for (x = 0; x < subtitles->w; x++, frame_ptr++, subtitle_ptr++)
    % }* W% }; I8 r) W2 M8 [
  595.             {
    % I  P9 F* Y  R3 s& e9 m
  596.                 if (*subtitle_ptr >= SUBTITLE_THRESHOLD)- F* w& @; h% w) e" a
  597.                     *frame_ptr = subtitle_pixel;' n: n' K2 x0 C9 J8 a) H( @
  598.             }
    8 U( T' ]2 d; E
  599.         }$ x- l* N. z+ k' \1 p. E$ }
  600.         subtitles = subtitles->next;
    * ~" m5 \; K6 U5 m- g1 S
  601.     }, V: _2 a" i* `9 J* X
  602. }
    2 m5 y* L, D) g- K) r2 l; m
  603. " I0 x. I; d* t: y8 J
  604. static int copy_frames(rbt_dec_context *rbt, FILE *inrbt_file, FILE *outrbt_file,
    ; D' [4 j& ~8 U1 ~5 n: V
  605.     int origin_x, int origin_y, int window_width, int window_height)
    : `* X9 X" P5 Z' o. q4 x) r
  606. {
    * |; C8 r6 c" h1 @: \+ D7 d7 k) A
  607.     int i;) @. I9 i& l% F' l# g+ o8 f
  608.     int j;
    8 a0 |" @& o- J6 y: h; `3 t6 ?
  609.     int scale;
    * j- E1 v8 Z( {+ u5 J) b7 R
  610.     int width;
    , `$ _) A+ J- f- @$ M9 _5 l, p$ |
  611.     int height;
      Q! r& p8 w. C1 \+ \2 K
  612.     int max_width;
    4 G& N% o( N& S, V) s, R; z/ I" W1 \
  613.     int max_height;
    9 x3 W8 Y0 g3 Z" |2 W
  614.     int frame_x;0 {5 [0 M/ x  G9 t' q
  615.     int frame_y;% R& ~3 B9 e* d/ j" |& Z
  616.     int fragment_count;3 J3 U$ Q% a. \! R1 v& m; Y
  617.     int decoded_size;9 X7 z& N: V* O' b# v) n: A7 o% m- G
  618.     uint8_t *decoded_frame;1 n) y- E, q# e6 \7 z
  619.     int fragment;
    5 M& T) F; \1 w# }4 R  a
  620.     int fragment_compressed_size;
    . _" e% Z: U7 Y& w3 ~: c2 b/ V: i
  621.     int fragment_decompressed_size;1 l: _# K$ U- n% g: C! B$ ]
  622.     int compression_type;" B* g0 O* [' `; I
  623.     int index;( }5 u0 [6 H. u
  624.     int out_index;
    0 @8 [+ [& p; y) B+ I$ x
  625.     get_bits_context gb;
    4 a1 F0 ~  w+ N( K' R0 `" y) r
  626.     int frame_size;
    ! F2 V8 K7 ^+ a3 l  r, S0 S# I
  627.     int video_frame_size;) p6 [' T7 z% O1 d3 j* u
  628.     int audio_frame_size;
    & b) L: A3 g9 B# @2 ^8 }4 Z7 W

  629. / {6 K. l* t) Y6 \% U. N
  630.     int back_ref_offset_type;; K- t! X1 t! k5 l& w7 e  }8 ^2 z; _
  631.     int back_ref_offset;
    ) \6 w! {( t& G9 l0 h
  632.     int back_ref_length;
    3 M8 l" E3 ?- W9 R3 M
  633.     int back_ref_start;& T, T4 c9 A% y& R0 P4 q
  634.     int back_ref_end;. U  W* ?' ^4 C+ Q& b" u5 i% w
  635. 5 `, o* h5 o0 }# l& {
  636.     uint8_t *full_window;6 U0 b4 ^) Y9 g& K. H
  637.     int full_window_size;
    4 l, C0 X2 v# L0 t& S
  638.     int y;) v5 y5 p* z6 m9 l" k. @
  639.     int window_top;
    / A; z; \' b4 ^4 _4 v
  640.     int window_bottom;2 i$ f7 |& t, r. l1 V
  641.     int window_left;3 J& h! `1 O5 F, O. @' E
  642.     int window_right;
    " ?: `$ N% h" w5 X, X$ B) i
  643.     int window_size;9 A8 M! Y/ g6 n5 N# U  S
  644. : a2 s( T2 i4 e+ v8 Z6 t
  645.     char filename[30];  M/ r4 [& y( y7 l  c
  646. 2 c8 O$ c6 o6 C% N0 t
  647.     put_bits_context *pb;7 ]1 t) r& [+ ^$ i) y' K

  648. % A% `5 [/ D7 U
  649.     full_window_size = window_width * window_height;
    3 L6 o5 B7 I* {0 i) C
  650.     full_window = malloc(full_window_size);. |3 m; ^& j' n* h0 w1 H- c
  651.     pb = init_put_bits();
    6 I" A3 ]0 T& |- U
  652. 8 T8 `5 f( A8 m- h! \/ p# Q6 e
  653.     max_width = 0;& J: O) x- M; b' G( Z9 g& c
  654.     max_height = 0;( R9 ^- U5 W* m" m. A) |
  655. - k+ W1 m5 H) g4 m" t& ]
  656.     for (i = 0; i < rbt->frame_count; i++)6 }0 s: O" L8 m9 ]4 v) e. g5 I
  657.     {
    , b+ D, X. C) u1 L
  658.         /* read the entire frame (includes audio and video) */
    + L7 l6 {0 S6 R& q. x. q  d; x
  659.         frame_size = LE_16(&rbt->frame_size_table[i*2]);
    & Q- b! ]( ]) W- v7 G6 F4 K
  660.         video_frame_size = LE_16(&rbt->video_frame_size_table[i*2]);
    & C7 Z" E1 S! _/ S
  661.         audio_frame_size = frame_size - video_frame_size;" \3 Q6 T4 z- B( G1 I
  662.         if (fread(rbt->frame_load_buffer, frame_size, 1, inrbt_file) != 1)
    $ U8 I2 E' q$ d- Y, w
  663.         {
    6 W! @2 v3 Z' j) p, T0 p
  664.             printf("problem reading frame %d\n", i);( g* Q. F- s, `8 u
  665.             return 0;; L0 @8 s/ G/ r+ r# C8 @
  666.         }
    4 J* [! k( l& v5 |$ B: S6 d5 @

  667. ( Y8 p6 m8 ~( I  H
  668.         scale = rbt->frame_load_buffer[3];
    + \, M3 P; X5 a1 T
  669.         width = LE_16(&rbt->frame_load_buffer[4]);+ }, M& H7 Y7 M" k* S" U
  670.         if (max_width < width)' W5 F6 M. L2 o; B8 _
  671.             max_width = width;
    ) R  C) v$ B0 s' [$ h) {- m
  672.         if (max_height < height)2 t/ K4 L- m2 k" U
  673.             max_height = height;" ~3 F3 G5 t, o
  674.         height = LE_16(&rbt->frame_load_buffer[6]);" x9 a' }5 B; I$ Z  R" S3 R
  675.         frame_x = LE_16(&rbt->frame_load_buffer[12]);
    0 R* y3 e/ C2 `
  676.         frame_y = LE_16(&rbt->frame_load_buffer[14]);7 V! D$ m( i. m( A
  677.         fragment_count = LE_16(&rbt->frame_load_buffer[18]);6 Q) T0 L7 q1 A1 Q" k
  678.         decoded_size = width * height;
    & p3 {# W( c9 f+ c7 e$ O
  679. . K2 V$ m5 ^8 ^% F" k) F/ c# S/ T4 d" c
  680.         printf("processing frame %d: %d%%, %dx%d, origin @ (%d, %d), %d fragments\n", i, scale, width, height, frame_x, frame_y, fragment_count);
    8 B. a+ }) x+ c+ i( `

  681. 0 I9 I! B7 K% ~$ P6 I
  682.         /* decode the frame */7 j9 Z, X3 u; }& Q4 l
  683.         decoded_frame = malloc(decoded_size);# b) w# @+ F' F9 i2 o+ ~
  684.         index = 24;
    , M: O$ u/ [" c
  685.         out_index = 0;
    / h7 z( ]5 \- U
  686.         for (fragment = 0; fragment < fragment_count; fragment++)
    ; k/ w7 t. E% p7 F4 \7 P* K/ I
  687.         {0 |% U/ n1 W' p: M3 o4 `
  688.             fragment_compressed_size = LE_32(&rbt->frame_load_buffer[index]);
    3 c; j; U* n$ l" _; u
  689.             index += 4;
    / d8 ~4 f3 E4 K# E& j# S
  690.             fragment_decompressed_size = LE_32(&rbt->frame_load_buffer[index]);
    ! ]8 ^$ w/ Y6 H0 h' z! Z9 ?9 U4 g! i
  691.             index += 4;6 u! K" k$ j' S
  692.             compression_type = LE_16(&rbt->frame_load_buffer[index]);8 {: i4 k" N3 ?+ i" O2 s
  693.             index += 2;6 U3 {+ i8 ~5 p. u0 z0 r

  694. - S. g9 }& o' H+ b6 f( X/ t2 @% V
  695.             if (compression_type == 0)
    4 a* Y1 Q8 T" b) T
  696.             {
    8 o; ^. I7 M# X' ?* K
  697.                 init_get_bits(&gb, &rbt->frame_load_buffer[index],1 O6 A) f* S3 D; {
  698.                     fragment_compressed_size);
    4 t; g) ^3 `7 z, K, Q; S1 z, A

  699. , }* {/ |5 f( @3 d0 C/ W- ?! Y) ]7 {
  700.                 while (out_index < fragment_decompressed_size)6 u! B3 j+ w- O8 `
  701.                 {4 H; [6 c2 F7 J
  702.                     if (read_bits(&gb, 1))& ~0 C1 o" ?4 \8 w+ O/ d
  703.                     {
    $ T+ V/ y; U! g) v0 `; S( F
  704.                         /* decode back reference offset type */! n4 P* N+ n; \8 f
  705.                         back_ref_offset_type = read_bits(&gb, 1);
    7 Q: I8 e  F4 S! q9 p$ i

  706. # a" s3 Q5 L7 M# F8 d. ~4 T9 z  O
  707.                         /* back reference offset is 7 or 11 bits */, L' P% ^9 h2 Q* \( y6 g8 v
  708.                         back_ref_offset = read_bits(&gb,* _+ w4 X% J) q
  709.                             (back_ref_offset_type) ? 7 : 11);$ e4 y; B7 I, ^7 p
  710. " E1 V+ }1 }% C0 K: j) r: d
  711.                         /* get the length of the back reference */
    ' g) X" a: r( e. C* u- \  D
  712.                         back_ref_length = get_lzs_back_ref_length(&gb);
    $ `8 J3 k8 K2 B  i6 ~' z
  713.                         back_ref_start = out_index - back_ref_offset;3 O; Z& Q' K! {+ h! Z6 K
  714.                         back_ref_end = back_ref_start + back_ref_length;1 l9 h% A* z: ]

  715. 5 |2 b4 B* a! o2 W6 C# b
  716.                         /* copy the back reference, byte by byte */$ y$ ?( o; I2 O9 b* x
  717.                         for (j = back_ref_start; j < back_ref_end; j++)
    + R( A. Y: U1 x
  718.                             decoded_frame[out_index++] = decoded_frame[j];
    " s: {# p+ t9 w. F
  719.                     }( r: I) r+ e$ _6 N3 C, _' S
  720.                     else
    ) m* i0 Y1 }' f$ @
  721.                     {
    ) ?; a- F: U( d- E& i0 h1 F
  722.                         /* read raw pixel byte */
    8 g( O+ u9 y# s' M4 s
  723.                         decoded_frame[out_index++] = read_bits(&gb, 8) & 0xFF;
      i  \7 F  |2 u
  724.                     }
    # L* z0 p9 ?, l7 {- n! b
  725.                 }+ |1 a3 ~! z" c, ?
  726. 4 M5 L1 @) E( d' o4 S& }! v) @
  727.                 delete_get_bits(&gb);
    8 y- A4 ]$ w3 I/ D* T
  728.             }
    9 C/ {3 M7 d; o) Y

  729. 8 q, {8 l6 [- m3 {" Q! p0 j
  730.             /* next fragment */
    0 K  B8 C2 t8 s
  731.             index += fragment_compressed_size;' @# m0 a7 {* z, }* q
  732.         }
    ( k) s' ~9 ~. i/ \1 w6 c9 O
  733. - F) X4 l- ~3 s" J
  734.         if (rbt->dump_frames)
    " p" F( u4 O0 W+ ?% N* t
  735.         {2 H% v/ X  ]2 |5 j4 c8 _% V# C
  736.             /* dump the original frame */, @7 W* l: T- b' T( |1 ?
  737.             sprintf(filename, "original-frame-%03d.pnm", i);  K/ t# S5 n! C4 r1 a
  738.             dump_pnm_file(filename, rbt, decoded_frame, width, height);% Y+ x/ f: Z% I; r/ {
  739.         }
    % x, k$ `5 X0 P; P: |

  740. , y* W5 t* _6 O- z1 ~. T$ J
  741.         /* transfer the image onto the frame window */$ m( ~: a8 R$ C0 @6 |" k# w
  742.         memset(full_window, 0xFF, full_window_size);
    . k; d1 [' n( ~4 q  y( x4 K$ G& v
  743.         index = 0;7 R1 x4 \* l4 p% X! i4 `
  744.         for (y = 0; y < height; y++)- \4 `) \8 Z1 B; v/ ~- m
  745.         {& h5 }# S, ^5 m2 Z! m$ X2 L
  746.             out_index = window_width * (frame_y + y) + frame_x;! U) D6 n. S: o9 n' j1 b1 w+ Q: `
  747.             memcpy(&full_window[out_index], &decoded_frame[index], width);6 q% F" B, `$ ~7 s2 G, N  m' \' C
  748.             index += width;
    ( [7 Y' o0 h! x2 \
  749.         }
    . p1 W2 o1 u; ~/ j% }# v

  750. 8 Y! ?& ^- t" L9 {
  751.         /* write the subtitle */. a( \6 ~: U7 V! n! F, d& j
  752.         subtitle_frame(rbt, full_window, window_width, window_height,. f7 j! J( m6 t+ k# ^
  753.             i * MILLISECONDS_PER_FRAME);+ t7 l7 T$ N6 P$ \9 e; ~
  754. 4 M% `8 ?" L0 H
  755.         /* figure out the smallest change window */
    ; z  U4 S, {6 @  r
  756.         window_top = frame_y;
    2 k. @3 j; [9 q: p1 Y: h
  757.         window_bottom = window_height;
    4 X9 T! w1 k( U
  758.         window_left = 0;. B) }, S6 I9 i8 S  d/ `, h. Y
  759.         window_right = window_width;
    # f# F9 r/ V4 H, D5 |
  760.         window_size = (window_right - window_left) * (window_bottom - window_top);
    % V0 |# i7 ~" s
  761. 2 {7 v; w' _( i: d$ E7 P
  762.         /* compress the frame */
    / j, ]% Q* K4 I) C
  763.         reset_put_bits(pb);0 S6 m: ^2 U' c/ ~  C/ u, f' O7 P
  764.         compress_window(pb, full_window, window_width, window_top,1 i$ W! M! l5 a; q5 W
  765.             window_bottom, window_left, window_right);
    2 [/ h0 G% |" m+ ]0 y8 y& P

  766. * k  S' c$ a" p2 ~8 D
  767.         if (rbt->dump_frames)
      ^* ?! C  X/ k0 l7 d# X+ _
  768.         {1 @3 ^  s! Q, S2 S; W4 t
  769.             /* dump the frame plotted onto the full window prior to encoding,6 P2 g! o( o' P, e
  770.              * with subtitle */
    6 f" V# ^% \! Q/ b" _# M
  771.             sprintf(filename, "pre-encoding-frame-%03d.pnm", i);: ^2 N( `1 R$ x) ]) Z$ @
  772.             dump_pnm_file(filename, rbt, full_window, window_width, window_height);
    9 H' G7 y5 m, |, \  g# c
  773.         }2 P0 V  d, Q6 P* z5 G  e& a* y
  774. 3 Q+ N& r: t% A% w8 ^! E) E
  775.         free(decoded_frame);8 h/ v2 V0 t+ D$ l

  776. , F, P( ?/ X: a8 @+ h+ M, |
  777.         /* update the frame header */
    , t: H) |2 A" p6 T1 r% ]& Y
  778.         /* width */( n# d% o/ J# C. G. I
  779.         rbt->frame_load_buffer[4] = (window_right - window_left) & 0xFF;
    8 `# V) P: J$ ^" n. J7 ^
  780.         rbt->frame_load_buffer[5] = (window_right - window_left) >> 8;
    * X& l- q- S* ~
  781.         /* height */
    ! h0 ?. F% N2 ]
  782.         rbt->frame_load_buffer[6] = (window_bottom - window_top) & 0xFF;; J( B. L, {( u: g; e6 m# @
  783.         rbt->frame_load_buffer[7] = (window_bottom - window_top) >> 8;
    " G+ P1 v: P" \. D
  784.         /* origin X */( ^3 s2 D. J6 Q) v7 K# r) j
  785.         rbt->frame_load_buffer[12] = window_left & 0xFF;
    4 p) Z5 h( l4 }0 t3 ^2 Q
  786.         rbt->frame_load_buffer[13] = window_left >> 8;9 f. ~( c) ~# ?$ C+ ^; u( c
  787.         /* origin Y */& ?  S/ a% }% q! j3 N# U
  788.         rbt->frame_load_buffer[14] = window_top & 0xFF;: y4 K9 z7 e* _
  789.         rbt->frame_load_buffer[15] = window_top >> 8;2 b6 M0 I2 ?5 u& {: v. F
  790.         /* fragment payload size */+ c- P3 ~% L' X* z, w
  791.         rbt->frame_load_buffer[16] = (pb->byte_index + 10) & 0xFF;
    8 R3 L* S- e# a
  792.         rbt->frame_load_buffer[17] = (pb->byte_index + 10) >> 8;
    ! E! {$ v' f2 V6 q7 K
  793.         /* fragment count (1) */
    & i, ^8 c! y. ]6 I0 {0 F( I! s
  794.         rbt->frame_load_buffer[18] = 1;
    ( w, c4 v& T% k; a1 @
  795.         rbt->frame_load_buffer[19] = 0;% E) Z7 M, s% r& P
  796. % X. E$ w2 q& R- Z
  797.         /* update the fragment header */
    % [  Q* [- J% y. Y# x
  798.         /* compressed size */  }: z. o2 Y' G9 @; g8 ]7 f
  799.         rbt->frame_load_buffer[24 + 0] = (pb->byte_index >>  0) & 0xFF;. y: E9 {, x. |0 m
  800.         rbt->frame_load_buffer[24 + 1] = (pb->byte_index >>  8) & 0xFF;/ [" D! I$ z, V7 H! Q6 W
  801.         rbt->frame_load_buffer[24 + 2] = (pb->byte_index >> 16) & 0xFF;
    ! _: g0 t; t% m6 a0 _% a0 I
  802.         rbt->frame_load_buffer[24 + 3] = (pb->byte_index >> 24) & 0xFF;7 W3 `5 {1 j4 {) w7 T/ R: G
  803.         /* decompressed size */, J( h& b( C5 Z. ~
  804.         rbt->frame_load_buffer[24 + 4] = (window_size >>  0) & 0xFF;
    * V. V3 E  M* j' f
  805.         rbt->frame_load_buffer[24 + 5] = (window_size >>  8) & 0xFF;
    5 N; I! r/ I/ z% v9 Q8 U" j$ B
  806.         rbt->frame_load_buffer[24 + 6] = (window_size >> 16) & 0xFF;
    + |6 }+ q( Q: g- H6 }0 c
  807.         rbt->frame_load_buffer[24 + 7] = (window_size >> 24) & 0xFF;
    - E" a0 j. S4 K$ G% z. Z% O  d' Y
  808.         /* compression format 0 */
    % q+ Y+ C; t' b: ^5 N- b
  809.         rbt->frame_load_buffer[24 + 8] = 0;! ]# l0 W0 T! K  m
  810.         rbt->frame_load_buffer[24 + 9] = 0;$ D9 d' e7 q/ ^$ w9 ?0 K  _
  811. 8 f, i- g1 c! E! y- b8 s0 e
  812.         /* write the 24-byte frame header and the 10-byte fragment header */# p* ~  a8 Y$ q& E& Q( N* f
  813.         if (fwrite(rbt->frame_load_buffer, 24 + 10, 1, outrbt_file) != 1)4 ?# X- |* m, i3 Y1 A, R
  814.         {
    / n- c. A6 t( V1 T' e6 d/ d
  815.             printf("problem writing frame %d\n", i);3 o- ]$ f7 J) g+ `. E
  816.             return 0;
    . G0 z  G" M5 w3 a
  817.         }1 P6 m2 C. E; T+ ~* Y6 Z( `5 D
  818. 6 z/ C" b4 @) ^" F
  819.         /* write the new compressed frame data */3 G$ U, y. u# @! [& A$ }
  820.         if (fwrite(pb->bytes, pb->byte_index, 1, outrbt_file) != 1)
    ; s) A9 e' E" J* i
  821.         {5 @9 W# L6 M* i- N/ J6 F
  822.             printf("problem writing frame %d\n", i);
    ( Y* |4 j7 [4 k$ Y4 S
  823.             return 0;
    ) q$ Z: k' d/ O, M
  824.         }
    + c. y' @, m( e; q7 M6 x

  825. & G. k2 p9 H+ G# _: w- l& B* P
  826.         /* write the audio data */
    + T3 ^) V$ l5 `4 T
  827.         if (fwrite(&rbt->frame_load_buffer[video_frame_size], frame_size - video_frame_size, 1, outrbt_file) != 1)
    8 x  n3 e5 b: F. E! p( s
  828.         {
    - v' U% p) ?5 p% f8 ]
  829.             printf("problem writing frame %d\n", i);
    5 o% J& T: a; _! T* g
  830.             return 0;4 q$ l' z# T* c" y- H
  831.         }2 ]1 c3 S: H0 h9 t: D

  832. $ K" s, ]/ j" n. B# A% B2 i
  833.         /* update the table entries */
    ' m& d! a" \0 k; M9 V0 H! a
  834.         video_frame_size = pb->byte_index + 24 + 10;, y8 r" H# z5 T8 Q
  835.         frame_size = video_frame_size + audio_frame_size;
    ! {2 o* P. q% U: L+ S% q
  836.         rbt->frame_size_table[i*2+0] = frame_size & 0xFF;
    4 C, Y* o. G6 k" g- i% |2 }
  837.         rbt->frame_size_table[i*2+1] = frame_size >> 8;
    ! C6 o$ v4 e$ N' A) G+ G/ @  D
  838.         rbt->video_frame_size_table[i*2+0] = video_frame_size & 0xFF;
    " i- w. e( \) b6 {5 y( G5 O' l' k  W0 z
  839.         rbt->video_frame_size_table[i*2+1] = video_frame_size >> 8;
    " a$ m, ]" d& p4 f' `, p& t# K
  840.     }
    % j5 [+ @0 X3 c+ J8 H9 k, T
  841. 5 b5 y; d" o% W
  842.     printf("maximum dimensions seen are %dx%d\n", max_width, max_height);2 {9 }0 \, [! v6 l+ t

  843. 8 ~% N' u' x- S; S8 `$ s
  844.     delete_put_bits(pb);% E* C9 L! x% x# B; Q
  845.     free(full_window);4 Y3 K2 H/ F4 c6 W; v  }
  846. ) ]* G0 p5 ]6 B( O
  847.     return 1;
    # M6 S* U+ Y- B
  848. }
    3 h5 E' m  W0 ]* {

  849. ; H$ r, Y' o& b( E2 S
  850. int main(int argc, char *argv[])
    2 q& U+ E. M& D8 \# y
  851. {
    * V: p  r4 k2 y' m9 c5 u0 U
  852.     char *subtitle_filename;
    & o$ Q- I8 p0 n5 Y$ @9 b+ `
  853.     FILE *subtitle_file;& y" J5 H1 D, n
  854.     char *inrbt_filename;
    # j/ w+ z0 N/ T9 n& R
  855.     FILE *inrbt_file;% q3 d8 W, ^. |% W1 A. q
  856.     char *outrbt_filename;
    # O; x7 ?: w: c7 w- v/ o3 w
  857.     FILE *outrbt_file;
    * x# N4 u5 K8 x: W
  858.     rbt_dec_context rbt;& x3 X1 D5 T6 y' \$ C
  859.     int origin_x;
    7 e; j- M  F. v! L7 Q" I
  860.     int origin_y;: x" c* n$ _8 R9 T4 x3 Y
  861.     int window_width;& S8 M. a! m+ \7 B$ W  b$ ]
  862.     int window_height;
    " L6 Q' h# v& }9 q4 Z
  863. 5 K3 K9 W  y* ~" p% y4 {/ D
  864.     /* testing the bit functions */
    ) [- {, R, `4 L3 `2 T  U
  865. #if 01 d: K# k, c! \1 U8 u
  866.     int i;
    1 v1 ^! n  e0 y- |
  867.     uint8_t bytestream[] = { 0x55, 0xAA, 0x00, 0xAA, 0x55, 0x77, 0xFF, 0x1B, 0x70, 0x8F };
    ) Z! H$ b8 ?6 v" t. a  ]# U5 }; V- o
  868.     int bytestream_size = 10;
    % H. c- h" i+ |' J, d, [
  869.     get_bits_context gb;
    # R& V- ~3 m( S2 U6 v
  870.     put_bits_context *pb;0 @+ X& h0 U5 V" u2 ^0 @% X
  871.     int bits;
    - L# r: M1 d1 I" U3 p& ]& Y; c

  872. 1 X5 L; K2 l4 Q/ j/ i) l
  873.     init_get_bits(&gb, bytestream, bytestream_size);
    8 Y6 T, j- n- B! J5 e
  874.     pb = init_put_bits();
    5 L" X. M: j+ X

  875. 4 G" p; M5 c! g9 i
  876.     for (i = 1; i <= 12; i++)6 R: _2 H8 H' z% p2 d. Y
  877.     {
    # A- e8 A, ?  {, S
  878.         bits = view_bits(&gb, i);! P) a* J% Y. e0 R) S' M- \9 P
  879.         printf("view %d bits: %d\n", i, bits);
    7 a7 x5 \- M# d5 k& ~8 l
  880.         printf("read %d bits: %d\n", i, read_bits(&gb, i));, M% a( S: t: r4 t7 ~/ W
  881.         put_bits(pb, bits, i);
    0 N" j# Y( J6 }
  882.     }
    ( t0 H) [' L" i8 y/ E0 I! ?1 P
  883.     put_bits_flush(pb);0 [' b) e, n, L. F& w! @
  884. * j& L& x9 ]- d+ e/ E
  885.     printf("original bytestream:\n");- T( _0 a5 i3 `8 j! y4 y: P* O. g
  886.     for (i = 0; i < bytestream_size; i++)
    , p. v$ h9 E. u; f8 M5 H
  887.         printf(" %02X", bytestream[i]);! T* X' f; x9 w  f. Z% J3 k
  888.     printf("\nnewbytestream:\n");8 S6 Z" p0 M; b, f3 W" Y
  889.     for (i = 0; i < pb->byte_index; i++)' L8 h7 [" z  u" T. [. }
  890.         printf(" %02X", pb->bytes[i]);
    6 y, y# T3 x$ `' p1 }' u
  891.     printf("\n");8 e! Y( D! p; y( j" e; U$ q+ ^& A0 S
  892. 7 k: G, B) \. V# z2 _% `
  893.     delete_get_bits(&gb);! d- Y6 ~: }- q& f" a. L) Z9 v0 h
  894.     free(pb);
    - E# H- \9 E; D1 v, I# ~$ w) z! x: a
  895. #endif) i9 |! K7 x  k  u: m0 @) }# N

  896. 1 F; A7 S9 v# m2 Y& `7 W8 z
  897.     /* validate the number of arguments */
    0 \2 k5 J9 e: v- j- o& Z* Z
  898.     if (argc != 8 && argc != 9)% a6 L) ]  c" g9 k
  899.     {
    # W- w$ n+ `2 U8 E* i
  900.         printf("USAGE: subtitle-rbt <subtitles.ass> <in.rbt> <out.rbt> <origin X> <origin Y> <width> <height> [dump_frames]\n");
    / X7 R1 ?4 s+ C, [2 ]
  901.         return 1;) y0 E. w9 @( ]+ N4 p4 X# U6 v6 ~
  902.     }8 A7 z( B9 X1 @% D3 `
  903.     subtitle_filename = argv[1];
    - o% w3 ^1 A) y9 v9 p& l
  904.     inrbt_filename = argv[2];& _1 E" u! l# V0 N; M: ^, M
  905.     outrbt_filename = argv[3];. ]4 q7 w0 c8 q% W# b/ m
  906.     origin_x = atoi(argv[4]);1 ]' W' Y( l7 ^8 Q
  907.     origin_y = atoi(argv[5]);
    ' Q9 w2 @9 p3 |+ m+ s6 d
  908.     window_width = atoi(argv[6]);
    7 e, r5 H0 ~8 b8 n+ U5 @3 j, z
  909.     window_height = atoi(argv[7]);( A1 d. P$ ~. E3 ], Y1 P% o
  910.     rbt.dump_frames = 0;
    + h' ?/ l0 o) Y0 v. _4 P
  911.     if (argc == 9)
    ( u8 D- Q& g/ H) v- p
  912.         rbt.dump_frames = 1;- u' g' D) o5 y$ M
  913. 8 z) T/ Y2 G. y* ~7 F% Y- \
  914.     /* verify that the specified input files are valid */" h9 |+ [/ @/ u8 E* a" b
  915.     subtitle_file = fopen(subtitle_filename, "r");
    ! I- r' e% [. m3 S
  916.     if (!subtitle_file)) X: Z2 D2 C+ r9 S, T
  917.     {
    ) K, z4 r7 S% h" q2 @
  918.         perror(subtitle_filename);3 C: K! _$ J6 a$ k8 e3 E- q
  919.         return 1;+ c& S# d: V* G9 `0 l
  920.     }
    ) X$ K" J: H' ~, H4 o
  921.     fclose(subtitle_file);. }: b' C6 [9 n  O" ~/ q7 Q
  922.     inrbt_file = fopen(inrbt_filename, "rb");6 u, u- s2 `/ P8 [& q
  923.     if (!inrbt_file)
    " k0 m. O, ?$ Y
  924.     {4 ?8 V3 ^2 Z) F
  925.         perror(inrbt_filename);4 Q) R4 C) U, P- \& K! j- z2 o( ^
  926.         return 1;- e& x  o% V& }/ m2 W2 N
  927.     }
    8 x9 b0 x" y3 o' ?

  928. ) U+ U* m0 {' e8 s4 g
  929.     /* initialize the subtitle support *// s- q" R- }; q' h0 L
  930.     rbt.ass_lib = ass_library_init();
    " ~5 k! I9 s; H! {2 D0 K" F9 p
  931.     rbt.ass_renderer = ass_renderer_init(rbt.ass_lib);
    2 p+ S* a; ]: B0 h2 G4 f
  932.     rbt.ass_track = ass_read_file(rbt.ass_lib, subtitle_filename, "UTF-8");$ E" l# A% Z. g* `" M! o& c
  933.     ass_set_frame_size(rbt.ass_renderer, window_width, window_height);
    9 m4 h4 n* M' b9 F! j* A; E- V4 k
  934.     ass_set_fonts(rbt.ass_renderer, NULL, NULL, 1, NULL, 1);
    & b- g$ S+ T+ @. s
  935. % Z. y& f4 W4 e. B
  936.     /* open the output file */
    ; r4 i, x# g8 z+ O
  937.     outrbt_file = fopen(outrbt_filename, "wb");
    $ I0 A+ l9 f* \3 o$ m
  938.     if (!outrbt_file)
    2 D, h; s/ y- D8 s9 S# a; w0 V9 o" l
  939.     {
    2 _$ c6 ^$ H0 ^
  940.         perror(outrbt_filename);' L/ @0 E: W8 {& e$ |. D
  941.         return 1;, F8 ?  o7 L0 f
  942.     }$ E3 K' A% L1 G( Y' {/ F3 M8 h

  943. ' a( m' p0 _: P' v
  944.     /* transfer header from input to output */9 j8 }$ |; [4 u, `( e2 s8 G; f  H
  945.     if (!load_and_copy_rbt_header(&rbt, inrbt_file, outrbt_file))/ |1 p  e8 G% P7 Q( f
  946.         return 1;
    6 O2 T8 T/ i* S0 C7 J9 e
  947. 0 U- I2 X9 @6 ^8 y
  948.     /* rewrite the frames */0 R2 Z5 k8 f# n- M  Z
  949.     if (!copy_frames(&rbt, inrbt_file, outrbt_file, origin_x, origin_y,
    - p' i/ E0 B! y$ D4 m
  950.         window_width, window_height))
    2 k! F2 l6 w- D- e: z
  951.         return 1;
    $ [& A8 p& J3 r: F2 m

  952. * w& z  V. L  @* Y" M6 S6 s4 p0 R
  953.     /* write the modified frame size tables back to the file */
    4 a, |  j* \8 H% ]% O0 F
  954.     fseek(outrbt_file, rbt.video_frame_size_table_offset, SEEK_SET);# z4 W' p9 q) R- h
  955.     fwrite(rbt.video_frame_size_table, rbt.frame_count * sizeof(uint16_t), 1, outrbt_file);
    ! b- q4 k& Z& Z/ E# G. q
  956.     fseek(outrbt_file, rbt.frame_size_table_offset, SEEK_SET);; H4 o( _" v( ?. }
  957.     fwrite(rbt.frame_size_table, rbt.frame_count * sizeof(uint16_t), 1, outrbt_file);
    8 p) Z$ a% i2 [. A9 G# U6 \0 F
  958. ) D- N/ L! m% g* I% @
  959.     /* finished with files */: _$ i" w. _) t- v' o( T
  960.     fclose(inrbt_file);
    ( _1 V4 N9 j5 C) _" P2 L- m
  961.     fclose(outrbt_file);
    9 V' o& i5 _( f+ |# L! \
  962. * D5 C6 n  L1 d# @3 O$ S
  963.     /* clean up subtitle library */# _: {) [0 m! D( s* x2 r: e8 X
  964.     ass_free_track(rbt.ass_track);
    & k  o5 a# J* U. x2 s0 F
  965.     ass_renderer_done(rbt.ass_renderer);
    6 n4 _( p4 @, k/ ~0 B/ L
  966.     ass_library_done(rbt.ass_lib);" D7 Z/ s; x+ R8 `$ n# W' ?
  967. % ^& J; V: \- Q6 U: y+ B+ c0 T/ s
  968.     /* clean up */, q+ R4 m+ u/ k/ k5 |9 g
  969.     free(rbt.frame_load_buffer);
    / G" I( l0 a0 A1 @7 y, \
  970.     free(rbt.video_frame_size_table);
    ) s8 }% M+ B% V. F% W
  971.     free(rbt.frame_size_table);6 V, ]! ?; A% c) S

  972. ) L) B0 f  Y0 K
  973.     return 0;
    5 ^1 h. L3 J% C- A
  974. }
复制代码
. M; y- f- a! N- @

* k! m: R0 F5 w; y+ Y# B! s- w6 C8 x

5 |" q, h% q( v4 ^
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 很美好很美好 很差劲很差劲
回复

使用道具 举报

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

使用道具 举报

板凳
 楼主| 发表于 2009-11-19 11:38 | 只看该作者
引用第1楼soring123于2009-11-19 11:09发表的  :
& `! k: b3 l4 M  P8 }3 l) h% O这游戏有字幕吗?
- k$ h( E& p! W
好像没有字幕,我说的是给视频外挂字幕方式的汉化。" [/ ?0 x% Y) v3 E
就像syberia2汉化版下面那行字一样。
回复 支持 反对

使用道具 举报

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

使用道具 举报

5#
 楼主| 发表于 2009-11-19 17:39 | 只看该作者
引用第3楼soring123于2009-11-19 17:07发表的  :/ C; G9 }7 K$ {+ I6 u5 v2 y% u
我记得是没字幕的 比较麻烦 都是视频的

. E7 W& O3 q* L! s) r/ f$ v( `给视频外挂字幕方式汉化也许能行。( C& f8 p0 l, _
要结合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日,是全球华人共同的冒险解谜类游戏家园。我们致力于提供各类冒险游戏资讯供大家学习交流。本站所有资源均不用于商业用途。

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