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

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

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

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

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

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

本帖最后由 shane007 于 2021-1-2 13:56 编辑 ( L% ?/ D8 O. T4 S8 P2 t  C
% j; z' A2 \+ o% V+ j$ s: x9 b
最近找到了一些和幽魂系列Phantasmagoria 有关的资料,. J! o, d8 [0 B& j
也许将来可以用于汉化。- V2 `5 v. X( n( y* ^- y

/ e, k0 [  l4 f* y1 j和日文版有关的信息* j9 {$ _0 ?' X; `1 B9 }5 w
http://anthonylarme.tripod.com/phantas/phintgtp.html
) X, T4 |0 F( h- ]4 F  S7 u9 v5 z) t, _6 h2 C0 K, K
相关工具6 T. G5 D2 m/ z0 C0 [" \9 g
http://anthonylarme.tripod.com/phantas/phcheats.html
+ ]% `# Y2 R! H-----------------------------------------------------------------------
% A: W/ ]3 |: s9 @4 R( W2 F! F; g2012/1/2  更新1 K. c( f4 h. F& ^# ?# ?: T8 f8 ?
关于幽魂游戏的字幕$ L/ G; r! ~. ]+ X
Phantasmagoria subtitles function discovered - ScummVM :: Forums( a2 N* J7 C4 `& G. l/ R$ z0 q* U

7 m- u9 H/ g, P4 {VMD文件
  M; F7 w: k. M% c, d; lSubtitling Sierra VMD Files | Breaking Eggs And Making Omelettes (multimedia.cx)VMD - MultimediaWiki) {6 y2 l3 ~4 }1 G7 ^% }4 _( Q

- m1 t& O8 `) @" S字幕9 c2 m( P+ ]8 F' N8 F
Subtitling Sierra RBT Files | Breaking Eggs And Making Omelettes (multimedia.cx)* t# M- S5 L! ]% S/ x2 h

1 ]" \4 V  ^  |% F9 V3 NFFmpeg/subtitle-rbt.c at feature/VMD_encoder · multimediamike/FFmpeg · GitHub
8 h# m7 i5 o. F  z! D
  1. /*: G$ q. o; @  c" M; C8 V
  2. * subtitle-rbt.c
    1 ^3 G  N  M8 u( t! q4 x; ^
  3. *  by Mike Melanson (mike -at- multimedia.cx)
      ^1 o' ]3 {: r# T# |! r3 u
  4. *
    % g1 M) o/ M( s1 D
  5. * build with this command:
    / i( Y  ]0 Z' F  Y5 E) L$ i" g: O
  6. *   gcc -g -Wall subtitle-rbt.c -o subtitle-rbt -lm -lass* {2 M+ l5 R! {, o5 O8 t$ @. u
  7. */
    2 U& }( K  F/ s2 g4 Z8 x* L
  8. 9 T( Z7 e- d4 q" J
  9. #include <inttypes.h>
    4 a; Y) D+ H4 Y0 E5 v
  10. #include <math.h>; D) Z$ d' G+ ?8 @/ y+ Q# }
  11. #include <stdio.h>
    8 t( i1 N' L2 ?, J+ e
  12. #include <stdlib.h>
    : K* o8 L$ d0 U4 v- g2 }
  13. #include <string.h>5 h) E" M- t8 J2 o9 A) ]7 d

  14. 2 ]; H4 n8 m( c) I3 T0 i! ^; B& z+ s
  15. #include <ass/ass.h>
    ! N) m8 S& W$ t% P& M& Q5 M
  16. * D5 n  h+ L/ W6 l4 Y1 ^; r, S% D4 g
  17. #define LE_16(x) ((((uint8_t*)(x))[1] <<  8) | ((uint8_t*)(x))[0])% N/ Q' `7 f! q
  18. & S, `4 Z, F2 a% w
  19. #define LE_32(x) (((uint32_t)(((uint8_t*)(x))[3]) << 24) |  \! y' ]+ i1 w$ I
  20.                              (((uint8_t*)(x))[2]  << 16) |  \
    6 G8 v3 @7 @. @  J0 F2 R* B
  21.                              (((uint8_t*)(x))[1]  <<  8) |  \) Y+ c7 Y  U$ i: D
  22.                               ((uint8_t*)(x))[0])$ c; P0 `( L6 v

  23. . ]; z; R+ X7 N, m4 ]# y% e. O2 i
  24. /*********************************************************************/! j& d" ]7 q& F- J

  25. . A( N# w4 ~0 z" @; D
  26. /* Bit reader stuff */
    7 I8 I9 o  Z6 `+ F

  27. + |4 E- p& a* [& n
  28. typedef struct4 y, \+ Z% i1 G6 n2 r! m. O
  29. {6 O+ S& ]3 N% L
  30.     uint8_t *bytestream;* _4 T( g! |# n4 G) P
  31.     int bytestream_size;! ~0 o& c$ D/ L/ ?* b
  32.     int index;0 V* N( ~1 v- q4 L6 f9 f$ h
  33.     uint32_t bits;( Q1 r3 E* [1 G2 T5 w" |
  34.     int bits_in_buffer;$ ^, f' A" ^/ U& l- E1 N
  35. } get_bits_context;
    # @+ ?1 F1 i, y% r# r- A

  36. 7 f) V$ p) ?5 d, U& f
  37. static inline void reload_bits(get_bits_context *gb)
    ( ?5 S6 P" G9 w; x. C; ^
  38. {' Z. y7 S, A# z  W' n' L$ i
  39.     while (gb->bits_in_buffer <= 24)
    ) o% Y9 _  {! S
  40.     {) [6 z! q4 @7 H& a" S- S- R
  41.         if (gb->index < gb->bytestream_size)' g/ z& ^+ W3 E- m' ]3 f
  42.             gb->bits |= (gb->bytestream[gb->index++] << (24 - gb->bits_in_buffer));
    ( N6 z* A5 l; s
  43.         gb->bits_in_buffer += 8;4 \* |1 s2 X% c5 c
  44.     }
    ) o# ?: y! D4 z5 v- h
  45. }4 m0 z$ b) Z1 X3 I, u% E( ?
  46. 8 ?7 _$ I. r# @: b$ ^' L
  47. static void init_get_bits(get_bits_context *gb, uint8_t *bytestream, int size)
    # m  }9 S* T; v* m4 P8 h& k
  48. {
    ( V: E" a: j7 l8 I' z2 h$ X
  49.     gb->bytestream = malloc(size);
    , F' V+ O/ @9 \+ g& q* M" E
  50.     memcpy(gb->bytestream, bytestream, size);
    . ?8 j! H# j% |( q; S3 c; a/ [
  51.     gb->bytestream_size = size;* q& e9 |5 A/ O% a
  52.     gb->index = 0;$ H0 p$ q: }9 G: E/ |
  53.     gb->bits = 0;' _' u  R3 G3 O0 ?& C7 B: O' p! b
  54.     gb->bits_in_buffer = 0;% M1 U) v/ m. A7 x) P% E

  55. % P# D$ T8 [1 P' [$ i! E% S5 B
  56.     reload_bits(gb);3 @) h+ [/ S- O
  57. }
    / b  R# G+ g# t  y4 e! P
  58. * b# t8 u0 u) @* N7 ?$ P* f
  59. /* read bits without consuming them from the stream */
    ; ~0 {6 v  Q9 h) f6 h0 s" h$ r
  60. static int view_bits(get_bits_context *gb, int count), a* j5 A$ V, Z
  61. {
    1 J/ u, ]$ T/ p5 n) F% S3 C( o
  62.     if (count >= 24)
    2 W! @6 s7 o2 H4 d
  63.         return -1;
    $ q# |6 U& G) F8 \4 g
  64.     if (gb->bits_in_buffer < count)$ U3 u8 J, I) _$ M& V, M9 c2 ^
  65.         reload_bits(gb);& Q- j0 L0 R# f7 ~# N& [0 u$ X
  66.     return (gb->bits >> (32 - count));! n9 H6 D/ `/ w% ?
  67. }
    6 G* Q! g9 [; b- Q( j

  68. 2 W8 R: Y3 [% Q* {# Y. h$ A8 q" I
  69. /* read and consume bits from the stream */
      D0 `; D! x, f/ M. Z- i7 p
  70. static int read_bits(get_bits_context *gb, int count)
    2 q: S' c7 Y8 o7 N, _( w
  71. {
    ' a" f1 s* t$ E. N; z( T5 T/ @
  72.     int value;" c- ~4 G- k: G9 @. N( b
  73. 3 P+ ~+ ~9 ^: I4 w; Z" x3 S9 U
  74.     if (count >= 24)
    & w1 {  p" {0 f% ]
  75.         return -1;7 M9 y% G2 d, F# p1 r% T+ {" Q3 Q
  76. 0 D+ z. y/ D2 R7 o5 F# \% A
  77.     value = view_bits(gb, count);
    " C/ e$ V: l% g) k- W1 F- R$ l
  78.     gb->bits <<= count;+ |7 R8 e: u" ]0 S
  79.     gb->bits_in_buffer -= count;4 t' Y7 C0 H) [+ H8 m
  80. * F* K5 q) V/ o9 @# d* \
  81.     return value;4 H. X+ z! }  t4 r
  82. }7 g0 v4 L$ ^& Z  C  y4 W2 `

  83. # W; B- Y7 z- I7 c3 D; v
  84. static void delete_get_bits(get_bits_context *gb)- \7 V( [& v" {8 X  C
  85. {
    4 a& Q' _: I% t, I7 p4 S( i4 c
  86.     free(gb->bytestream);
    , c8 ^" O7 U- i6 N; M4 G2 I2 e
  87. }
    ! G: _! l2 J0 ?' v

  88. 7 `* ]( y- C- Z5 V  l1 d
  89. /*********************************************************************/- i2 B5 f* Q' O  G, z

  90. 1 G- u* S. C) _1 J1 W( n! a
  91. /* Bit writer stuff */
    9 m2 m& [1 a2 ~5 t

  92. / r( x6 \: l( {7 y" A
  93. #define MAX_PUT_BITS_BYTES 63000
    ) _# ]+ e4 b+ n: q/ H3 B' }
  94. typedef struct
    - m7 V/ m9 W, c# l! \
  95. {
    4 o. H( G( _% s) e  m
  96.     uint8_t bytes[MAX_PUT_BITS_BYTES];4 l$ W& `9 u7 v2 X9 `6 S
  97.     int byte_index;
    $ d' p* w2 J4 Y+ e
  98.     uint32_t bit_buffer;
    4 O0 _  V) I4 C9 O2 b( `0 X8 o5 w
  99.     int bits_buffered;
    5 [% P5 p7 d# S
  100. } put_bits_context;
    - p$ `: k% C: G/ v4 |
  101. 2 |+ {) T8 T7 {' h5 q+ D1 X; |
  102. static void reset_put_bits(put_bits_context *pb)* K* u3 }' O9 [7 M4 ^
  103. {) r. I5 g% k3 i; W6 `
  104.     memset(pb->bytes, 0, MAX_PUT_BITS_BYTES);
    # ?7 v4 H) B; d! O! }2 Y8 m# e
  105.     pb->byte_index = 0;& @8 V7 c% |5 v# a; Q1 ]6 C
  106.     pb->bit_buffer = 0;
    8 d# c" m8 p7 C, q5 E1 S) g$ D
  107.     pb->bits_buffered = 0;  S/ H$ }& L0 |  b2 C2 t
  108. }+ t: Z/ l0 c: Y! p: U) |5 p
  109. . i& Q- m" B  c) ~4 ?
  110. static put_bits_context *init_put_bits()( H+ }4 g, A3 q! V2 M* c/ G' L
  111. {
    . f  V0 n: H: K* y- K+ A8 R
  112.     put_bits_context *pb;
    , q' n0 a% M8 Z  Q7 c

  113. * v( v6 j8 V# a  O3 {" H; b
  114.     pb = malloc(sizeof(put_bits_context));
    8 j" j1 Z6 z/ X" K8 s) |. m7 k9 ]
  115.     reset_put_bits(pb);
    + P! A% R' C) r4 z% b5 y
  116. 0 X( ^$ Y; j- ]7 z
  117.     return pb;. N* n7 ?; L  H' z: A  y: v
  118. }& I* w* Y$ @7 u  R, F& D. n2 {

  119. 6 ~: d/ h7 D  r/ T, \
  120. static void put_bits(put_bits_context *pb, int bits, int count)
    ( |# T) a7 [& S. V6 ~9 Y
  121. {1 O6 B: C2 m8 [% b( f  n1 d& U
  122.     pb->bit_buffer <<= count;# W4 @. a2 l; p6 Z9 S. W7 V2 e) l
  123.     pb->bit_buffer |= (bits & (~(0xFFFFFFFF << count)));
    7 o3 ~2 s- s/ _. o$ M& Z
  124.     pb->bits_buffered += count;
    0 }" f  B3 S) N0 B5 R" _
  125. & N$ g4 j; X/ B& J: {, U5 w
  126.     while (pb->bits_buffered >= 8)
    * ~% r  a, ]7 Z/ E, e
  127.     {2 ^1 s. B, o* _8 Y
  128.         pb->bytes[pb->byte_index++] = pb->bit_buffer >> (pb->bits_buffered - 8);" n' q: e( D/ ?# U+ @5 m% R; E; x! M
  129.         pb->bit_buffer &= (~(0xFFFFFFFF << (pb->bits_buffered - 8)));( o+ @) k2 A% o1 T
  130.         pb->bits_buffered -= 8;
    5 ?& a# w( b! v8 X: V
  131.     }. z) H. W7 w. G& a3 P. E. J
  132. 8 ]& Z, K8 ^! P; r
  133.     if (pb->byte_index >= MAX_PUT_BITS_BYTES)0 B6 H" S! d2 i) a4 d8 s
  134.     {
    " w7 e/ y* ]& \4 F
  135.         printf("HELP! Bit overflow\n");4 w% M  T" Y9 G0 F+ X1 I+ I5 k! N
  136.         exit(1);
    8 S  S9 E8 ]4 a8 M- T
  137.     }8 O6 J7 [" J" ~+ X, H
  138. }
    ' {) q3 E. S0 e+ }0 b( v. f

  139. 7 k! L2 y' f' p, m0 [# ~
  140. static void put_bits_flush(put_bits_context *pb)
    % R& I- T# y  h) v+ l& G9 V
  141. {$ {8 n* T1 @0 Y' c* E
  142.     if (pb->bits_buffered > 0)0 _1 E/ y# Z  @4 D( Y
  143.         pb->bytes[pb->byte_index++] = pb->bit_buffer << (8 - pb->bits_buffered);; a) g2 P9 H) o, B# G
  144. }
    - R2 S6 l, [# p/ b, F: T4 O

  145. * ~$ r& H$ u* ~; a  b
  146. static void delete_put_bits(put_bits_context *pb)
    : Y" ?" Q( Z7 r7 ?
  147. {, J3 c. U" R" k. m% t. v
  148.     free(pb->bytes);2 c2 {2 R. O% b/ I9 F  P
  149. }3 K0 F$ J# A7 D
  150. / t# S. l& d) }; ]2 v2 W2 l
  151. /*********************************************************************/! f& i% t* n0 Q; E5 i

  152. 9 o) d2 x* f9 |  D+ e6 `) v
  153. /* RBT functions */
    1 Y' T: t/ h" d) S9 G; y  e3 n+ g) K& F

  154. % N7 F0 k+ e4 L* n2 g
  155. #define PALETTE_COUNT 256
    . T% y2 l$ o$ S+ e1 i
  156. #define RBT_HEADER_SIZE 60
    $ l2 y% a* l5 Q7 t
  157. #define UNKNOWN_TABLE_SIZE (1024+512)
    1 o& X! p0 a5 j; ~5 Z
  158. #define SUBTITLE_THRESHOLD 0x70
    $ K$ ~) Z/ R6 `5 q7 G( B1 K4 b. g
  159. #define MILLISECONDS_PER_FRAME 100
    1 |+ {) J0 \3 U$ V" Q0 E3 t5 C
  160. 8 x9 b) ~) T+ e* ]
  161. /* VLC table */; v& Q/ s& z4 Q& N  i- r) n
  162. #define VLC_SIZE 48 C% @3 i- E" r" f
  163. static struct
    $ L$ B: E7 h2 y) I
  164. {
    - Q9 {' J1 W3 m0 O
  165.     int count;
    7 O% `" e" r# v
  166.     int value;; A' J/ A& y' `/ I1 I$ `4 h
  167. } lzs_vlc_table[] =
    8 \8 H! P, ~" i; b- |
  168. {$ \& p' `3 s) M+ L" F# |9 `+ L
  169.     /* code length = 2 bits; value = 2 */& C3 m1 Z0 T, S8 q! [
  170.     /* 0000 */ { 2, 2 },; H+ T; i; a% ^+ j! l
  171.     /* 0001 */ { 2, 2 },
    - i" I$ r7 R4 `# U8 M
  172.     /* 0010 */ { 2, 2 },$ f" x( {+ R$ u# |
  173.     /* 0011 */ { 2, 2 },
    ( L& b8 |3 z9 U' h+ z" @
  174. . c+ G4 M: p1 K
  175.     /* code length = 2 bits; value = 3 */1 f9 f0 p* x/ C: S' n% |
  176.     /* 0100 */ { 2, 3 },
    % E5 l0 Y! L* `
  177.     /* 0101 */ { 2, 3 },
    - f3 o2 V- n4 `2 A5 s5 h4 E+ V
  178.     /* 0110 */ { 2, 3 },
    8 s; _6 a$ c5 {) b
  179.     /* 0111 */ { 2, 3 },# ?9 @, Y+ Q- U! m9 F

  180. + x2 {$ d/ o5 A
  181.     /* code length = 2 bits; value = 4 */
    ) g$ D  T9 T0 ^- _/ Q9 J
  182.     /* 1000 */ { 2, 4 },$ }& S% a. e- s+ K& B
  183.     /* 1001 */ { 2, 4 },( g, Z' @" ~3 O
  184.     /* 1010 */ { 2, 4 },/ ?! L, V* H$ q! T
  185.     /* 1011 */ { 2, 4 },3 U* O8 d3 G6 P2 M4 E

  186. 6 `+ j+ L5 d, W& [, W/ c6 F3 _, ]: C
  187.     /* code length = 4 bits; value = 5 */
    . b4 @/ @; d& q8 \5 c. U
  188.     /* 1100 */ { 4, 5 }," j! R7 n8 w5 [5 N' Y4 ~' v

  189. ; V1 J9 ^& @' o* j( h$ A; C6 y1 ^( s6 v
  190.     /* code length = 4 bits; value = 6 */
    ! w( S7 O- E. s+ e' F
  191.     /* 1101 */ { 4, 6 },6 t2 y# z  s' C, f4 i

  192. / ^# g. s2 [. d8 m1 n4 n
  193.     /* code length = 4 bits; value = 7 */
    . C+ X% O8 j: H! ?
  194.     /* 1110 */ { 4, 7 },9 i! d6 J1 j4 p( t- R# F4 v1 E' A

  195. & l' m8 F8 s# ^4 b) V
  196.     /* special case */! a; A# Y+ M$ P& d9 X8 i
  197.     /* 1111 */ { 4, 8 }
    * a' ]% A+ n+ e! L
  198. };
    ) f+ H8 C  Z" ~; o% M( q" m9 |9 [. x
  199. 4 A) J2 n) M$ |4 v, c% [. Q
  200. typedef struct
    8 z! S- m9 e/ R! r7 _# q
  201. {: d- w" b! g: d7 n; q  q
  202.     int version;
      a) F- h3 l! y3 W& ?, a
  203.     int width;7 R" M% C/ X+ I# X% Y
  204.     int height;
    , Z. l' c# p8 O- V5 M5 i# i7 w
  205.     int frame_count;
    ; H" X- ^3 T( i/ {+ V. y2 k
  206.     int audio_chunk_size;8 X! L6 e# H; {) E" ~$ \1 G5 ~9 x
  207.     uint8_t palette[PALETTE_COUNT * 3];
    ( l( b9 [/ q; Q1 }
  208.     off_t video_frame_size_table_offset;0 A, J" F0 {  z9 @# q
  209.     uint8_t *video_frame_size_table;
    0 @- Y3 W, y  I0 y: |3 ]
  210.     off_t frame_size_table_offset;: _1 }5 v6 }+ M  M2 ~
  211.     uint8_t *frame_size_table;  P3 V8 k6 a0 I' q7 d
  212.     uint8_t *frame_load_buffer;
    : A) Y: T, K% i
  213.     int dump_frames;9 `4 f) `' ^) y+ U

  214. ! ], \' o( Y8 P) [$ o7 e3 o' [/ g; F
  215.     /* subtitle library */
    ! [9 M3 {; r6 h) q3 `
  216.     ASS_Library *ass_lib;# E6 L5 ?( e3 ~
  217.     ASS_Renderer *ass_renderer;
      C7 k  _( m& M$ }- j# H
  218.     ASS_Track *ass_track;
    8 p3 o* r2 c/ W* |& w  x; a
  219. } rbt_dec_context;
    . {3 r  x, [2 h( S- v
  220. 5 J0 S( g1 M( \: S" g
  221. static void dump_pnm_file(char *filename, rbt_dec_context *rbt,3 t9 b, I% z  B6 x3 e9 b8 s
  222.     uint8_t *image, int width, int height)/ Q% K- _1 S4 A
  223. {
    7 X: h  l, A! X7 N! _$ I2 j
  224.     FILE *outfile;
    9 f( P% |$ N  B' j; m/ U+ C! r
  225.     uint8_t bytes[3];
      b, u5 I/ N: _/ A" }: b
  226.     int p;
    . V! @8 c8 _* w0 b
  227.     uint8_t pixel;
    $ b$ v( B+ k; E
  228. / d% C* k/ b  `" k) {% T
  229.     outfile = fopen(filename, "wb");$ e+ P$ p; e1 J3 A* {" A! `7 Y
  230.     fprintf(outfile, "P6\n%d %d\n255\n", width, height);
    4 X' d/ |* i6 @
  231.     for (p = 0; p < width * height; p++)
    + x! X. |6 c$ i. z- H
  232.     {
    ! O( y' ?4 `: |- |
  233.         pixel = image[p];- Z. w- T+ g( D. _
  234.         bytes[0] = rbt->palette[pixel*3+0];- g3 ^! }- {9 \  _0 |8 I7 Y
  235.         bytes[1] = rbt->palette[pixel*3+1];3 r# G; T, l3 s- l
  236.         bytes[2] = rbt->palette[pixel*3+2];
    % T; v& w& _, }1 y3 P% m) K" g
  237.         fwrite(bytes, 3, 1, outfile);
    3 V4 b: Y$ U0 m7 }+ M
  238.     }. c& ]' X" `  Q% g) `+ E
  239.     fclose(outfile);+ y2 ^: A: J7 }. P' C
  240. }+ c  w, [) ]7 a6 z

  241. % t% G: C" E+ R1 L/ K" r2 b
  242. static int load_and_copy_rbt_header(rbt_dec_context *rbt, FILE *inrbt_file, FILE *outrbt_file)% F7 `& D- V  B5 \. F, b  e
  243. {% f1 L; R+ z+ g. F7 ~, q4 c  W
  244.     uint8_t header[RBT_HEADER_SIZE];
    " G) |3 p, _1 L3 G) ^9 r
  245.     int palette_data_size;
    3 t5 c2 y4 j$ {5 q5 y7 L; p- G. N
  246.     uint8_t *palette_chunk;
    + r$ U" C& ^5 c* i' K  D
  247.     int unknown_chunk_size;% d. ^- V/ a4 |- C3 F
  248.     uint8_t *unknown_chunk;
    0 R8 Z0 x" l0 z( {+ N9 b
  249.     uint8_t unknown_table[UNKNOWN_TABLE_SIZE];
    " m* M: n- g6 I/ P5 W) S
  250.     off_t padding_size;
    $ V; x/ M  ~5 u: E* r' ^7 Y' v
  251.     uint8_t *padding;' W7 c8 Z$ P$ N+ m: _. P* C/ a
  252.     int i;& l4 z' m9 ^( k  T/ L3 g9 v
  253.     int frame_size;( {5 K  l# j2 @- e; @2 i
  254.     int max_frame_size;6 {, N" Y. Z1 r, Y3 P* E
  255.     int first_palette_index;
    , E) D8 @" ]0 b& _) |" l% N$ Z
  256.     int palette_count;, V: _+ `% R+ n! b2 I2 V* Y) k
  257.     int palette_type;1 D# U" e0 c6 V+ y1 H8 z( t3 n
  258.     int palette_index;
    ) s( S7 n. [/ N/ L6 x- ]4 F1 ~
  259. % Y0 n1 o) o5 q5 L7 w( N5 N/ \" d+ D
  260.     fseek(inrbt_file, 0, SEEK_SET);% `1 h0 l0 j! H
  261.     fseek(outrbt_file, 0, SEEK_SET);
    3 e, P2 G( O( p  s

  262. 2 W4 L$ V: A. q2 M2 ^
  263.     /* load the header */3 l+ d; W+ Z( r6 h; x. n- o% I
  264.     if (fread(header, RBT_HEADER_SIZE, 1, inrbt_file) != 1)
    , Y4 j. \2 o- p2 `# m% {
  265.     {
    / ?& z% b* d/ _. M# D/ D- s
  266.         printf("problem reading initial RBT header\n");$ h& f; t7 H/ @8 ^5 R; J
  267.         return 0;
    % b2 L8 j2 u2 Q" M- z% \
  268.     }! v! O4 F3 B: B3 o. U

  269. 1 ?# \. m7 g& c2 n
  270.     /* copy header to the output */
    : y# N2 `0 F0 |( @8 c  Y
  271.     if (fwrite(header, RBT_HEADER_SIZE, 1, outrbt_file) != 1)# ]& z8 ]# X5 o. v1 _" T
  272.     {( w8 q7 ~5 Z2 [5 z* q
  273.         printf("problem writing initial RBT header\n");
    7 l7 F$ s6 S( i2 m3 s0 B) _; c. q- q* D
  274.         return 0;2 C/ u1 o  V3 E# r! s. i$ e/ m: ?
  275.     }2 V; j3 ]( n7 ?3 L" A$ ]% M

  276. 8 V+ h, r( o  R- ~5 w" ]0 D
  277.     rbt->version = LE_16(&header[6]);  [, q. Q0 g, H0 O+ M
  278.     rbt->audio_chunk_size = LE_16(&header[8]);
    1 S" A; h) ?! s& x
  279.     rbt->frame_count = LE_16(&header[14]);
    - K* h( C" n8 r* o) A

  280. 6 m* w; j; G" _
  281.     /* transfer the unknown data, if it's there */
    7 s* b( E* T) _2 J
  282.     unknown_chunk_size = LE_16(&header[18]);/ Y' x: z5 |4 m' ~' }9 g* f4 @  J
  283.     if (unknown_chunk_size > 0)
    / u: v: A) r6 ~& L$ L, |
  284.     {+ ^1 i7 |7 K& u. }8 e! \) P2 Y
  285.         unknown_chunk = malloc(unknown_chunk_size);
    / v4 O% V% Y/ R7 k% r& k
  286.         if (fread(unknown_chunk, unknown_chunk_size, 1, inrbt_file) != 1), h) I2 {% e: N! _
  287.         {
    2 n/ w: f. ~# M9 k2 J' ~
  288.             printf("problem reading unknown data\n");
    8 m( K' f6 e. P2 i  P6 O
  289.             return 0;
    ! X# d  J. ]) X8 ^4 [
  290.         }2 o7 {; @! L3 G8 E! l; v1 |3 P# h
  291.         if (fwrite(unknown_chunk, unknown_chunk_size, 1, outrbt_file) != 1), [. V6 E0 x8 Z& d2 }$ _, u$ @
  292.         {
    ( u* L0 e3 M# K# Q
  293.             printf("problem writing unknown data\n");
    $ R5 x& b8 b+ t) D1 _
  294.             return 0;
    % ~0 G/ j! U4 m/ N+ p0 ?
  295.         }! b( u; f5 N: j
  296.         free(unknown_chunk);
    & U; \% h* [$ K- O8 j; j
  297.     }
    % ^( W% |1 ^  p6 H

  298. 7 \3 W  m* |0 l* r; T. R
  299.     /* transfer the palette chunk */# l( q  g8 c% e1 j* i/ }$ M
  300.     palette_data_size = LE_16(&header[16]);& f' o; M+ j5 n( Y
  301.     palette_chunk = malloc(palette_data_size);
    & B9 m6 c7 A* N0 ~: }9 o; B6 m. a
  302.     if (fread(palette_chunk, palette_data_size, 1, inrbt_file) != 1)% R: G# U- Q( q# b7 C
  303.     {7 A3 g1 Q' G2 [! f& a4 `& F5 |/ Y
  304.         printf("problem reading palette\n");
    " X3 a9 C6 @: R+ x, V
  305.         return 0;
    - x3 I; e( P& r* F
  306.     }+ E4 k2 C1 y9 L- q  |
  307.     if (fwrite(palette_chunk, palette_data_size, 1, outrbt_file) != 1)
    ; T$ D2 X" x( H8 M( T+ {
  308.     {
    8 Z! N/ W1 V( l9 b( }2 @
  309.         printf("problem writing palette\n");6 C& U- ]+ \4 L! Q! @
  310.         return 0;4 P2 t' S6 {4 V- F$ q
  311.     }
    3 B: P3 H$ H$ {
  312.     /* load the palette into the internal context */
    ! s) B/ ]' G' U" ?
  313.     memset(rbt->palette, 0, PALETTE_COUNT * 3);+ m% q3 u* T6 U! l6 g
  314.     first_palette_index = palette_chunk[25];0 m( n: q, C  L' t5 X9 }
  315.     palette_count = LE_16(&palette_chunk[29]);: s) m3 p. `. {. |# @
  316.     palette_type = palette_chunk[32];
    2 O) d* V; p3 H! ~: T4 H
  317.     palette_index = (palette_type == 0) ? 38 : 37;- T3 u$ {& R; f# c6 [& O
  318.     for (i = first_palette_index; i < first_palette_index + palette_count; i++)) f7 ]) F; s  P# N" [
  319.     {
    9 z9 a9 t) p9 k+ |# ]
  320.         rbt->palette[i*3+0] = palette_chunk[palette_index++];8 w" w- a# w5 b+ y. P, ]8 x3 _7 b) u9 V
  321.         rbt->palette[i*3+1] = palette_chunk[palette_index++];6 u+ R, T6 M8 F2 j  R0 v  z
  322.         rbt->palette[i*3+2] = palette_chunk[palette_index++];4 U5 ]1 \4 a- |
  323.     }4 X8 |" j  X, R( ?  F5 d
  324.     free(palette_chunk);8 a2 o# a; W2 }# l1 o- T% |
  325. ) J( s: ^" V; N$ y  x* j) R( L. Q/ U
  326.     /* copy the video frame size table (2 bytes per frame), as a placeholder */5 u+ y; a2 p$ Y5 e) G5 O
  327.     rbt->video_frame_size_table = malloc(rbt->frame_count * sizeof(uint16_t));
    / g: ~* p2 j: m( d* o  V
  328.     if (fread(rbt->video_frame_size_table, rbt->frame_count * sizeof(uint16_t), 1, inrbt_file) != 1)
    - b: B& G0 [  o* j7 ]: p7 b
  329.     {
    ( m# S0 }' O% \. ?% u% j
  330.         printf("problem reading frame table\n");
    ! ^+ Q1 z9 k, \8 Q4 X
  331.         return 0;
    : N4 Q2 E* C& ]# Y9 f; K" v5 x
  332.     }
    0 r8 N) b# g6 N- Y( M( _+ N
  333.     rbt->video_frame_size_table_offset = ftell(outrbt_file);8 D! a7 G( Z1 O
  334.     if (fwrite(rbt->video_frame_size_table, rbt->frame_count * sizeof(uint16_t), 1, outrbt_file) != 1)
    ! \# A7 j& `6 b- I, h" l  A
  335.     {
    ) E% ?* ^3 ]' I
  336.         printf("problem writing frame table\n");
    4 E8 J3 }* I/ Y3 l5 Z
  337.         return 0;* M4 M8 b% a- H* R% {
  338.     }
    $ M  `% E& P  J! o( @' M2 z9 I
  339. , Q4 ~  K6 M1 Y4 z4 e6 _1 l
  340.     /* copy the frame size table (2 bytes per frame), as a placeholder */2 P7 f8 W3 e" J1 w( N9 M
  341.     rbt->frame_size_table = malloc(rbt->frame_count * sizeof(uint16_t));& {$ a& B' k5 Z% L/ r1 B+ b7 _, W% E
  342.     if (fread(rbt->frame_size_table, rbt->frame_count * sizeof(uint16_t), 1, inrbt_file) != 1)3 U/ [! n+ N5 Q0 s- L/ o  g
  343.     {
    4 k/ A1 ~4 l- U, l9 Z! o. `/ ]! r
  344.         printf("problem reading frame table\n");* d4 I6 ~- Q1 o8 t2 Q' a' @
  345.         return 0;
    / P6 a  G% T+ S0 F' D
  346.     }# }  x. b! c: I7 g  {9 x' M/ \
  347.     rbt->frame_size_table_offset = ftell(outrbt_file);
    & ?6 q# z1 D0 L
  348.     if (fwrite(rbt->frame_size_table, rbt->frame_count * sizeof(uint16_t), 1, outrbt_file) != 1)
    & J: Z! U) b5 z% c& k& [
  349.     {
    2 j$ C/ [6 N8 e/ e8 B" @8 ^: y
  350.         printf("problem writing frame table\n");
    ' v$ {8 q7 K7 E) _  p
  351.         return 0;4 f+ B& b* X# N) u! o
  352.     }: |/ d# j* d( N/ z# v4 _  @4 E: l

  353. ) k, ?: w6 j" {1 o
  354.     /* find the max frame size */
    , N* G; ^! o, x6 W0 r
  355.     max_frame_size = 0;
    ) j" h- @+ w9 K& t: f; L8 n3 B
  356.     for (i = 0; i < rbt->frame_count; i++)3 c$ O. \' p" A9 r% m& Q8 L
  357.     {1 w! a  ^8 Y: h7 E( M
  358.         frame_size = LE_16(&rbt->frame_size_table[i*2]);
    * R! d3 Z+ d: J# U
  359.         if (frame_size > max_frame_size)5 x! Y; e. C; c0 Z! k* D
  360.             max_frame_size = frame_size;
    $ w5 z+ `: L, V% U6 Z- q' y
  361.     }* G6 g+ W* l) m' Q: w  h; {
  362.     rbt->frame_load_buffer = malloc(max_frame_size);( G) U. [" j  s- U; x' Q1 r3 d

  363. 9 g( M3 h1 P- _$ _4 q. R4 S7 P  t4 k0 C# y
  364.     /* transfer the unknown table(s) *// T; g5 w; _! t7 n7 T; V7 x
  365.     if (fread(unknown_table, UNKNOWN_TABLE_SIZE, 1, inrbt_file) != 1)
    & P3 O. b% L( [( g* Q# D
  366.     {
    ! p* }" @: k* u, }' o, }. N) e
  367.         printf("problem reading unknown table\n");9 U: V$ P, Q8 D* F3 ~! C( C
  368.         return 0;9 o/ n  c1 }* C% F" h  P6 I
  369.     }9 G$ _7 w- m: Y2 j- N
  370.     if (fwrite(unknown_table, UNKNOWN_TABLE_SIZE, 1, outrbt_file) != 1)
    ( A: C2 ?1 C) d" g2 r
  371.     {  g/ v' p. R. R( `
  372.         printf("problem writing unknown table\n");
    5 y( l$ y) s' J/ n
  373.         return 0;5 ^& r5 r2 s: R( A6 \; t6 T
  374.     }
    . ?  F# T7 [6 e* [6 f" G6 S
  375. 5 @: O0 a; F, s. ^5 ~
  376.     /* copy over padding */) S# N4 U9 }" u" B; W$ {
  377.     padding_size = 0x800 - (ftell(inrbt_file) & 0x7FF);
    ) ~# o8 S6 Q' l2 g) D! J
  378.     if (padding_size), G2 A/ \" u, S# a+ \6 w
  379.     {9 P) `5 i( R: ?. V& a4 l4 B+ O
  380.         padding = malloc(padding_size);
    0 _- N1 J/ H7 F% L1 _
  381.         if (fread(padding, padding_size, 1, inrbt_file) != 1)
    9 Y' p9 U- k9 R* Z7 I' d/ D
  382.         {
    3 [" q+ f: J; l* Z9 Q  ]
  383.             printf("problem reading padding\n");
    3 ?2 ^: s/ G! k; M
  384.             return 0;
      e# s! P4 M$ G9 _
  385.         }# {; n) c; f. w. u' B0 Y1 \# R: m. U
  386.         if (fwrite(padding, padding_size, 1, outrbt_file) != 1)) |8 c0 i8 u+ f* P) f; s8 D
  387.         {
    , f6 P2 O- b0 Z# Y0 ]
  388.             printf("problem writing padding\n");
    ; m0 d# j) L6 [7 {+ Q  r7 L
  389.             return 0;# O1 i' J, g. Y' X' U4 o( ^
  390.         }
    . R- L& ?' B: J, D8 {7 D
  391.         free(padding);
    . g  p; I1 Q7 e
  392.     }
    , B6 T# {) m2 p1 t' K

  393. ' I$ \' s& }% v9 E  P
  394.     return 1;7 G0 @: Y; y) J8 P3 w, S* t& X6 {9 N9 T
  395. }* J0 j+ `4 ?$ s  W- o' z

  396. / y/ R8 _7 d4 J* e4 \4 G/ L
  397. static int get_lzs_back_ref_length(get_bits_context *gb)9 ?% B- M5 i3 p, r$ J* U0 j/ h5 C
  398. {1 L% w% @6 e; O5 H2 _6 Y" x; g
  399.     int vlc;
    : o- l9 I/ r8 u  P) v9 Q4 G
  400.     int count;
    3 c( P) q0 I: D" I3 l% S
  401.     int value;# y" s& @6 `6 U

  402. 3 i1 o! Z. \3 K0 ^6 I" ^
  403.     vlc = view_bits(gb, VLC_SIZE);
    4 W: Y5 D# M6 u# a" h" c
  404.     count = lzs_vlc_table[vlc].count;4 ?) d, u  k+ ]+ U" {  m
  405.     value = lzs_vlc_table[vlc].value;/ G, @1 w  a& b3 D8 j; l" r  z
  406. 5 ~2 h6 z8 ^. ^; D4 i5 p( @
  407.     read_bits(gb, count);
    ) e9 i/ d" O0 C
  408.     if (value == 8)# j9 o; |: R! L+ p- x& }5 N
  409.     {% z" K/ F0 U/ v: ~
  410.         do
    & a" H1 H* |% G+ x# b$ T
  411.         {* A0 S; V) q# c) i( g
  412.             vlc = read_bits(gb, VLC_SIZE);
    / p4 z5 [4 L6 P# o2 ?, M
  413.             value += vlc;
    # E" `( J+ o! _$ [2 i; M% j- u
  414.         }
    . v2 n: P) \; O( ?0 |6 t& d9 B
  415.         while (vlc == 0xF);2 N& k. j) g8 O2 k" A% ^( U1 j" P! @
  416.     }
    % Y3 U9 S  x: T' C, {; [
  417. % n* C. T; O4 @+ y, S
  418.     return value;
    ! @  m0 v- I( n
  419. }+ |' l; h) F3 s8 x$ b  J$ c  O0 _
  420. ) R* J9 t! I1 x7 e) @% U- T
  421. static void compress_window(put_bits_context *pb, uint8_t *full_window,* b+ `+ |8 l0 O
  422.     int full_window_stride,
    ! l( Y& R7 D* @: m) G
  423.     int window_top, int window_bottom, int window_left, int window_right)- D& N' ]  @/ A4 q7 N3 _8 v4 y5 V
  424. {0 p, Q, j! S( h
  425.     int last_pixel;
    6 u" A4 f. t8 k$ B' ]
  426.     int run_size;
    ( R( q3 {$ [/ c2 }
  427.     int x;
    # A  D4 W8 \. I" r/ M+ h
  428.     int y;0 l4 `( r/ \1 n8 t" m' V
  429.     int start_index;
    1 a" p" p5 z7 Z% j4 J& e
  430.     int end_index;
    " H! {3 |; V) b2 z0 Z: J$ ^
  431.     int encode_last_run;% X+ k$ }3 t1 {% h$ H
  432. 6 U! s5 H$ t+ [3 Q/ }& [
  433.     last_pixel = full_window[0];
    8 ^9 u* p( S7 j* b6 m
  434.     run_size = 1;
    8 ]2 E7 U4 F7 T. ?
  435.     for (y = window_top; y <= window_bottom; y++)
    / E3 E' j( X1 a( n6 s8 z6 _
  436.     {
    2 I/ G* o) o& l- u  s9 w
  437.         start_index = y * full_window_stride + window_left;
    + v% N$ C* i( j( }( @) P
  438.         if (y == window_top); i7 l5 o8 E2 w
  439.             start_index += 1;: ]1 V( {3 D# {: h# ]
  440.         end_index = y * full_window_stride + window_right;
    9 r6 }1 U* b5 z
  441.         if (y == window_bottom)
    . C- H$ \3 K, x3 h7 S
  442.             encode_last_run = 1;
    & F6 @3 @) `  ^( @/ h
  443.         else/ ~3 h$ s! c! }
  444.             encode_last_run = 0;9 u3 n. s; S0 _3 d/ U
  445.         for (x = start_index; x < end_index; x++)$ k$ {9 _7 j0 i( {8 e# `
  446.         {
    5 G5 @' O* U$ c& S0 d: {' l+ g
  447.             if (!encode_last_run && full_window[x] == last_pixel)
    ' M: p9 z! r3 v; h
  448.                 run_size++;, b% G5 Y9 a, t1 a) h# u
  449.             else
    7 f/ e4 n- _' |+ I: W
  450.             {4 w$ L) B0 i+ ]* p* x
  451.                 if (run_size == 1)% @4 x* C% E8 b8 F) r/ L3 c
  452.                 {
    9 S  H0 R) b6 x, O8 E
  453.                     /* encode a 0 bit followed by raw pixel byte */
    " y; G7 h  ~0 W4 m% i
  454.                     put_bits(pb, 0, 1);7 z  ^3 S  E) z/ d
  455.                     put_bits(pb, last_pixel, 8);0 |1 b% k2 O( t# o: p! E: r# U: M/ }
  456.                 }* i8 h, P" @& J" p- N
  457.                 else if (run_size == 2)
    & ~' ?/ |' x  A  E4 s
  458.                 {
    4 m: f/ g7 L9 F5 z0 C7 R
  459.                     /* encode a 0 bit followed by raw pixel byte */6 z' t1 h" W. c" k, M
  460.                     put_bits(pb, 0, 1);8 Z4 n9 {& e7 \2 m
  461.                     put_bits(pb, last_pixel, 8);
    4 B3 q* x& D1 U6 R# |) g  G. L2 I5 u
  462.                     put_bits(pb, 0, 1);
    / ?  y! x( ^& B! q- H. e6 H3 P3 F
  463.                     put_bits(pb, last_pixel, 8);% U6 k: x6 ~( b( e6 F8 I# d+ v
  464.                 }5 x2 M& b7 \& S5 q/ t3 |9 b
  465.                 else
    . d; g8 O3 L/ [5 L
  466.                 {
    0 r. Q7 _5 [. o8 {& D5 o4 U6 u
  467.                     /* encode a 0 bit followed by raw pixel byte */% w2 I9 X  U1 T! d
  468.                     put_bits(pb, 0, 1);
    - z  Y* C* |9 H1 U
  469.                     put_bits(pb, last_pixel, 8);
    & u4 A1 w4 b: `2 t- Z4 {) U9 D
  470.                     run_size--;$ }0 a" m7 l+ [+ c. |8 m* w9 k
  471.                     /* encode a run: a 1 bit, followed by a back reference5 g8 D7 j" T( _) i- Y. }
  472.                      * offset (-1), followed by a length */
    - C1 V8 ^6 v& a2 _$ R* H
  473.                     put_bits(pb, 1, 1);
    3 u8 y3 O/ A' C% |
  474.                     put_bits(pb, 1, 1);  /* 1 = 7-bit offset */. ?: U" _; H: K3 `
  475.                     put_bits(pb, 1, 7);% e* u8 [3 q/ N( l$ t
  476.                     if (run_size <= 4)( h, k* C$ q1 J8 I4 v. h4 ~" h
  477.                     {5 }+ U' n: H: v+ E/ D
  478.                         /* lengths 2, 3, and 4 are 2 bits */
    ' n# b7 z4 r. P) H
  479.                         put_bits(pb, run_size - 2, 2);
    * o+ U, e5 p7 t
  480.                     }' c3 a+ Y- l& _! K$ \$ f
  481.                     else if (run_size <= 7)
    ' K4 z* `+ n& Y/ l
  482.                     {- N; ?! x6 C2 K- I! m0 V
  483.                         /* lengths 5, 6, and 7 are 4 bits */! H8 n/ P4 X9 C6 n# k- m+ }( B' \
  484.                         put_bits(pb, run_size + 7, 4);
    5 w6 |' Y* m9 ~5 U9 n1 c- I  U
  485.                     }
    $ @7 a* e8 y, g) a& v- l4 j
  486.                     else
    - k( z3 J. \, }+ I* w+ v
  487.                     {
    1 c2 `! ~- X: R' p! `1 w+ C$ n
  488.                         /* arbitrary length; start by encoding 0xF which
    " G/ q* O/ R6 [8 m2 R# B
  489.                          * stands in for an initial version of 8 */
    # {& ^( y7 J5 ?& r$ Z1 N* Z
  490.                         put_bits(pb, 0xF, 4);
    & C7 F8 C7 Q: t9 ^" d
  491.                         run_size -= 8;
    ( j) J# ~6 K5 j) h% L# @# v; z

  492. : W. z: j) J, U' U) M
  493.                         /* encode blocks of 4 bits until run_size is 0 */# s. V& {) S3 J) f6 `
  494.                         while (run_size >= 0)
    7 R4 H% A$ u& M4 z+ B
  495.                         {
    ( D/ [/ z5 u' x3 z* N" Y
  496.                             if (run_size >= 15), {% G+ {% V. D* T  _8 y& ^
  497.                             {
    - P3 G: Y( z' C2 d5 d5 S
  498.                                 put_bits(pb, 0xF, 4);$ A, F. F& p5 F$ {1 P* ~
  499.                                 run_size -= 0xF;
    " o0 l4 h; b- Z  Q3 z2 g
  500.                             }
    : {( K1 G/ E! S; `
  501.                             else
    & ?5 E, P$ N5 S+ A. T
  502.                             {
    7 u% k' ~- G0 A- G& i
  503.                                 put_bits(pb, run_size, 4);  |( u6 G3 I. H4 E3 m. O& e
  504.                                 run_size = -1;: z+ A4 R8 T! w) A. @
  505.                             }
    + \* p) x/ }4 Y; m9 V9 R
  506.                         }
    ' X3 ]+ T# X& u: b' A# u
  507.                     }
    ) Y3 n. W4 e) x( K1 @" x1 }
  508.                 }
    1 N) ?; n3 L, d; @+ v

  509. # a9 h# I& ~3 U) m
  510.                 last_pixel = full_window[x];
    * r2 _. z; V' |( i
  511.                 run_size = 1;9 s/ K! C( E4 H0 d! _1 U

  512. 5 r7 x- [2 d) g  V% x4 e
  513.                 /* this single x iteration was only here to close the final run */8 }& ~5 }9 b: c; P6 o, p
  514.                 if (y == window_bottom)
    9 j. ]) O8 ]6 C3 r
  515.                     break;9 M7 ~' M5 T7 W" |8 s6 T1 {0 ?
  516.             }* q* e5 J  t2 ?: ^
  517.         }1 b$ @2 z1 l/ ^  c4 D
  518.     }
    6 f7 ~1 d+ Z* m1 n
  519. $ z7 V6 c, u, h. M8 Q
  520.     /* close the bitstream by encoding a back reference with length 0 */; M4 t$ J9 E, U. E- @" Q
  521.     put_bits(pb, 1, 1);  /* back reference run */
    $ K& s& A/ e# @0 ?& C1 g
  522.     put_bits(pb, 1, 1);  /* 1 = 7-bit offset */* [" N8 \* {; q4 x6 n7 `6 d
  523.     put_bits(pb, 0, 7);  /* length 0 *// P* I- ~8 V" }* M! b, R

  524. - ?' c1 C) d- T+ z. {, L4 F
  525.     put_bits_flush(pb);
    , w6 f# i/ b# y
  526. }
    ; n6 f: {. g0 ^- D% n) ^- s- B3 M% v, i! `

  527. 5 f! \4 c  ]( J0 n% S7 |
  528. /* compute Euclidean distance between an RGB color and the desired target */
    0 H/ P( u1 s9 `+ s3 N3 v6 H
  529. static int compute_rgb_distance(int r1, int r2, int g1, int g2, int b1, int b2)5 o) D! R4 T' i% E9 q
  530. {
    7 i( k3 }, P3 J' T' z
  531.     return sqrt((r1 - r2) * (r1 - r2) +! l0 J# b( \3 F3 K
  532.                 (g1 - g2) * (g1 - g2) +
    # M( T; |/ f) g
  533.                 (b1 - b2) * (b1 - b2));0 X2 c9 l4 G$ w. @+ u4 z+ @/ _
  534. }
    : X. C8 ~% K9 S: x- m% f) |/ C

  535. " a/ P- Q, S; M$ Q
  536. static uint8_t find_nearest_color(rbt_dec_context *rbt, int r, int g, int b)7 K: k% i; a% T' Y! E
  537. {" G( ?# n! }9 m& f$ n" t2 n
  538.     int i;
    : H- s. b+ R, P
  539.     int nearest_distance;
    ( O" f1 V) p$ H5 E& o7 y" g
  540.     int distance;
    8 b7 G; B" J% N' E6 t- n& {  ^: |
  541.     int rp;
    * U5 u# @8 ?) h
  542.     int gp;
    - {+ v- S9 d- W* `% p3 G' N
  543.     int bp;3 c: }' q2 l6 O+ `6 q
  544.     uint8_t palette_index;
    ; \4 r7 o; U# H1 F5 E# k+ {8 I
  545. 3 R: _% J( o* I
  546.     nearest_distance = 999999999;( X& l. h$ Z2 U! H% i% [$ g
  547.     palette_index = 0;
    ' w- |8 |9 t9 M4 ?1 J* @& u
  548.     for (i = 0; i < 256; i++)
    # O/ Z+ [' c2 M$ t
  549.     {- v+ Z# o$ f* M! f. r
  550.         rp = rbt->palette[i * 3 + 0];$ v0 B* p0 Q5 Z3 N5 p! f
  551.         gp = rbt->palette[i * 3 + 1];& c  y' Q" `* y5 w$ y3 p2 P
  552.         bp = rbt->palette[i * 3 + 2];
    ( G: Q2 ]5 r3 m4 i8 s# u) T
  553.         distance = compute_rgb_distance(r, rp, g, gp, b, bp);
    3 M2 X& j4 C7 q" t
  554.         if (distance < nearest_distance)
    2 T) K+ s! A/ T3 c) c: b3 F# L
  555.         {$ |" W' b" h) W, R- b
  556.             nearest_distance = distance;# k- `, b2 Y) Q/ P4 Z$ t
  557.             palette_index = i;. H6 g2 D. Z' _/ `7 n3 w4 y
  558.         }
    7 Q( y5 J5 {9 y! L# V3 u
  559.         /* can't get closer than 0; break early */
    & A8 \3 z, }# ~: y* c. M3 G
  560.         if (distance == 0)& |) P0 g8 ~, C, t
  561.             break;& H3 l- d" ]( W# T  @
  562.     }
    & P0 p, z. V3 n* l: w

  563. % L" u: p5 H, J) s& W% T! |
  564.     return palette_index;
    1 ]' N) g" M4 ?3 z3 ~9 ]) @
  565. }
    * Q2 x* p1 |' ?! r. V: x2 g

  566. 7 a. V+ v) G' ^
  567. static void subtitle_frame(rbt_dec_context *rbt, uint8_t *frame,* S( \" Q! J) w. {  L* C- A/ [
  568.     int width, int height, int timestamp)! E; W) Y$ O+ E( N5 Z. \5 ?
  569. {
    2 [5 h/ ?1 t( `0 O2 x% r
  570.     ASS_Image *subtitles;1 j3 p; T2 N8 V/ m
  571.     int detect_change;, U  \! q- \" |; j- d
  572.     uint8_t subtitle_pixel;; w) ~3 B; a  h  Y" m
  573.     int x, y;
    ' W" ]5 X  a# J' F* x0 j. v* N
  574.     uint8_t *frame_ptr;
    ! U2 Z9 f0 M% F* g
  575.     uint8_t *subtitle_ptr;
    ; A- a$ L, ?# _( w9 k5 q' H6 f" z

  576. & {, `- v* S9 J/ k! T6 R2 G( L4 p
  577.     /* ask library for the subtitle for this timestamp */8 d$ K8 N* j% g: y! W- Z0 D8 B, H
  578.     subtitles = ass_render_frame(rbt->ass_renderer, rbt->ass_track,. |9 a& f# Y6 [$ U& A1 r" R
  579.         timestamp, &detect_change);; b  a. h9 y0 c* f- Q! o1 d

  580. 5 }$ n2 e+ H7 S. Z  L1 M1 J0 y' e
  581.     /* render the list of subtitles onto the decoded frame */
    4 l2 q# E5 t/ f- a2 K5 I
  582.     while (subtitles)
    * a' z# h  U6 g  ~, c, [% c5 U
  583.     {
    " n0 u$ F" ^7 v
  584.         /* palette components are only 6 bits, so shift an extra 2; N6 R: I( h  x+ [  m! |
  585.          * bits off each component */
    8 y' [9 N6 P9 r6 d
  586.         subtitle_pixel = find_nearest_color(rbt,  i, |% _2 n* V# j0 o" D9 ~+ R1 _
  587.             (subtitles->color >> 10) & 0xFF,$ }* {% N% ]; p1 O. t. P) x; ^
  588.             (subtitles->color >> 18) & 0xFF,
    5 I5 M' ^/ }) I/ G# P
  589.             (subtitles->color >> 26) & 0xFF);
    - A) w" |7 _' i+ v
  590.         for (y = 0; y < subtitles->h; y++); Q3 h! b1 ]* v% `7 e
  591.         {; O1 `/ B0 H: T, U0 o- `& E# g0 u
  592.             subtitle_ptr = &subtitles->bitmap[y * subtitles->stride];( C" _+ I! p: @: L
  593.             frame_ptr = &frame[(subtitles->dst_y + y) * width + subtitles->dst_x];
    . s( p; e1 h2 R5 E
  594.             for (x = 0; x < subtitles->w; x++, frame_ptr++, subtitle_ptr++)
    : y8 J9 f: c5 `" E  p5 H0 M: J
  595.             {3 i4 J6 r* e* G, ?
  596.                 if (*subtitle_ptr >= SUBTITLE_THRESHOLD)
    - G# H4 L) L4 ?! K9 Z- H
  597.                     *frame_ptr = subtitle_pixel;/ q7 D% |! W. M5 Y7 P; @
  598.             }
    ) I1 L0 f9 E* I& x+ e) m
  599.         }2 l$ Y2 A1 f1 B$ ]5 g( |' j
  600.         subtitles = subtitles->next;
    4 ]2 m" _1 Y: b  C- A
  601.     }$ q; \5 ^4 L8 T
  602. }; G, d) A3 G( R* `* R" w

  603. ; I8 C) R+ y7 ?. P) u% o* B& ?
  604. static int copy_frames(rbt_dec_context *rbt, FILE *inrbt_file, FILE *outrbt_file,, b& v6 Y" ^' m0 Y& X! s7 Y  G
  605.     int origin_x, int origin_y, int window_width, int window_height)
    : {& }; |3 v! Y& m# @: M1 s
  606. {6 P7 f& ~) s$ S0 U9 j+ l
  607.     int i;
    6 y) O3 W  l: t0 n, i) E
  608.     int j;4 Z2 O: m# D8 z% P4 {6 {
  609.     int scale;
      Y3 p, D& A8 }0 d# `$ c" E
  610.     int width;2 v' _7 P+ G  Z, F
  611.     int height;, B% Y" F" g6 T5 L
  612.     int max_width;
    1 ]% F. L! R' w
  613.     int max_height;/ X) \5 O2 P' f  D/ U' J) _* \
  614.     int frame_x;
    " i" `1 E% n6 M) q! U! ^6 f* W/ z; }
  615.     int frame_y;
    1 i! r( `4 d# \; F# D
  616.     int fragment_count;
    . Q( h3 ~& H( D6 f( r- i# a) P
  617.     int decoded_size;0 {) D1 B4 l' K+ Z& z; S
  618.     uint8_t *decoded_frame;; v3 G2 @4 L3 J/ B1 v% U
  619.     int fragment;  J0 F1 u9 m: F! l* n2 ?3 R
  620.     int fragment_compressed_size;0 z1 }: L9 k" M9 @3 H
  621.     int fragment_decompressed_size;
    * D+ {9 P- T; A  o
  622.     int compression_type;
    % j( `0 I+ y% i3 v
  623.     int index;
    1 v9 ]. e! {0 `. S+ _
  624.     int out_index;
    # V6 X, V+ c+ N. R( W$ O$ i
  625.     get_bits_context gb;* |6 U' [5 s+ Y! z2 w8 A/ N7 E5 ~
  626.     int frame_size;' ^3 v; p8 Z3 U6 W* O2 ]
  627.     int video_frame_size;
    : D( `) k& u! @4 V* O+ `9 E
  628.     int audio_frame_size;, `! a0 {, r; _* `3 [  A( T6 i
  629. 8 W/ N1 n7 t( W- H9 ]! A3 w
  630.     int back_ref_offset_type;7 [6 c! t/ {* l6 p1 l) y
  631.     int back_ref_offset;
    . J6 W0 D! o: a# d
  632.     int back_ref_length;: Y9 Y# E- i- j) o5 z
  633.     int back_ref_start;
    5 S) c% g' Z( a) q+ s( I0 N
  634.     int back_ref_end;* a: w: [' S8 O0 J( H
  635. , W8 t2 W& I6 {  X
  636.     uint8_t *full_window;
    & I$ U4 f) q7 a/ E2 w
  637.     int full_window_size;2 T! I4 s) D& c& Z
  638.     int y;
    5 h% s: E& J1 n7 P$ f
  639.     int window_top;
    4 {" S; ~$ ]1 m& A2 `& R
  640.     int window_bottom;
    7 f- I3 k( m: j0 v) P. R
  641.     int window_left;
    , J2 M; F  U0 o2 L: s* k
  642.     int window_right;3 v1 R6 X$ D, P6 d/ F3 }" h
  643.     int window_size;  L7 n$ e! h4 D9 U  Q* _* O- s0 M
  644. % m1 q0 s4 i2 w3 D
  645.     char filename[30];
    9 F6 r" z) c' J1 C$ N* Y. S

  646. " `9 ^+ k& q' u  m0 G+ u( z
  647.     put_bits_context *pb;
    ! y0 P6 o$ G+ W2 e. D. w7 o
  648. : ~( c+ c% _7 d! W. I* {) Z
  649.     full_window_size = window_width * window_height;
    & f9 c( l7 x9 {0 [/ ]$ j
  650.     full_window = malloc(full_window_size);
    ! Y$ N9 j9 U, t/ g
  651.     pb = init_put_bits();  k7 n, B% v7 k2 E: v* n0 N
  652. % i  s, L1 a, y
  653.     max_width = 0;1 c+ F0 F. _; E  J
  654.     max_height = 0;
    ' T- i, K  N2 y1 {6 J* N

  655.   _5 e8 F& m. I: i- A) I
  656.     for (i = 0; i < rbt->frame_count; i++)  e$ a1 k) r0 b
  657.     {, a$ h  P* \, ~8 F4 ^3 a
  658.         /* read the entire frame (includes audio and video) */
    7 h9 j8 K; S- X1 n' s6 K- W
  659.         frame_size = LE_16(&rbt->frame_size_table[i*2]);
    / o9 A8 F; Z0 F2 J
  660.         video_frame_size = LE_16(&rbt->video_frame_size_table[i*2]);& c' u* f# ]4 f0 N1 Y9 J4 l
  661.         audio_frame_size = frame_size - video_frame_size;
    + Z/ N, |2 n6 N; ~2 H* k6 k
  662.         if (fread(rbt->frame_load_buffer, frame_size, 1, inrbt_file) != 1), y; }7 N+ i; X- L( R( Q
  663.         {
    3 l4 d( a! d" T# H" N; g( T) D: O, T
  664.             printf("problem reading frame %d\n", i);( D% z! y3 c! D% \3 o$ R6 M" }
  665.             return 0;+ ?9 M* V) \0 }& l7 z# J1 a+ k* z
  666.         }1 m1 [2 [2 L; c

  667. 2 ]  U2 P" g& s/ I
  668.         scale = rbt->frame_load_buffer[3];
    ! V4 h9 k+ F7 d0 i# k
  669.         width = LE_16(&rbt->frame_load_buffer[4]);* h( j* Q2 E/ C
  670.         if (max_width < width)9 Q# d2 v  H9 b  R: H; d1 u: M
  671.             max_width = width;
    2 G+ ?3 l5 H: }5 @8 z
  672.         if (max_height < height)' j/ p9 e  {; N# n7 s0 b
  673.             max_height = height;
    8 _' z7 |4 n7 P. W2 ?6 I
  674.         height = LE_16(&rbt->frame_load_buffer[6]);
    6 C% c9 y) ?! M! e% w- X
  675.         frame_x = LE_16(&rbt->frame_load_buffer[12]);9 T. j8 E6 n9 ~3 ]7 C. i+ m
  676.         frame_y = LE_16(&rbt->frame_load_buffer[14]);
    5 {. V$ J3 o- a8 F/ J7 |
  677.         fragment_count = LE_16(&rbt->frame_load_buffer[18]);
    0 p6 m8 b* i% q/ S
  678.         decoded_size = width * height;5 \: }% [/ k6 V9 \6 F$ u: W4 }

  679. 2 T. c+ ?, d. V6 j* }0 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);
    ( j3 Q+ f4 n5 x5 f/ [6 O

  681. ( S4 P7 A8 U+ B$ J! y+ {3 S
  682.         /* decode the frame */
    / E3 k  a8 B7 k6 P! r
  683.         decoded_frame = malloc(decoded_size);7 s; s) e' ?2 g$ v
  684.         index = 24;
    $ }$ [1 O, H7 H2 [
  685.         out_index = 0;
    ; s7 g5 G, M1 P& V6 w; s
  686.         for (fragment = 0; fragment < fragment_count; fragment++)
    ; ]* j1 R, n6 F! h$ G
  687.         {' V  |5 C- k, w3 W1 Y
  688.             fragment_compressed_size = LE_32(&rbt->frame_load_buffer[index]);
    , R' Q" E0 C# F: x# W! Q( _
  689.             index += 4;
    % b, ~: u* m  t; H
  690.             fragment_decompressed_size = LE_32(&rbt->frame_load_buffer[index]);
    - U. V2 g: l4 e. V4 U: y. r* p
  691.             index += 4;& Y; V+ ]) w8 T
  692.             compression_type = LE_16(&rbt->frame_load_buffer[index]);( c7 I6 _/ V8 V( e9 B; O. D& p; [
  693.             index += 2;$ l. N  C, {1 g) a  n6 M

  694. . w) y7 E7 t* @+ ^) W% k( F
  695.             if (compression_type == 0)
    ( s% v$ U% V7 B3 ~
  696.             {
      M! `7 Z& M; ]9 X/ t
  697.                 init_get_bits(&gb, &rbt->frame_load_buffer[index],
    $ n  ^. D0 G; x7 M9 D$ t
  698.                     fragment_compressed_size);
    0 h  K% e! z; _$ K9 {
  699. 8 h% D/ T6 ]0 a. j' f
  700.                 while (out_index < fragment_decompressed_size)& X5 i- r- w' X0 ~. w' w
  701.                 {
    8 ~. G( U) F. F* u; {( p
  702.                     if (read_bits(&gb, 1))0 Q) p  X" ~6 |1 p) h
  703.                     {
    6 F' G+ i; y9 m
  704.                         /* decode back reference offset type */+ g: x$ [8 q' [) ^/ p8 {
  705.                         back_ref_offset_type = read_bits(&gb, 1);
    5 g% a9 {5 C" }: E* i- f" z) H* ^' d
  706. 6 p, ]# g1 p: H' X" P/ ^; ~
  707.                         /* back reference offset is 7 or 11 bits */
    & D) [1 F/ v$ O$ c& z$ l
  708.                         back_ref_offset = read_bits(&gb,7 f/ t4 M) F% {- @( g/ @/ R- T; D
  709.                             (back_ref_offset_type) ? 7 : 11);$ L  P1 w5 z0 }; x. I( N3 N

  710. " e; _& P' C8 V) s/ E
  711.                         /* get the length of the back reference */1 X' Z  y* Q' P
  712.                         back_ref_length = get_lzs_back_ref_length(&gb);* d/ m, u$ r6 I  B- [
  713.                         back_ref_start = out_index - back_ref_offset;. d' {3 _% P6 N8 ?
  714.                         back_ref_end = back_ref_start + back_ref_length;
    7 l2 B- H$ a' X8 I9 L' G8 i
  715. $ ~# ~* Y7 P6 v) i: }7 K$ y
  716.                         /* copy the back reference, byte by byte */
    6 l! w3 ?. y4 z
  717.                         for (j = back_ref_start; j < back_ref_end; j++)
    ! h7 d/ {& L, l9 k4 C* [8 ~  _& P: D
  718.                             decoded_frame[out_index++] = decoded_frame[j];' Z0 H2 V4 `( ?& P: K0 t
  719.                     }, v6 Z0 Y- W' \& b/ s: o' ?0 r
  720.                     else
    3 d6 z( P; H& b4 T2 u2 |6 A; O
  721.                     {
    1 U. c1 N2 J# _+ _" l  x' J6 F" d
  722.                         /* read raw pixel byte */
    ! g, O  o% u3 H  J$ s' z7 T
  723.                         decoded_frame[out_index++] = read_bits(&gb, 8) & 0xFF;' l8 K9 H, [8 d3 h" o. L  t
  724.                     }
    3 I% O  f) N* W' z
  725.                 }
    ; L0 W% a# U. Y/ E: u' }
  726. ; q$ P! n# a8 e- ]1 b
  727.                 delete_get_bits(&gb);
    7 |0 Q% [  [% t; e* x6 W4 h
  728.             }
    9 l$ O+ l) a* M
  729. 8 e% ~6 u7 V( X
  730.             /* next fragment */
    # {  q. r# G# l" q8 A4 Z' `
  731.             index += fragment_compressed_size;7 {  X( ]! m3 G+ t* f1 e
  732.         }
    7 H' y5 U: b" @3 ^9 V  w8 Y
  733. , @! W; F+ d) G( G
  734.         if (rbt->dump_frames): A+ C; ?* t! Z, u1 x0 x' ^2 Z2 e
  735.         {) ~5 I, p8 v4 o5 c$ ]
  736.             /* dump the original frame */( G" E$ H! P4 p8 z
  737.             sprintf(filename, "original-frame-%03d.pnm", i);
    . z+ q9 b. V' v
  738.             dump_pnm_file(filename, rbt, decoded_frame, width, height);
    1 |6 ]0 y: ~! _" Q, y7 v5 R
  739.         }: R' y! u& [7 n! b7 Y& E
  740. * D" P+ A" ~  p# s# |& e6 h- P* b. p
  741.         /* transfer the image onto the frame window */
    3 O1 O) z5 I. I) L" i
  742.         memset(full_window, 0xFF, full_window_size);& c0 ~) a& p( m: ~/ F
  743.         index = 0;
    & A* ^+ Y% Z7 ?  M% x. i
  744.         for (y = 0; y < height; y++)
      g1 X! E* {- O2 F+ o& s  R
  745.         {
    0 _2 s7 r8 y: ^( `. d' [# x
  746.             out_index = window_width * (frame_y + y) + frame_x;
    : L/ E& L4 h. u" w1 ?
  747.             memcpy(&full_window[out_index], &decoded_frame[index], width);  Y# Z- _( E/ u* h! i8 V
  748.             index += width;4 G% [1 W. y7 o: V
  749.         }
    - g6 V3 {0 j9 U0 K
  750. 6 t4 t' C& V; I; Y+ z. q0 `9 z0 g$ K
  751.         /* write the subtitle */. E1 p" M# [0 @1 B, \
  752.         subtitle_frame(rbt, full_window, window_width, window_height,
    ( w. U' p1 j+ C5 c
  753.             i * MILLISECONDS_PER_FRAME);
    % x* J& }1 i# d
  754. 4 D/ K. h4 a$ q, d, j& g
  755.         /* figure out the smallest change window */# f; B' |* J" [3 a0 p7 Z
  756.         window_top = frame_y;
    " O8 ]. \' e; Z9 I9 m7 ?
  757.         window_bottom = window_height;8 x2 F$ u" _- b1 n, b
  758.         window_left = 0;
    7 W( U# g9 K$ H8 ?3 r8 j8 f: g! X
  759.         window_right = window_width;
    6 p6 M1 u$ U. z, ]
  760.         window_size = (window_right - window_left) * (window_bottom - window_top);
    / h! q: w; l6 @- _

  761. ( K# `( C- h9 V, i% |( o; ?" f( l# m
  762.         /* compress the frame */: |! I4 F7 m( D
  763.         reset_put_bits(pb);
    : m+ g8 m9 k7 X1 D
  764.         compress_window(pb, full_window, window_width, window_top,) f3 k5 i1 R6 A9 H( G
  765.             window_bottom, window_left, window_right);* }" W+ ?$ m7 ^& i

  766. & [3 |' b1 e( x1 ~' w9 A: m0 `5 p+ @
  767.         if (rbt->dump_frames)
    3 i$ B2 |2 t' B, h' V% e
  768.         {
    : ]8 B- E/ X0 i4 p
  769.             /* dump the frame plotted onto the full window prior to encoding,( i% G( @0 w: n  C, p5 r0 N
  770.              * with subtitle */# C1 \' ^+ l6 {6 u! T& a
  771.             sprintf(filename, "pre-encoding-frame-%03d.pnm", i);- `4 [+ t& g- y) `, e) o8 @
  772.             dump_pnm_file(filename, rbt, full_window, window_width, window_height);. O' [9 f3 M( j! g
  773.         }
    3 k9 I- R; w, b3 C  r  [0 G2 q+ M
  774. 4 N# e: q9 i1 V2 p7 ?2 `' q- _8 k
  775.         free(decoded_frame);
    ( E7 y# s8 [$ p1 y$ J: i; `7 G
  776. . G3 T0 r1 S  W* c! R  b4 `
  777.         /* update the frame header */
    # t0 g( G" \: x- V. L
  778.         /* width */
    8 U& s3 O0 Q$ Y) E. Q6 S
  779.         rbt->frame_load_buffer[4] = (window_right - window_left) & 0xFF;
    0 h" ~  v1 g0 B, N$ v+ `5 k2 ?
  780.         rbt->frame_load_buffer[5] = (window_right - window_left) >> 8;; L2 m6 ]' ]" k1 Q# _
  781.         /* height */6 a" A) \5 V6 P6 h4 C* ]2 m4 j8 |
  782.         rbt->frame_load_buffer[6] = (window_bottom - window_top) & 0xFF;
    5 e+ n: p5 c- N: w: t7 s
  783.         rbt->frame_load_buffer[7] = (window_bottom - window_top) >> 8;7 v" a; Z  z+ Q% x/ x- ?3 E8 d7 T8 p
  784.         /* origin X */' [! U" S( ?; L5 z
  785.         rbt->frame_load_buffer[12] = window_left & 0xFF;4 f- Y# q- k6 A8 F* V
  786.         rbt->frame_load_buffer[13] = window_left >> 8;( e: w  s- v9 c  C' _% y
  787.         /* origin Y */
    . b) W/ M& e% [1 o3 R
  788.         rbt->frame_load_buffer[14] = window_top & 0xFF;2 l) x+ o7 O+ ?: I7 j
  789.         rbt->frame_load_buffer[15] = window_top >> 8;
    1 e8 w: o! ~" w0 g; p- Y2 A, D
  790.         /* fragment payload size */
    # [) e$ L% i- q/ \# r0 G- j! L
  791.         rbt->frame_load_buffer[16] = (pb->byte_index + 10) & 0xFF;& Y) h% q, ?; [* w' z/ }
  792.         rbt->frame_load_buffer[17] = (pb->byte_index + 10) >> 8;
    6 }9 ?2 ~: Y( V5 p' l' V
  793.         /* fragment count (1) *// d/ Q, c3 V4 A1 ]: t/ r$ n
  794.         rbt->frame_load_buffer[18] = 1;
    . h, Z- u/ V8 S4 x- ?5 r
  795.         rbt->frame_load_buffer[19] = 0;
    # g3 S! p% z! N6 r! E# B
  796. 8 K' {  {. o. a" k. }
  797.         /* update the fragment header */
    ( g% ~# e6 x( x3 E" {! S: a
  798.         /* compressed size */
    & C- p$ _+ N% b2 j' w5 q( w
  799.         rbt->frame_load_buffer[24 + 0] = (pb->byte_index >>  0) & 0xFF;" i$ [5 v7 u  t$ j
  800.         rbt->frame_load_buffer[24 + 1] = (pb->byte_index >>  8) & 0xFF;5 s% R" z& w* m% N$ t/ u
  801.         rbt->frame_load_buffer[24 + 2] = (pb->byte_index >> 16) & 0xFF;
    1 D4 E) n  q" K6 s
  802.         rbt->frame_load_buffer[24 + 3] = (pb->byte_index >> 24) & 0xFF;
    9 E. V6 Y; I# o  U! }' f
  803.         /* decompressed size */3 f4 w' a% c1 t* }! w8 a
  804.         rbt->frame_load_buffer[24 + 4] = (window_size >>  0) & 0xFF;
    ! E' K  m3 q  g* `% O; [
  805.         rbt->frame_load_buffer[24 + 5] = (window_size >>  8) & 0xFF;
    2 T6 X- u7 A2 W4 f7 i  v. G
  806.         rbt->frame_load_buffer[24 + 6] = (window_size >> 16) & 0xFF;4 \! t  V3 P4 j( i
  807.         rbt->frame_load_buffer[24 + 7] = (window_size >> 24) & 0xFF;" J& a+ V" y1 D8 ~  w- O' {
  808.         /* compression format 0 */
    9 P- @/ n" C2 w2 j  d
  809.         rbt->frame_load_buffer[24 + 8] = 0;6 S' m. x! T7 Q' ^
  810.         rbt->frame_load_buffer[24 + 9] = 0;
    7 B% G$ t1 s! h% O1 @- j

  811. % t- F; o( {. T2 j
  812.         /* write the 24-byte frame header and the 10-byte fragment header */8 \$ H! h4 o5 H1 s' v8 G
  813.         if (fwrite(rbt->frame_load_buffer, 24 + 10, 1, outrbt_file) != 1): I' d. Q  a+ Y
  814.         {4 b( }0 q+ F" u
  815.             printf("problem writing frame %d\n", i);
    / @, J- j- Q6 F5 ?, X
  816.             return 0;. I( f- P/ X% h" S( C
  817.         }9 B/ W) P- o: C' z# r* L6 S

  818. % z- W% L8 h2 n
  819.         /* write the new compressed frame data */
    ( O8 O5 c; T* s3 h
  820.         if (fwrite(pb->bytes, pb->byte_index, 1, outrbt_file) != 1)8 a0 N' X+ b$ k2 h% d1 Q4 a
  821.         {% a9 k% R4 f7 C6 U9 {2 r
  822.             printf("problem writing frame %d\n", i);
    2 \! d5 q* ?( I' ^
  823.             return 0;+ h3 T3 ^7 |  u6 x6 c
  824.         }
    , g9 B0 W! h6 o) C4 P
  825. 9 {, r7 U& P# u; A1 j/ U
  826.         /* write the audio data */
    $ {5 N2 C" E3 L) l" T. F! v& [2 X
  827.         if (fwrite(&rbt->frame_load_buffer[video_frame_size], frame_size - video_frame_size, 1, outrbt_file) != 1)
    9 d. V6 ?+ J$ S+ L) b
  828.         {# `: U. ]+ S8 {
  829.             printf("problem writing frame %d\n", i);
    & L3 C8 ]( @& R9 S5 b1 P
  830.             return 0;2 U& x; c' K+ {4 Z4 W
  831.         }
    ! \5 P% g* e5 j

  832. 6 X; m$ u; i" c* ~% [" A
  833.         /* update the table entries */8 }$ [" y8 r4 ]' V
  834.         video_frame_size = pb->byte_index + 24 + 10;
    % r8 |) o. t: |, e( \% k! Z
  835.         frame_size = video_frame_size + audio_frame_size;
    % \& n7 N8 O8 u5 W
  836.         rbt->frame_size_table[i*2+0] = frame_size & 0xFF;
    , D3 [, e( o/ {3 E3 H  A
  837.         rbt->frame_size_table[i*2+1] = frame_size >> 8;
    * z1 L" u$ m; W1 |
  838.         rbt->video_frame_size_table[i*2+0] = video_frame_size & 0xFF;) P+ x2 t* t" [' [8 i6 T, j
  839.         rbt->video_frame_size_table[i*2+1] = video_frame_size >> 8;
    ! {8 ^0 X9 A: R3 G
  840.     }
    4 O; z) q1 e0 j  J
  841. - _9 ^! P7 J+ n  J" m
  842.     printf("maximum dimensions seen are %dx%d\n", max_width, max_height);6 |0 M$ i- ]; v; ~% {
  843. % g. B/ q6 G, o$ v* D
  844.     delete_put_bits(pb);$ {) U/ t1 K$ R- R9 h" S& _
  845.     free(full_window);* L; F. h4 m, S# g- A4 i0 y( [/ U

  846. * M% d" c! [7 \0 g6 A" Z/ I7 E
  847.     return 1;
    6 ?, F) X* e  {
  848. }
    8 q* }2 v" [- T: }+ ?% x- E( ~/ }  l

  849. ; n2 m! t6 V9 c! l) S" l
  850. int main(int argc, char *argv[])5 G( ^9 M+ c1 I+ C; {: U3 Q
  851. {
    ; O, _: [5 C1 U1 Z4 z/ R- A
  852.     char *subtitle_filename;: _: z. P! {7 v5 u4 B( x
  853.     FILE *subtitle_file;
    ' {9 V, J5 ~9 ~. J( Q
  854.     char *inrbt_filename;
    3 q5 E; F, }' I" i! c6 y3 ^9 G
  855.     FILE *inrbt_file;
    $ b; m* u$ Y7 F# |) o4 V7 }
  856.     char *outrbt_filename;, c, N- ]2 p  J! g6 i7 a
  857.     FILE *outrbt_file;
    ( H/ K( ?' |  X2 o6 Q. m3 w
  858.     rbt_dec_context rbt;
    . T# V' b8 c  Y, N) {/ c' v
  859.     int origin_x;
    $ y! W9 T. G# B- d( v1 u# H% m
  860.     int origin_y;1 L6 P2 M! Z* ^$ _! l+ @5 q
  861.     int window_width;& b) ?8 @/ z" l& }: _! d+ |! K
  862.     int window_height;
    * X# F' e5 h$ |% `0 z& j

  863. ! a5 U9 ^' x  c  S4 C0 U& \/ Y
  864.     /* testing the bit functions */
    1 \; B- q& G  ^
  865. #if 0! z5 J7 V- Z; x! u) ~4 Y
  866.     int i;
    ! }* \# ~$ ~6 n- }% E9 q: k8 w6 E) T, K+ V
  867.     uint8_t bytestream[] = { 0x55, 0xAA, 0x00, 0xAA, 0x55, 0x77, 0xFF, 0x1B, 0x70, 0x8F };
    3 u( I2 t% |0 _& a
  868.     int bytestream_size = 10;/ _$ G$ e( G" k8 B5 W8 J9 z
  869.     get_bits_context gb;
    0 ^* }/ n  }7 Q; v* \0 D& {" [
  870.     put_bits_context *pb;1 U, z( v! }3 h) L
  871.     int bits;
    1 B# U/ ^3 R) r. s+ [6 R# E

  872. 4 d5 i' |. v2 L' S% @, J$ q9 V
  873.     init_get_bits(&gb, bytestream, bytestream_size);$ Q9 }& T. K( ~! F/ A4 h$ I% T! p9 Z
  874.     pb = init_put_bits();( c" v  G5 O8 D" c

  875. : ^% f# o6 U2 g
  876.     for (i = 1; i <= 12; i++)# ?$ i* U; T4 ]
  877.     {/ J4 z2 G. S; _
  878.         bits = view_bits(&gb, i);
    1 s5 L0 K1 r% N. T4 x
  879.         printf("view %d bits: %d\n", i, bits);! l2 r* R6 w; I' E
  880.         printf("read %d bits: %d\n", i, read_bits(&gb, i));2 |  {; K* x$ V  {4 s3 p" |5 W
  881.         put_bits(pb, bits, i);
    . ~% A' g4 {7 Z! x. p
  882.     }; V& Z' f6 I( f* U9 e! G1 o
  883.     put_bits_flush(pb);) Z' k" e# V! ]- g; j

  884. . F/ Y3 }+ ^; J# `* z0 S
  885.     printf("original bytestream:\n");
    0 U7 k5 I- o+ z0 m
  886.     for (i = 0; i < bytestream_size; i++); D2 l3 S$ q0 U7 j
  887.         printf(" %02X", bytestream[i]);
    ) j& r) K" j! Z" N- z! J
  888.     printf("\nnewbytestream:\n");
    3 J, C8 Z; b- H! \& C4 z
  889.     for (i = 0; i < pb->byte_index; i++)
    ; l1 \, i$ p; x
  890.         printf(" %02X", pb->bytes[i]);
    , E  z) L) [/ N5 ]
  891.     printf("\n");! ?7 p/ m- ~* \3 W6 d- j* @
  892. " y2 _8 H: s6 [4 G: s
  893.     delete_get_bits(&gb);
    9 ~7 h+ G# l5 K7 G( E& w( f" _) t
  894.     free(pb);
    + R4 h, w* U/ }$ y5 D7 H$ K- h
  895. #endif
    " Y0 g3 k3 Z$ l# a+ L4 v

  896. ! N/ c$ z: K8 b* M3 \: t. O' ]) @
  897.     /* validate the number of arguments */( n5 E1 T/ ?. b& g9 |
  898.     if (argc != 8 && argc != 9)* C7 W! @% r. H$ O6 A8 x: y; y
  899.     {
    ' V: K7 v5 @- W
  900.         printf("USAGE: subtitle-rbt <subtitles.ass> <in.rbt> <out.rbt> <origin X> <origin Y> <width> <height> [dump_frames]\n");
    : ?2 R0 n/ J8 n3 u
  901.         return 1;- X  S6 O7 v* q2 [* L
  902.     }
    * N, E; o" `2 C+ d4 e6 j7 z
  903.     subtitle_filename = argv[1];
    ( J: Q$ |0 O6 K* h
  904.     inrbt_filename = argv[2];1 l& I, P" r& C9 H8 v  a4 a
  905.     outrbt_filename = argv[3];* t/ J1 y' E9 Y6 Y! P& D
  906.     origin_x = atoi(argv[4]);2 z" n8 e/ _/ @+ ?1 Z3 W
  907.     origin_y = atoi(argv[5]);. [0 o) ~" L( k$ V! g
  908.     window_width = atoi(argv[6]);
    / ?7 Q% [( n/ i% ~
  909.     window_height = atoi(argv[7]);; X* o" J$ B- i$ p4 D
  910.     rbt.dump_frames = 0;
    4 ~4 }7 T; @9 o7 i; r/ }! r
  911.     if (argc == 9)
    # c* b: Z, ?, \# a
  912.         rbt.dump_frames = 1;/ D! E3 |' U" z8 v! X

  913. % I" y5 O& E7 w* _( }: \7 i& L
  914.     /* verify that the specified input files are valid */
    ) E, A" Q6 F+ z
  915.     subtitle_file = fopen(subtitle_filename, "r");
    # d& e) F) J; k- {
  916.     if (!subtitle_file)
    $ `. N) r% t6 C- k# ^- o
  917.     {' C3 p6 t: {9 Y4 \) d: i/ O
  918.         perror(subtitle_filename);* ?5 ~+ ~; h5 ?- ~3 c2 Q4 p
  919.         return 1;
    2 _- `1 F4 M, T$ |& A" k' d
  920.     }
    . {& _* m- f3 B$ {$ @* u0 y, ?
  921.     fclose(subtitle_file);
    2 s/ M' e! R- a% Y2 l$ R
  922.     inrbt_file = fopen(inrbt_filename, "rb");+ Q) E% z# m8 a/ j
  923.     if (!inrbt_file), w, n! k/ a! l# }( G+ {
  924.     {' _( H0 z% o  ]3 Y( _& b( J( y
  925.         perror(inrbt_filename);' P) L( I8 K; l7 c  ~5 j4 z
  926.         return 1;
    2 K4 x: `9 o1 z, P
  927.     }
    . Y( B5 ~8 g9 f3 U, a; I( M7 V

  928. : j8 c7 H9 P1 R8 B6 z
  929.     /* initialize the subtitle support */
    / _4 Z6 j/ _5 L1 p3 z* t
  930.     rbt.ass_lib = ass_library_init();9 e; F2 i. H. L9 W, {. `4 k- x) o
  931.     rbt.ass_renderer = ass_renderer_init(rbt.ass_lib);
    ( H: m' g, ~; u4 g  b( U% t( L8 Z
  932.     rbt.ass_track = ass_read_file(rbt.ass_lib, subtitle_filename, "UTF-8");
    / P- x4 Z) H2 [
  933.     ass_set_frame_size(rbt.ass_renderer, window_width, window_height);) M! h5 {. r; P
  934.     ass_set_fonts(rbt.ass_renderer, NULL, NULL, 1, NULL, 1);' A# C5 R' d. q" S. K: ?* t$ x
  935. # C: A8 [# }8 e# U7 Q- t) m3 a
  936.     /* open the output file */
    4 N/ }' M, d. Q0 [9 c% R  m$ Z
  937.     outrbt_file = fopen(outrbt_filename, "wb");
    3 W8 l: v; S+ J5 s8 S
  938.     if (!outrbt_file)0 L8 B! L- q5 Q, s( |
  939.     {9 ]# ]- x3 B( P. i5 M; N; f
  940.         perror(outrbt_filename);8 `& R9 I) G9 ~* _
  941.         return 1;/ |3 l+ J# i2 j9 Q" Q% a
  942.     }
    " L8 i9 o* \7 ^- h4 l. k# R
  943. ; ]8 S* o% `; Y
  944.     /* transfer header from input to output */% W) @* l5 H  w
  945.     if (!load_and_copy_rbt_header(&rbt, inrbt_file, outrbt_file))5 J8 B# z" Z: g% H: B
  946.         return 1;
    9 ?! M$ j+ d6 n$ _
  947. : H2 J' q; K/ A, n5 N$ m+ y8 U
  948.     /* rewrite the frames */
    9 ?7 z4 ]" F+ _$ J; Y
  949.     if (!copy_frames(&rbt, inrbt_file, outrbt_file, origin_x, origin_y,
    0 j1 n, p" J& G; \5 g4 ?
  950.         window_width, window_height))% s0 w; W: t8 F
  951.         return 1;
    8 z6 s! D; _3 P2 T
  952. 8 ^/ p2 y2 ~) q1 n' r" x' V
  953.     /* write the modified frame size tables back to the file */
    ; C2 Z4 ]9 ~  ^# n9 C4 l: @
  954.     fseek(outrbt_file, rbt.video_frame_size_table_offset, SEEK_SET);' I' |7 f& i3 x4 i2 {
  955.     fwrite(rbt.video_frame_size_table, rbt.frame_count * sizeof(uint16_t), 1, outrbt_file);/ \8 `: E$ ?, a3 E
  956.     fseek(outrbt_file, rbt.frame_size_table_offset, SEEK_SET);& M2 S) ?1 b, y; S& h/ J
  957.     fwrite(rbt.frame_size_table, rbt.frame_count * sizeof(uint16_t), 1, outrbt_file);
    5 v: |* S2 G2 V! j# \7 n+ f
  958. + U5 W8 w* k: B+ {  ]: z3 t
  959.     /* finished with files */8 D5 c2 S9 i4 e  }* K- P
  960.     fclose(inrbt_file);4 o8 I* F# l' T7 Z
  961.     fclose(outrbt_file);3 I+ Y5 @! e/ ?3 C$ g
  962. " R# {7 V# ^' D
  963.     /* clean up subtitle library */
    % M7 T9 }! Q6 w5 l5 B' l2 T
  964.     ass_free_track(rbt.ass_track);2 M- n$ w7 K9 J
  965.     ass_renderer_done(rbt.ass_renderer);
    ' B: g( t! p* t
  966.     ass_library_done(rbt.ass_lib);- Q. _) Y0 c/ {1 j  t

  967. : n; `) @  Z/ T/ ~
  968.     /* clean up */
    % g7 N8 f  c! `; i
  969.     free(rbt.frame_load_buffer);
    * N, f9 U9 i9 q. T! H
  970.     free(rbt.video_frame_size_table);
    2 l% \4 [% M4 i  o2 p$ ?, v
  971.     free(rbt.frame_size_table);: S4 {+ A" Y- w. x) m

  972. & h4 ?6 M) n/ w
  973.     return 0;) S6 S& k; c" `4 ^  z. i  j
  974. }
复制代码
5 n+ Y/ _' N; {& p2 u3 p

$ f( n# y- e& n
; w6 D' N' {# X) O# j$ N- X
8 p" ^4 o& [6 J" x- V
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 很美好很美好 很差劲很差劲
回复

使用道具 举报

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

使用道具 举报

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

使用道具 举报

5#
 楼主| 发表于 2009-11-19 17:39 | 只看该作者
引用第3楼soring123于2009-11-19 17:07发表的  :
+ Z( t. P9 H" A- V2 q我记得是没字幕的 比较麻烦 都是视频的

2 ~1 D$ k: ?6 B- ~0 n给视频外挂字幕方式汉化也许能行。5 q$ V  d4 f, B# S$ B' V! t3 o& F" _
要结合dosbox和代理dll技术。
回复 支持 反对

使用道具 举报

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

使用道具 举报

板凳
 楼主| 发表于 2009-11-19 11:38 | 只看该作者
引用第1楼soring123于2009-11-19 11:09发表的  :1 L0 ~2 h% z4 `: G% v4 [; W
这游戏有字幕吗?

4 V3 C% N3 c( t2 b好像没有字幕,我说的是给视频外挂字幕方式的汉化。( U' h* Y% y' ]4 W+ Q+ \3 g" }
就像syberia2汉化版下面那行字一样。
回复 支持 反对

使用道具 举报

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

使用道具 举报

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

本版积分规则

冒险解谜游戏中文网 ChinaAVG

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

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

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

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