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

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

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

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

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

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

本帖最后由 shane007 于 2021-1-2 13:56 编辑
, b' a. J4 G& y5 _
5 x8 I* e, {( f) }/ S# v! E) s8 \9 v最近找到了一些和幽魂系列Phantasmagoria 有关的资料,
$ Q# K' _+ u; S1 ~$ N0 j4 m& c也许将来可以用于汉化。/ _  Q% o1 _! R5 l& c
% q; b/ `  {' m" _0 F. t
和日文版有关的信息3 S- z" q5 c' d! O  |. w6 m
http://anthonylarme.tripod.com/phantas/phintgtp.html! R  d3 e- G+ i0 f
) @, R% ~9 B1 O) r! Z, T3 D4 `
相关工具
7 u/ A. I$ J" @http://anthonylarme.tripod.com/phantas/phcheats.html
3 w, v. ]8 Z* F. `$ h) J-----------------------------------------------------------------------, X- ?# f; d* d( [' {
2012/1/2  更新
; G2 o' {& R4 [- V关于幽魂游戏的字幕
+ I4 w; D$ k9 r& r# H% APhantasmagoria subtitles function discovered - ScummVM :: Forums
6 M. s" f0 C% _5 |# x6 C0 S9 U- o6 `
VMD文件) t4 r( e2 _- U: ]; Y/ L* R* K
Subtitling Sierra VMD Files | Breaking Eggs And Making Omelettes (multimedia.cx)VMD - MultimediaWiki6 A* \5 i4 q( m! }1 X/ ?
- [4 c! M8 J2 r9 k$ K* G
字幕
3 d$ |4 b# G: a' w5 ESubtitling Sierra RBT Files | Breaking Eggs And Making Omelettes (multimedia.cx)* b; L  ?6 M- T

& N) W* M  V$ M: xFFmpeg/subtitle-rbt.c at feature/VMD_encoder · multimediamike/FFmpeg · GitHub! X$ D1 B; r  j# F* M) w( |6 E
  1. /*4 U/ B; y' V! f% V8 C+ G" q( D
  2. * subtitle-rbt.c
    % J$ e9 G) c: k  d/ J/ S% M8 p$ T
  3. *  by Mike Melanson (mike -at- multimedia.cx)* c% A3 {% ~* ~
  4. *, m( R4 w. R7 Z" N9 s
  5. * build with this command:
    6 f/ }0 q/ y. d( v$ S
  6. *   gcc -g -Wall subtitle-rbt.c -o subtitle-rbt -lm -lass' F$ K% c$ F/ i" g1 M: K7 C
  7. */1 }# F6 W) M! g" W# P) {! c* M

  8. 1 e9 G. D0 c2 J( c+ z4 M
  9. #include <inttypes.h>
    * h+ p0 o' o0 a0 a# }
  10. #include <math.h>' ?3 ~! n. x- |9 ?( _$ O* d. k
  11. #include <stdio.h>' q7 ]" C, _' X" w# D  l
  12. #include <stdlib.h>
    ( w4 a" G/ r+ q2 i6 H# s8 s3 [
  13. #include <string.h>, e9 j( O7 P1 ~- V" ^, L& ]

  14. ' s$ H$ H5 H9 h, j- x
  15. #include <ass/ass.h>
    9 _) u, ^+ w, u( `- g4 d5 N% ?

  16. ) E% Z' n/ }) o' y) a
  17. #define LE_16(x) ((((uint8_t*)(x))[1] <<  8) | ((uint8_t*)(x))[0])4 x/ M) N/ s+ K- Y& K+ T3 n; A
  18. 8 E: b! [  T5 K/ H3 C
  19. #define LE_32(x) (((uint32_t)(((uint8_t*)(x))[3]) << 24) |  \
    ) X0 Y. M0 L/ ^* s& y
  20.                              (((uint8_t*)(x))[2]  << 16) |  \
    ' I  u: Z! }1 o  a
  21.                              (((uint8_t*)(x))[1]  <<  8) |  \8 [  l6 o4 j$ H8 q7 G9 A1 Q+ C
  22.                               ((uint8_t*)(x))[0])" T0 X$ R/ `4 F2 b" _& _: h3 e" @

  23. 2 m! I6 {' s' J/ E9 N" M( [
  24. /*********************************************************************/# ^% [: u% F6 ]1 |! n2 G9 ~
  25. 7 P" B8 ]7 o8 ~6 X
  26. /* Bit reader stuff */3 h0 D% W( U( v4 d7 I
  27. 1 k% J: b! `" {  H; J3 K
  28. typedef struct
    , w6 Z3 y* h  p7 V: p2 p' F+ R& T
  29. {, g5 W& x' a' U4 [& [$ j5 \
  30.     uint8_t *bytestream;  r( W- u9 m, c7 Y7 Z& m7 e1 d
  31.     int bytestream_size;
    : b4 Y! r$ Q0 D% x& R
  32.     int index;
    / G% L8 h# P8 ~9 G" G4 s( o
  33.     uint32_t bits;
    9 s0 ~" F; A/ I* e* z
  34.     int bits_in_buffer;- @& E9 ?0 @2 @6 r" y3 b% f
  35. } get_bits_context;
    0 j) D/ _" Y4 J' y5 O7 e; [1 H7 u
  36. : O7 J+ x! M! `% @3 \5 I2 ?
  37. static inline void reload_bits(get_bits_context *gb)- f5 ~; Y) `) ?& F' g
  38. {( A! |* |6 X0 K/ {1 U4 y/ z
  39.     while (gb->bits_in_buffer <= 24)2 y6 Y/ X* f. ?* A( r; Q
  40.     {
    ! b- G3 z) m3 @
  41.         if (gb->index < gb->bytestream_size)4 ~  {: C' I7 h
  42.             gb->bits |= (gb->bytestream[gb->index++] << (24 - gb->bits_in_buffer));
    ) R# m& Q- p8 B/ c9 c0 @
  43.         gb->bits_in_buffer += 8;
    8 [9 s4 r6 V3 z; X- C$ Y! H; e
  44.     }0 X9 P; q; P6 H* C" ]( I( ?
  45. }& K) M( b- S, |2 R
  46. 0 d0 f2 B$ f5 l4 v/ b1 _
  47. static void init_get_bits(get_bits_context *gb, uint8_t *bytestream, int size)) T7 R' I" w. w5 j8 r- k2 w: i0 ^
  48. {
    ! L8 ?- q2 P  o9 e( E; t5 W9 D3 @
  49.     gb->bytestream = malloc(size);
    + j6 r) a: i& w+ u- c# @( i
  50.     memcpy(gb->bytestream, bytestream, size);* b4 v( J: i1 R' G( T; {- s' o
  51.     gb->bytestream_size = size;
    / g' Z- `2 a! i. K& G: P* \) q
  52.     gb->index = 0;
    5 \% ?# T5 Y  O: `- z. H3 ^+ ?
  53.     gb->bits = 0;
      |3 L/ O2 b  g5 g& D( L# y9 H" H
  54.     gb->bits_in_buffer = 0;
    - q2 w" ^* w' k2 V: C1 _
  55. 7 U4 Z  L- q/ o
  56.     reload_bits(gb);
    / t4 K) M/ W4 g  B( p: v
  57. }
    - Q3 V# t% b. g5 W* ]
  58. 0 ]2 s; v$ M7 Y
  59. /* read bits without consuming them from the stream */
    3 L3 f! H% I3 O5 H  e9 d+ D
  60. static int view_bits(get_bits_context *gb, int count)
    ' e4 W- S  y: I+ p
  61. {
      c+ O! P( @# d  u* J3 @2 a- k; e
  62.     if (count >= 24)
    0 y" n, v0 A6 `, C: j
  63.         return -1;
    2 v. [/ F3 O6 @- y% x
  64.     if (gb->bits_in_buffer < count)
    2 J$ L1 e2 s, v5 b( L; B7 e
  65.         reload_bits(gb);
    * H% N/ U/ ^* s' l( }8 v4 ~1 I
  66.     return (gb->bits >> (32 - count));
    : X& z) a% s1 l3 c( d
  67. }
    * \1 V; n% x; k- x' b
  68. 7 s* K- \0 S  z' E
  69. /* read and consume bits from the stream */9 y( q9 X/ X5 g1 U2 ?
  70. static int read_bits(get_bits_context *gb, int count)# ?* I* G1 A3 E- h3 u/ l! f
  71. {
    ; r8 r0 \; @1 u& u$ ?5 K
  72.     int value;9 l  G% p5 z- I9 `  a, K

  73. " Q( `5 w- O. T  M. _# C. o
  74.     if (count >= 24); H- M8 F6 M5 D6 t4 g: @
  75.         return -1;
    , [- }! r8 V5 P0 V$ N5 |

  76. & g! V/ n5 a* S' K; q1 Q# c6 D
  77.     value = view_bits(gb, count);" K7 S. f7 @  _2 Z! w) A! c+ f: _
  78.     gb->bits <<= count;
    ; S' Z7 E- P% K. Y1 ~( b
  79.     gb->bits_in_buffer -= count;1 l$ ~* X; P* [+ u! y" K% g) L/ x# u

  80. 0 ?" q& G7 X% O, u; e
  81.     return value;
    ) D9 C9 x3 b) s% x2 V. q: h3 I' c
  82. }
    & L+ }: w% \" w8 h( t
  83. , }3 y; M* x1 R0 z
  84. static void delete_get_bits(get_bits_context *gb)
    ) `( m: f% I7 R8 k/ @  E3 P. Z' {
  85. {
    * y: \2 p' V% u! W+ S4 i
  86.     free(gb->bytestream);
    3 K3 S: u, Q" s& |7 g
  87. }
    / F3 a0 h0 t# `
  88. - L9 a% u2 T$ X! M
  89. /*********************************************************************/! d; I! i! n2 X
  90. 3 e) s  X$ O2 r4 x! G, t
  91. /* Bit writer stuff */# c+ K6 P+ h8 q4 c
  92. , A( w, W7 p  l5 l# N0 l
  93. #define MAX_PUT_BITS_BYTES 630007 `4 G: }% ?  ~2 m
  94. typedef struct  \6 R& I' J2 G/ O! H! s+ _2 m! O
  95. {
    , \, {" i; ^9 w& H) {8 X7 h
  96.     uint8_t bytes[MAX_PUT_BITS_BYTES];
    * p0 l  ~' f  T3 L& }8 C
  97.     int byte_index;
    , T# u4 [7 d* h, ?8 m" U% s  b; s
  98.     uint32_t bit_buffer;
    , M( `3 i1 V4 E# R' w5 E3 Z" u3 l
  99.     int bits_buffered;
    2 W% ~/ M8 d: l! v
  100. } put_bits_context;$ S/ Z, W" b% P7 M# h. X( f: o
  101. 0 w0 N& q3 p" ]8 f4 a. g' \7 Q% A" @
  102. static void reset_put_bits(put_bits_context *pb)& w$ A4 M$ d1 L9 `( n  E
  103. {
    # g7 T1 w2 V9 c2 _$ k' v0 b
  104.     memset(pb->bytes, 0, MAX_PUT_BITS_BYTES);- h8 k5 M  O7 \
  105.     pb->byte_index = 0;
    & E/ y4 P8 l1 J6 a
  106.     pb->bit_buffer = 0;
    8 L5 t6 m! H. ]# Q4 X( y+ ~" G
  107.     pb->bits_buffered = 0;7 }  J  c  a! j7 o* E' N
  108. }
    / |! J5 _% @, l

  109. : _  n8 T2 Z! d
  110. static put_bits_context *init_put_bits()
    1 D% @: T' B9 E
  111. {
      T- |# e) {! s+ v
  112.     put_bits_context *pb;, C" }5 C- n! @# |
  113.   d& y7 b, D% J
  114.     pb = malloc(sizeof(put_bits_context));
    ! i- {) p& A( h' m2 Q
  115.     reset_put_bits(pb);
    ) g. y; _: [) P7 Z3 Z
  116. 3 ?% T6 X* K( A1 C5 p
  117.     return pb;9 J/ A4 \+ Y# l; {
  118. }) f- K  S; q+ S9 k
  119. ! C1 B) y" g! ]- V3 X1 c; Y- H
  120. static void put_bits(put_bits_context *pb, int bits, int count)# t( j+ q- {& z( g; s+ C! @
  121. {
      Q( h0 Y( C7 r- z. k% A6 D2 G
  122.     pb->bit_buffer <<= count;% ~0 W, {1 h+ Z/ }8 s5 X* W
  123.     pb->bit_buffer |= (bits & (~(0xFFFFFFFF << count)));- n) M! s# r8 I3 K: X1 u5 W" |
  124.     pb->bits_buffered += count;
    ) Q) p" e' J# [0 Q$ {$ L" {
  125. ; ]2 d5 m# u0 L* m' [' B
  126.     while (pb->bits_buffered >= 8)
    8 M3 X! w( N( S
  127.     {( ~8 o" G. y2 ?& Q0 W
  128.         pb->bytes[pb->byte_index++] = pb->bit_buffer >> (pb->bits_buffered - 8);
    / i# m$ [* N6 V2 D6 ]. ^
  129.         pb->bit_buffer &= (~(0xFFFFFFFF << (pb->bits_buffered - 8)));
    ' L' [& I' a6 u! c3 k3 F/ X- J/ u
  130.         pb->bits_buffered -= 8;# H' u, E8 \, f+ b- {8 x2 f  ^
  131.     }3 Q* {9 O0 K+ r; r% F+ u: F
  132. ! d! u' j; y& O) z- O
  133.     if (pb->byte_index >= MAX_PUT_BITS_BYTES)4 n( L0 n) E9 ?0 [* @
  134.     {! o/ ?& S6 I3 |  w1 g+ ~
  135.         printf("HELP! Bit overflow\n");% |% b, z5 x' I( F0 a9 u8 X. y  B
  136.         exit(1);
    ' j7 d- a6 E7 j& N4 `
  137.     }5 b: n+ H! E5 K' p5 j6 T
  138. }; F# Y0 _/ }/ }. t; `0 v2 \: c3 f
  139. ! S  h8 T, M3 ?  p0 j6 u
  140. static void put_bits_flush(put_bits_context *pb)
    1 E) K- F; C$ ]. X9 G) [; v) f
  141. {$ L" J4 u6 z$ O7 s& G
  142.     if (pb->bits_buffered > 0)3 z& I7 l* k2 M; x3 A
  143.         pb->bytes[pb->byte_index++] = pb->bit_buffer << (8 - pb->bits_buffered);0 H1 }( a/ ~5 }& g( r0 X& a
  144. }
    6 a8 s& S/ ~! n* H5 y
  145. ' n& w5 z* L6 r2 O
  146. static void delete_put_bits(put_bits_context *pb)
    $ U9 o0 n: ?4 g% V3 I
  147. {
    ' \+ ^5 f/ }+ s1 k4 V
  148.     free(pb->bytes);' I1 p; ^6 s( c1 c6 |
  149. }6 }0 M5 N4 D% O2 d$ F
  150. 8 Z2 l0 A0 Q$ P7 c+ K" Z" l
  151. /*********************************************************************/
    ! V5 u, y- V8 B/ ~
  152. / y# f/ a. t( I( P
  153. /* RBT functions */
    * P. J/ _+ O$ O1 h% S# s, X9 `
  154. $ r  ?2 ~! I) V. [$ y& l
  155. #define PALETTE_COUNT 256
    " `4 T; q  J$ A/ w5 M
  156. #define RBT_HEADER_SIZE 60, M) D8 b0 Y/ y5 b. j
  157. #define UNKNOWN_TABLE_SIZE (1024+512)
    ! @1 a2 r. M' Y2 |% u
  158. #define SUBTITLE_THRESHOLD 0x70
    ! m& ?/ h: @6 Z$ ^5 o
  159. #define MILLISECONDS_PER_FRAME 100
    $ P% k+ F3 b% K! y) D2 d3 }

  160. * b! r7 e& i. v, [# D
  161. /* VLC table */3 f6 d9 u1 V' a' T1 ~+ p6 c; \7 ?
  162. #define VLC_SIZE 47 ~& e2 k6 J0 }
  163. static struct0 {. W2 y" h/ g$ p
  164. {
    * ?$ f2 Q/ z1 M# s" ]. y) ?
  165.     int count;
    ) _; C, h- W" f, \0 T) z+ I- R$ f
  166.     int value;
    $ a$ s: J( v5 [' T$ w& i- R
  167. } lzs_vlc_table[] =
    3 a4 |# B# _& ?0 e$ g$ ^
  168. {
    0 }2 k& [: Q0 K8 S# M) F$ f$ r" k
  169.     /* code length = 2 bits; value = 2 *// z2 @# {; x+ Y& P  P8 q7 r6 c
  170.     /* 0000 */ { 2, 2 },' H2 t9 O3 U' c/ u
  171.     /* 0001 */ { 2, 2 },
      Q" b: \) k( |& t/ D0 e; Q9 m
  172.     /* 0010 */ { 2, 2 },
    2 D0 Z+ x1 n2 ^
  173.     /* 0011 */ { 2, 2 },
    2 k# j: q8 N0 @! R0 n, R

  174.   x, N: \4 ~8 q6 J; E/ ?
  175.     /* code length = 2 bits; value = 3 */6 X2 l) q  C1 ~( w
  176.     /* 0100 */ { 2, 3 },0 Z7 ~( Q$ Y# [! ?8 [1 G; [0 ?
  177.     /* 0101 */ { 2, 3 },
    $ s) ]2 E- p. q& H6 M% r% \
  178.     /* 0110 */ { 2, 3 },& m2 s  _0 r5 p
  179.     /* 0111 */ { 2, 3 },9 O  G, F3 Y2 b4 T
  180. & U) h" T( G- r' ~
  181.     /* code length = 2 bits; value = 4 */
    6 y7 m/ n" P+ m7 [4 J$ H
  182.     /* 1000 */ { 2, 4 },: h  T2 \0 O3 a7 V
  183.     /* 1001 */ { 2, 4 },. w, a" b0 s. G9 ?7 C8 D
  184.     /* 1010 */ { 2, 4 }," `' h4 E) c; v; @% G
  185.     /* 1011 */ { 2, 4 },' f  S: ?; R# s, X" N4 L
  186.   ^) S$ [5 Y8 Q0 N% A+ C$ q5 L' B
  187.     /* code length = 4 bits; value = 5 */
    4 ~4 q- ^. e8 j) Y$ S- B) b
  188.     /* 1100 */ { 4, 5 },! e, }, J2 t/ c' N" E" {$ W
  189. 5 W0 G) y* B6 J
  190.     /* code length = 4 bits; value = 6 */7 I% l5 \9 y$ ]
  191.     /* 1101 */ { 4, 6 },6 y3 M: b: w7 K+ S4 ~1 j! W

  192. ) t7 @9 Q- e9 P& N; B8 S2 ]
  193.     /* code length = 4 bits; value = 7 */
    5 f$ y/ w8 C$ _; x5 i* Y
  194.     /* 1110 */ { 4, 7 },8 N! H5 `1 {! Q, E$ u# ]

  195. & n' j1 a, W7 `; X# r& w! A
  196.     /* special case */: r& {- H3 h4 P
  197.     /* 1111 */ { 4, 8 }* z' d- g' x" X- u" u: i. Q4 @
  198. };
    5 ]4 E. e2 _& u* ~- G( y4 C/ {
  199. 4 L, @6 `; j" t0 Y
  200. typedef struct
    # M" N1 K- h5 x& v9 Q  C
  201. {
    # ]9 m% K/ M3 }% Z& C7 Z1 k
  202.     int version;
    & I  m$ n& g/ C) q$ O
  203.     int width;
    : H# L9 P0 p6 j  @3 z2 d  c9 p
  204.     int height;1 V) h/ U4 _5 A$ Q
  205.     int frame_count;0 @' T& ^* q- I9 X
  206.     int audio_chunk_size;
    " s' W$ C4 \: j3 v
  207.     uint8_t palette[PALETTE_COUNT * 3];
    9 X2 h8 i" z5 y+ o0 o
  208.     off_t video_frame_size_table_offset;3 x( V# o4 I% K% A; z
  209.     uint8_t *video_frame_size_table;' W& I$ g4 ~4 L6 k
  210.     off_t frame_size_table_offset;
    " q' E3 g; `% ?% C. `$ i/ g& z
  211.     uint8_t *frame_size_table;. z9 o3 l% V, `- X
  212.     uint8_t *frame_load_buffer;
    % @: l; `8 s7 ]$ n
  213.     int dump_frames;4 k- |5 D: e4 w

  214. + ^: [6 b! @& {7 C$ o" U; ^$ a
  215.     /* subtitle library */
    " N9 _, V7 r/ P2 o
  216.     ASS_Library *ass_lib;3 {8 J6 U" Q* G: n
  217.     ASS_Renderer *ass_renderer;
    9 `1 }5 }" a9 v
  218.     ASS_Track *ass_track;
    6 i) |0 U9 L% s8 k; d/ v5 n
  219. } rbt_dec_context;
    $ f4 |# L* o. Q) _' u) t0 n

  220. # f0 [3 A" e) k. u$ ?3 E
  221. static void dump_pnm_file(char *filename, rbt_dec_context *rbt,2 D. Q8 x3 r$ x. O8 D
  222.     uint8_t *image, int width, int height)
      v2 h, @! M/ G$ j% T2 n) I& T9 @
  223. {
    & N$ y5 S& e# }9 L
  224.     FILE *outfile;
    : J0 h' |$ h0 V( d8 U( {; n
  225.     uint8_t bytes[3];
    - u2 O1 E1 k" j9 U3 v/ I
  226.     int p;( @) u$ V% T0 E! D# _* l; t% @
  227.     uint8_t pixel;8 a  ]& `& f. W/ U1 T+ b

  228. . U( B. k' V$ v1 N/ K) [
  229.     outfile = fopen(filename, "wb");
    $ n: e! p6 @$ D4 x( `
  230.     fprintf(outfile, "P6\n%d %d\n255\n", width, height);
    5 ]: k! u0 m  ]$ |1 G: K; [
  231.     for (p = 0; p < width * height; p++)" R8 M& }- r. E5 n/ C; [
  232.     {, M8 V% a& Z! `) ~
  233.         pixel = image[p];
    6 c- \, P7 N- G7 ^6 _; D6 A' W
  234.         bytes[0] = rbt->palette[pixel*3+0];- u/ S6 J* ~3 I' B! s: G3 y
  235.         bytes[1] = rbt->palette[pixel*3+1];4 s# |$ \! |& o, W4 @/ s: h
  236.         bytes[2] = rbt->palette[pixel*3+2];
    8 r' ^" ~5 u. I+ X! L! L$ D
  237.         fwrite(bytes, 3, 1, outfile);
    3 O, V5 @9 ?& g. a5 e
  238.     }
    $ N- h" P: l% D- `) Z6 _8 h5 d
  239.     fclose(outfile);5 H, M$ n0 G% |) L1 M3 @
  240. }
    # D  T: O/ U- K: r( ~
  241. $ u$ G: G8 F* P8 q/ [9 [  O
  242. static int load_and_copy_rbt_header(rbt_dec_context *rbt, FILE *inrbt_file, FILE *outrbt_file)# V1 [  i. g- g4 H) A" g( ~
  243. {
    ! B, J. N/ y* ^1 `* H5 ?6 G
  244.     uint8_t header[RBT_HEADER_SIZE];& E- E- |. Z; ^; I: ?& ?& d( B
  245.     int palette_data_size;" r9 w3 h) V- R$ q( n4 n
  246.     uint8_t *palette_chunk;* D6 m* Y4 b  z; N' {( |) s( w
  247.     int unknown_chunk_size;
    . X) W3 ]: d$ L3 k
  248.     uint8_t *unknown_chunk;
    * T( E- S& M+ @) }" F- j+ ^* V8 h; |
  249.     uint8_t unknown_table[UNKNOWN_TABLE_SIZE];
    7 @& x4 E" u$ ~8 M" q* w
  250.     off_t padding_size;8 z6 N) x; X; ]0 e' I5 ], E# y
  251.     uint8_t *padding;
    : H" @- R& J$ K
  252.     int i;
    1 c' y; C* C3 I0 v) F
  253.     int frame_size;
    7 d! E  h  x  t9 k2 ^2 _
  254.     int max_frame_size;5 d; H0 i* q1 ]$ w7 Z
  255.     int first_palette_index;
    % X% t: z% B! \7 W" _5 D" r5 u( A8 ^
  256.     int palette_count;
      h' p. n( Q2 s; Y" k: I( ?; w3 I# i
  257.     int palette_type;+ R2 i9 u1 _8 g6 T3 b2 S
  258.     int palette_index;: a5 S  o8 r, c, d
  259. % f: y$ n) Q% V7 m9 c" O/ W. T
  260.     fseek(inrbt_file, 0, SEEK_SET);
    " X1 I+ |$ F) s$ ]
  261.     fseek(outrbt_file, 0, SEEK_SET);$ d0 ?6 ?7 [# k$ C- r

  262. ) t, E6 z  U( J: n
  263.     /* load the header *// J) @% i# ~# Q% N  y
  264.     if (fread(header, RBT_HEADER_SIZE, 1, inrbt_file) != 1)6 O9 E# j. Q& T$ t9 D5 S! d. _; O
  265.     {) J3 `% c1 M! p  g
  266.         printf("problem reading initial RBT header\n");
    ' S. X; j$ u( P. z
  267.         return 0;
    ) h; K$ F2 ]) Z1 ]+ Z. `
  268.     }) s6 l' u; {  c# G6 L
  269. + s& r, D; ]: |9 S$ u
  270.     /* copy header to the output */3 H+ g1 N& V& a+ e( e+ u
  271.     if (fwrite(header, RBT_HEADER_SIZE, 1, outrbt_file) != 1), U1 i$ Q- y& @2 Z) y
  272.     {
    3 Y  c8 ?% A* f- D( k- [
  273.         printf("problem writing initial RBT header\n");' R+ f- a; {: q! l
  274.         return 0;
    $ Q$ O2 v0 M/ U8 B5 V
  275.     }
    6 T( O8 Z+ q# R; |

  276. : s8 f7 K8 Z0 e& r- o
  277.     rbt->version = LE_16(&header[6]);
    ! D: b9 p2 T8 n/ B
  278.     rbt->audio_chunk_size = LE_16(&header[8]);
    & V( i0 J) f# W2 y5 w
  279.     rbt->frame_count = LE_16(&header[14]);
      Z8 F& j% ~4 ]' o" ?! p) i! f; }

  280. - F- c+ M: A$ h2 W# s
  281.     /* transfer the unknown data, if it's there */% |7 K8 C" ]* s- N9 u3 F0 b* C
  282.     unknown_chunk_size = LE_16(&header[18]);
    9 j" }: [: T+ B
  283.     if (unknown_chunk_size > 0)
    ( T9 ~, I6 {; z" N
  284.     {
    , M- q6 G  x4 n8 C+ p: o
  285.         unknown_chunk = malloc(unknown_chunk_size);
    * W! y% ^3 i( E  u' m
  286.         if (fread(unknown_chunk, unknown_chunk_size, 1, inrbt_file) != 1)
    ; P' i# k  T7 V# [3 {3 Y% I+ P
  287.         {
    9 ]/ m: j, p" ~6 ?, K0 _: H
  288.             printf("problem reading unknown data\n");  ]7 Y6 }3 {$ o1 E# G" S8 M5 E6 V
  289.             return 0;
      R# w% s) ^8 S9 u3 ?9 `9 s
  290.         }
    1 u" y7 ?' p( Y$ p, I
  291.         if (fwrite(unknown_chunk, unknown_chunk_size, 1, outrbt_file) != 1)* Y7 d3 `. L/ K
  292.         {
    5 X; m7 Y. c" F+ R; T
  293.             printf("problem writing unknown data\n");9 F, ^3 a7 E, ]& j& n
  294.             return 0;
    6 x& w4 |  B) W& [  c- {2 F
  295.         }
    4 k- ]; g- V' a: R
  296.         free(unknown_chunk);5 P1 G8 `4 j1 u0 O" W# N1 u8 b  a9 Z
  297.     }0 A, V% h8 p; c  C

  298. . [) [/ [! }0 c) l' q, P5 y7 V
  299.     /* transfer the palette chunk */
    : a( N$ m0 Q! _5 d7 a  n% V
  300.     palette_data_size = LE_16(&header[16]);
    # k5 r4 `% x; w  H& D1 o5 L1 F
  301.     palette_chunk = malloc(palette_data_size);' ]- @# e2 x, Y, Q1 A: ?
  302.     if (fread(palette_chunk, palette_data_size, 1, inrbt_file) != 1)0 Y+ G7 ~1 d2 f7 K
  303.     {
    + R) v; x7 p1 O8 B1 x0 D
  304.         printf("problem reading palette\n");
    ) j- R0 {: j' D8 ^  P
  305.         return 0;5 _3 Y# m+ @0 g! f0 h( S: n
  306.     }
    2 j1 [/ z6 ?5 M) T$ r) M! s
  307.     if (fwrite(palette_chunk, palette_data_size, 1, outrbt_file) != 1)
    # y6 P: q5 r( m" X4 K5 E4 L
  308.     {
    # m7 v1 q. m2 ?; |  ]
  309.         printf("problem writing palette\n");
    ' a7 i8 W& K" u: d" P& C) g' T8 `/ g
  310.         return 0;; b4 L. d% Y* G3 S5 X1 ?4 h+ K. `5 \
  311.     }) m) U; |) J/ I. W
  312.     /* load the palette into the internal context */
    + |- G( ?" B# R9 W+ M9 E
  313.     memset(rbt->palette, 0, PALETTE_COUNT * 3);: ?2 y6 b$ G, Z1 u5 L0 G; Q. q  Y0 J
  314.     first_palette_index = palette_chunk[25];
    $ z- ]' e8 G+ Q7 O1 T% e
  315.     palette_count = LE_16(&palette_chunk[29]);
    ; y3 D5 W# H$ ?0 \7 |1 N$ m: r4 N$ n
  316.     palette_type = palette_chunk[32];$ U) |/ F+ M% G5 w: a
  317.     palette_index = (palette_type == 0) ? 38 : 37;. N: h+ x  M5 |6 \" V" ~$ X2 f
  318.     for (i = first_palette_index; i < first_palette_index + palette_count; i++)/ y, [* z9 j7 d* Q
  319.     {, A$ v4 y8 }+ ?( T  a
  320.         rbt->palette[i*3+0] = palette_chunk[palette_index++];
    # ~% x& m" `% V
  321.         rbt->palette[i*3+1] = palette_chunk[palette_index++];
    + W/ D7 K9 q. t, b. b
  322.         rbt->palette[i*3+2] = palette_chunk[palette_index++];- F+ }1 w! L# y' m. B
  323.     }7 ?6 D5 r/ L# h  H9 Z
  324.     free(palette_chunk);; y; _9 z! j! H: z

  325. / M* ~* S1 i3 ^
  326.     /* copy the video frame size table (2 bytes per frame), as a placeholder */# Q# ^# q( J! X/ q# ^$ o* f
  327.     rbt->video_frame_size_table = malloc(rbt->frame_count * sizeof(uint16_t));" Z3 D% d  }0 f2 v" P! v
  328.     if (fread(rbt->video_frame_size_table, rbt->frame_count * sizeof(uint16_t), 1, inrbt_file) != 1)1 p4 o" R+ j  }
  329.     {, J8 X; J- L; O+ ~
  330.         printf("problem reading frame table\n");
    ! R9 `2 D% ]2 C3 @8 x# Z; y
  331.         return 0;
    2 k3 E* B3 A( t: k( z
  332.     }9 G% {2 o7 V1 C
  333.     rbt->video_frame_size_table_offset = ftell(outrbt_file);1 S* C/ [: l  \. i* b6 }1 |" W
  334.     if (fwrite(rbt->video_frame_size_table, rbt->frame_count * sizeof(uint16_t), 1, outrbt_file) != 1)
    / @" O. W( w  h7 C
  335.     {" e1 n' g: r+ a7 x9 S8 R
  336.         printf("problem writing frame table\n");
    2 w/ B( c: h+ ^) b( ^; Z
  337.         return 0;1 ^: \, h! W2 ~
  338.     }! N/ Z  {) U7 M5 Y) ?
  339. , F$ H5 ^/ C8 A: Q- |
  340.     /* copy the frame size table (2 bytes per frame), as a placeholder */* e1 O. P6 p/ g- p
  341.     rbt->frame_size_table = malloc(rbt->frame_count * sizeof(uint16_t));
    ; w1 n8 B2 D) j# R+ T' ?1 i% s
  342.     if (fread(rbt->frame_size_table, rbt->frame_count * sizeof(uint16_t), 1, inrbt_file) != 1)
    , {3 q2 T" s2 N5 D
  343.     {
    ( P4 n1 B" x* r( G
  344.         printf("problem reading frame table\n");
    4 P  O) w( c4 V! @; p. I* [
  345.         return 0;* A) U+ g- {9 X
  346.     }3 k0 O( ?  f6 B  K
  347.     rbt->frame_size_table_offset = ftell(outrbt_file);
    ; `( ^/ l! o+ @! K
  348.     if (fwrite(rbt->frame_size_table, rbt->frame_count * sizeof(uint16_t), 1, outrbt_file) != 1)! G/ t2 u5 R% \
  349.     {0 p, Z+ _  [3 }2 I- b/ J. B
  350.         printf("problem writing frame table\n");
    6 h2 d# L& W! Z
  351.         return 0;/ `; [: Y8 L" Y  @; B; H/ U
  352.     }8 ~2 n9 i. [6 I: o
  353. % A7 y* U2 y# ^
  354.     /* find the max frame size */
    ' n4 V+ {5 p9 D* [
  355.     max_frame_size = 0;; G! P4 m$ s( a% l3 t# n: L# E
  356.     for (i = 0; i < rbt->frame_count; i++)
    5 Q: V9 I( _8 K" L' T
  357.     {
    7 Z/ F% V# I1 X8 q
  358.         frame_size = LE_16(&rbt->frame_size_table[i*2]);
    " P6 \  J( d0 u( |7 [
  359.         if (frame_size > max_frame_size)
    0 c8 s8 o" }( j  |
  360.             max_frame_size = frame_size;
    0 d- f# u3 Y6 c/ H6 _4 x
  361.     }
    0 K+ e' ]! X  ^! L8 v
  362.     rbt->frame_load_buffer = malloc(max_frame_size);
    . D% M+ |2 k2 t4 L1 x' C: h
  363. . {" v( Y5 d! v7 E/ G
  364.     /* transfer the unknown table(s) */
    $ ^* h) x, ?/ `2 f2 r* j8 N6 O
  365.     if (fread(unknown_table, UNKNOWN_TABLE_SIZE, 1, inrbt_file) != 1)) h/ @, A! X* Z& q% L7 E* d/ {/ r
  366.     {
    ; @' ^: I2 z! J  A( R; T* z
  367.         printf("problem reading unknown table\n");
    * J9 {; J$ H/ ?, F% y! B
  368.         return 0;
    - d. A/ Y' Y# E! h) w
  369.     }' Z( s# n, ]. u/ b! x
  370.     if (fwrite(unknown_table, UNKNOWN_TABLE_SIZE, 1, outrbt_file) != 1)0 i: \8 a. c3 P8 V9 J
  371.     {
    4 _3 H" Y& K! z: `
  372.         printf("problem writing unknown table\n");8 Q* ^; W3 s  z" w5 H! T; A
  373.         return 0;
    2 ?, C8 G2 f6 p( ]' M8 L, Z; r$ V
  374.     }
    4 f: F* G5 F/ r6 i% O+ h) Y

  375. 8 o  \: n# l3 Y! U
  376.     /* copy over padding */
    $ L5 {0 a+ }. x! o% p
  377.     padding_size = 0x800 - (ftell(inrbt_file) & 0x7FF);
    # p4 J, ?3 \) |  a- C
  378.     if (padding_size)4 K) k9 i5 u5 [6 z9 u
  379.     {" k# _2 q  X3 r& s% G
  380.         padding = malloc(padding_size);
    3 m: n3 \# ]! p$ }4 G% ^7 e
  381.         if (fread(padding, padding_size, 1, inrbt_file) != 1)8 N4 e4 W1 C0 a  n
  382.         {! P( i- ?4 J7 U8 C; j' c- O$ ~
  383.             printf("problem reading padding\n");
    / b5 r( B- Q" a
  384.             return 0;
    % [$ A# _$ `9 v5 v) e0 ?- r4 W
  385.         }
    9 Z+ a1 {$ q. a$ s. A1 v
  386.         if (fwrite(padding, padding_size, 1, outrbt_file) != 1)
    : R6 [. a7 @9 k) u
  387.         {
    ( @- Z5 e3 e* t( [
  388.             printf("problem writing padding\n");, e# E4 H3 o, A
  389.             return 0;
    , @3 l( ?2 t4 ]8 h' U- G
  390.         }
    ( m0 w. U# f8 E. ]
  391.         free(padding);" e$ {( \; F7 D& Q
  392.     }
    & V8 H  \+ _& i
  393. 8 q" n7 g6 _7 H" G8 Z- r" S7 _4 R
  394.     return 1;9 _* `8 Q$ Y2 r$ j
  395. }
    ) ?7 q5 w" U$ J
  396. $ j/ P4 y% p; N1 M4 A6 D
  397. static int get_lzs_back_ref_length(get_bits_context *gb): r+ W. t9 W1 ~
  398. {
    . o! v+ v6 g. E; k" x% N9 ?0 m9 f
  399.     int vlc;6 A/ S# Z1 h% X# {
  400.     int count;
    2 o6 T) m9 s! w9 T4 w* R
  401.     int value;
    5 U% d8 y3 T5 l( w0 _# I

  402. " [: d$ g, p7 a' }. y! y& H
  403.     vlc = view_bits(gb, VLC_SIZE);
    1 x! o% F) @# |; E6 q
  404.     count = lzs_vlc_table[vlc].count;6 t1 B4 b4 @0 q: a1 J! N
  405.     value = lzs_vlc_table[vlc].value;
    1 I9 }6 L0 @2 z) U8 s5 H

  406. . F8 E! o$ O, @9 l5 q
  407.     read_bits(gb, count);+ _. g+ K! F# i  q$ H
  408.     if (value == 8)' b% p4 [% s: _4 l( G
  409.     {
    * \3 _) Q/ X9 c, L6 R- }( u
  410.         do
    % \5 ~3 b# }0 q1 ]6 a4 Q9 v& A! {. U
  411.         {
    ( O* Q8 |4 {0 Y, o) J8 f
  412.             vlc = read_bits(gb, VLC_SIZE);0 D& ]$ B" Q0 M) ?$ z
  413.             value += vlc;
    9 p, a( _% F; R! j& A* D
  414.         }
    . l% H. x4 `6 f7 y  E
  415.         while (vlc == 0xF);, z/ b) W3 ?/ P. z5 p- B7 I
  416.     }
    + m! q( [4 j. K- T$ g

  417. ; K0 w. E; \* {5 g5 {/ c( z
  418.     return value;. {+ U* y+ c. F2 R; Y8 D* D
  419. }
    ! K1 K4 ?2 C( ~8 ]3 E  _/ t7 `

  420. + b5 A- |' D4 k4 Q; h  ]! k
  421. static void compress_window(put_bits_context *pb, uint8_t *full_window,& X+ \$ q+ e/ T4 }4 ^& g$ \
  422.     int full_window_stride,
    ) a# J  Z! v2 R+ ^- T! k9 }8 H9 O+ q
  423.     int window_top, int window_bottom, int window_left, int window_right)
    5 l7 I1 o4 }( p4 L) S( [1 t+ `  P
  424. {
    % a2 S$ X2 u, w5 Y) `) y0 C; j
  425.     int last_pixel;
    : E' _4 y- V1 K8 D
  426.     int run_size;
    . V7 B9 ^: t0 N
  427.     int x;! g+ Q- E" z6 P) k+ w/ p) T
  428.     int y;
    * ?6 ?" N$ k' ?2 k: ]6 S
  429.     int start_index;7 p% s% X7 O7 ]0 ~
  430.     int end_index;
    * F6 m( B% n' |$ J  i2 d
  431.     int encode_last_run;# R1 F5 E' Y, V2 e- h8 p

  432.   S. R5 |$ M+ ?$ V2 ?
  433.     last_pixel = full_window[0];
    6 N4 g: A& W7 ~% G& H
  434.     run_size = 1;
    - _2 X8 j$ _: y0 z  ?5 U4 _
  435.     for (y = window_top; y <= window_bottom; y++), s- M9 n# p9 H* C8 v
  436.     {3 V% C' T" X9 k& W: R7 e) \
  437.         start_index = y * full_window_stride + window_left;
    , y% k, P) c3 j
  438.         if (y == window_top)' V/ e* W, [1 E( U
  439.             start_index += 1;, _5 `  |/ Z/ {2 a
  440.         end_index = y * full_window_stride + window_right;
    * B# }) N5 h1 w& O/ u  H
  441.         if (y == window_bottom)0 B3 C% l# H* }% K& J
  442.             encode_last_run = 1;
    $ D1 I. v9 m$ S8 Y* m: f. M) J
  443.         else6 G. q: b1 ~9 [( H+ M8 A2 O- _
  444.             encode_last_run = 0;- H% |: l5 l3 K1 D; B2 m0 U" @2 i
  445.         for (x = start_index; x < end_index; x++): l' B6 q3 {' T- Y  R4 {2 e
  446.         {
    ! Z& Q2 ^; t' u6 X
  447.             if (!encode_last_run && full_window[x] == last_pixel)
    7 K2 V. P# ~9 T7 T  f
  448.                 run_size++;  D/ k8 p2 K. p: }2 I
  449.             else5 e  M' n7 S* u3 R& ^, z) R' Q
  450.             {
    3 _8 w2 @* E5 U! O# c
  451.                 if (run_size == 1)
    ! I. Z! d+ O0 g' O
  452.                 {
    1 I7 n9 `7 K! ?
  453.                     /* encode a 0 bit followed by raw pixel byte */
    6 h, z( Z8 V$ d6 }4 O
  454.                     put_bits(pb, 0, 1);' p+ R. X* ?. P" @8 B" `$ n
  455.                     put_bits(pb, last_pixel, 8);
    " |, ?/ S( _2 x) B6 g" g
  456.                 }2 r, {( _1 E# a) H$ a6 l* H
  457.                 else if (run_size == 2). I' b7 n* N/ I: G4 |3 U8 A
  458.                 {, Z2 F! u# m* R* k' a- T* s
  459.                     /* encode a 0 bit followed by raw pixel byte */: x- c5 z, {6 Y. E
  460.                     put_bits(pb, 0, 1);+ _: W! H! f' Q
  461.                     put_bits(pb, last_pixel, 8);
    % ?9 k9 ^- Z& K! k7 L1 g
  462.                     put_bits(pb, 0, 1);
    ! E( N3 b( P9 l
  463.                     put_bits(pb, last_pixel, 8);/ r6 j( G- g4 z  X
  464.                 }
    0 {! _8 y5 L( q( V
  465.                 else4 T3 ?* n; F' B: o4 Y
  466.                 {) e- I+ S, j" ]! n3 r/ C
  467.                     /* encode a 0 bit followed by raw pixel byte */
    # j9 ?8 V/ y0 ~7 g2 s9 a! ?
  468.                     put_bits(pb, 0, 1);1 V1 J* z# t+ D7 p  W
  469.                     put_bits(pb, last_pixel, 8);
      [, O5 [3 A" u2 |$ M/ b
  470.                     run_size--;
    / D* S) h; r# @: q
  471.                     /* encode a run: a 1 bit, followed by a back reference" v' w5 u) J% p( ^' B9 s
  472.                      * offset (-1), followed by a length */( g# R, Q: d2 i( H7 v7 J- g  \  B
  473.                     put_bits(pb, 1, 1);( O! U  X2 _0 Z$ w8 M
  474.                     put_bits(pb, 1, 1);  /* 1 = 7-bit offset */5 W  |4 M& F4 E; c' f% r: }
  475.                     put_bits(pb, 1, 7);
    " B+ _2 j1 _" R# T' c0 r
  476.                     if (run_size <= 4)$ k1 U0 n- E  O! U
  477.                     {
    8 ]3 r& U' N+ j6 ^' {( _
  478.                         /* lengths 2, 3, and 4 are 2 bits */4 ~" K, X, b. Y8 p6 V1 w  P4 ]; G
  479.                         put_bits(pb, run_size - 2, 2);
    6 K- D: G' }# x) ^
  480.                     }
    0 [8 m3 B' Q/ x, J
  481.                     else if (run_size <= 7)) ?$ M7 A: H; C0 p7 B: X) C' n
  482.                     {
    ) n6 @7 v5 K4 y/ E( l" M  Y$ ^6 W6 V
  483.                         /* lengths 5, 6, and 7 are 4 bits */
    # U6 h6 U, W% |. Z  a  i
  484.                         put_bits(pb, run_size + 7, 4);5 z* q* e8 Q' R  x( J
  485.                     }3 I$ S* i5 F( k/ {$ v8 }
  486.                     else
      _0 V. w" E" ~- K+ A* p6 B
  487.                     {
    & ?; _/ C* g& H1 r' c$ K& d2 t, w; b
  488.                         /* arbitrary length; start by encoding 0xF which
    + H  b& q9 W5 q! X4 ]4 T& J
  489.                          * stands in for an initial version of 8 */3 L3 d2 F) N) I
  490.                         put_bits(pb, 0xF, 4);
    ) {$ j/ |3 g& z& Y
  491.                         run_size -= 8;
    + I3 k% k) g' E- a

  492. * u% |) {' O0 ]5 }# A" O4 E. @
  493.                         /* encode blocks of 4 bits until run_size is 0 */4 \: R% [0 {! [( }+ x
  494.                         while (run_size >= 0)' X1 I1 l4 z7 K/ z0 |# E" G
  495.                         {
    2 I/ K& z* n9 V& l/ R6 m; O$ `5 C
  496.                             if (run_size >= 15)6 D9 B8 {9 K1 g- c3 X7 A# d
  497.                             {
    - S" k( M  q; w# h8 a
  498.                                 put_bits(pb, 0xF, 4);
    - i# |" S: ?! x7 b0 Q* @
  499.                                 run_size -= 0xF;, o# P  C+ }9 O
  500.                             }
    - @6 y& U: z* ]6 Z8 }; L
  501.                             else1 Z1 p  |5 Y1 U# Z
  502.                             {
    4 R9 }& x; L' d( o' L' F* B
  503.                                 put_bits(pb, run_size, 4);9 z# q# E# v& H- N# f) i' T5 z2 q
  504.                                 run_size = -1;! s  ~2 D# r! ^9 z! s
  505.                             }
    , W$ l& E* E8 U3 h6 K) T
  506.                         }
    & ^9 ~% A1 M0 v2 V- O
  507.                     }
    . v1 [; v1 \. R8 ?2 b
  508.                 }
    9 J" u; G; Q9 }, p8 {5 i& W
  509. & g5 k/ z6 {0 q1 t
  510.                 last_pixel = full_window[x];$ M1 L3 U3 d: J4 _! u, c! ~
  511.                 run_size = 1;
    8 k( v6 S* y8 Q* a& ]/ g
  512. 5 I2 T2 ~9 O! \/ u2 }+ S- [+ `2 z' N
  513.                 /* this single x iteration was only here to close the final run */' O6 M" f3 |( B; S( |! H
  514.                 if (y == window_bottom)+ i5 v' q# k, c3 q/ c
  515.                     break;
      |$ c9 }! w0 q- M+ h
  516.             }
    ! r+ a( C( e. Z0 M, A7 w& d
  517.         }
      m! ?$ C3 N, b) `  a, d
  518.     }
    ' _  {: W4 Q" c, F, o! j7 l" D
  519. - v& M+ D; r; U8 D' r
  520.     /* close the bitstream by encoding a back reference with length 0 */* Q! Y, T( G( g7 D
  521.     put_bits(pb, 1, 1);  /* back reference run */# u+ k  L/ G% ]1 H* R0 W3 ^
  522.     put_bits(pb, 1, 1);  /* 1 = 7-bit offset */
    3 |: M" b8 q3 u8 r/ c
  523.     put_bits(pb, 0, 7);  /* length 0 */  W+ a# x' l9 Q- J( V* }3 u

  524. , G$ }+ a: _0 |. @
  525.     put_bits_flush(pb);5 V% @& s3 u9 I! @
  526. }
    7 c5 p% \2 r1 F( g& m. _! z
  527. : [6 y- ~$ E1 K1 R6 i
  528. /* compute Euclidean distance between an RGB color and the desired target */
    9 l/ c' o* ^& @- o( B9 c) f
  529. static int compute_rgb_distance(int r1, int r2, int g1, int g2, int b1, int b2)
    - Z1 i" U. F8 ]1 A
  530. {
    0 P4 u4 |2 i( y  [9 q4 w
  531.     return sqrt((r1 - r2) * (r1 - r2) +" {$ y! K4 m& Q; y2 u# ?+ e8 i
  532.                 (g1 - g2) * (g1 - g2) +/ G. l: U, k5 D2 b
  533.                 (b1 - b2) * (b1 - b2));
    ) {: |5 c( ~+ N3 F% ~& h$ G
  534. }" L8 d( Y* w  r. s8 Y; \8 W
  535. $ d: J- U/ y' L% w
  536. static uint8_t find_nearest_color(rbt_dec_context *rbt, int r, int g, int b)) N9 j( _  |. [: o, ], F. W
  537. {5 u: b1 a$ S: [* z* J
  538.     int i;
    * z0 k" `% Y( c
  539.     int nearest_distance;
    , h- f) a% K% }) _) X
  540.     int distance;, o$ z* Q) G2 T0 {/ @6 r
  541.     int rp;, p( e( d% z" U" J0 F
  542.     int gp;. M/ {$ k3 P/ e2 F& E* r8 m5 X
  543.     int bp;
    9 B; V$ c4 x9 a
  544.     uint8_t palette_index;
    , L0 z! _2 P! S! L0 y& U0 b
  545. ; z: w2 N4 W0 y; V' \3 ^- X8 w0 y
  546.     nearest_distance = 999999999;
    5 v; V% ~' g6 l) o# C8 h2 u
  547.     palette_index = 0;
    ' o  E( Y% w, d8 ]0 L9 R# {# k4 v9 n
  548.     for (i = 0; i < 256; i++)
    # }/ I8 y. I2 H! L/ Z* V
  549.     {
    ! }, `6 V0 x) e3 m' P5 @
  550.         rp = rbt->palette[i * 3 + 0];0 M  o. l6 k" _6 q
  551.         gp = rbt->palette[i * 3 + 1];
    ( o4 K) S5 y3 ~2 k* b; }5 ~" L
  552.         bp = rbt->palette[i * 3 + 2];
    ) i" b- }5 i( i* f
  553.         distance = compute_rgb_distance(r, rp, g, gp, b, bp);
    * d; D4 Y$ Y8 D2 z
  554.         if (distance < nearest_distance)
    " O0 C8 s! C" f" |
  555.         {
    8 D+ A/ t2 S0 }7 b4 d7 z+ [
  556.             nearest_distance = distance;$ n! j% X' V  f2 ~3 K% L5 ?6 Z
  557.             palette_index = i;. n& \6 Q: J: w# i
  558.         }4 K: l1 r+ P- X( H4 {# |6 R' x
  559.         /* can't get closer than 0; break early */
    / B$ c5 C9 A+ J3 u9 g( E# H% |
  560.         if (distance == 0)$ z& h, {1 n; a/ T, A
  561.             break;6 M  I8 o% o6 k6 [" s2 x
  562.     }
    8 D( ]$ x. U; v" i1 h0 Z
  563. ( }2 q+ |' s% G0 l+ g7 P
  564.     return palette_index;" T' K4 M( t8 K. c
  565. }
    + E4 E% F5 s. [6 {% B4 T
  566. 3 Q+ I3 w6 I* s" j$ B8 U
  567. static void subtitle_frame(rbt_dec_context *rbt, uint8_t *frame,
    & m: [# \0 c; U' \: n/ b1 }( _
  568.     int width, int height, int timestamp)! W" u! E  b+ v$ }; l0 a& @5 [$ ?- x
  569. {; r6 ]1 N; T% P5 W/ n7 a9 d& o1 c
  570.     ASS_Image *subtitles;* C/ Y: \- }& s6 I. d4 {* C
  571.     int detect_change;
    ( Z! Z+ q  ~5 v- P' n7 V
  572.     uint8_t subtitle_pixel;
    2 _5 R9 v0 b. y8 Z
  573.     int x, y;
    3 u( |8 x8 l- e
  574.     uint8_t *frame_ptr;% a6 |/ @1 }. l7 j! k
  575.     uint8_t *subtitle_ptr;+ K) _7 w5 i4 ]- u
  576. 3 N+ v- ?' ^4 P% z2 `
  577.     /* ask library for the subtitle for this timestamp */
    8 e4 r% v  K: g; s  ~1 I( z
  578.     subtitles = ass_render_frame(rbt->ass_renderer, rbt->ass_track,2 Y) y& Q$ z9 u/ q; w5 p* [
  579.         timestamp, &detect_change);
    6 c" g1 D' h- u+ K% a# u
  580. : }0 a; `# B) b* V' h
  581.     /* render the list of subtitles onto the decoded frame */; q) z( v1 R) {* L, R+ d
  582.     while (subtitles)
    % S3 J! k( Y( ]  [3 j/ p- n
  583.     {
    ( _; H9 a/ d" c
  584.         /* palette components are only 6 bits, so shift an extra 2
    ; G. B1 H: b; g, w- ?
  585.          * bits off each component */
    : q! P) b% ~- o  `; T, B
  586.         subtitle_pixel = find_nearest_color(rbt,
    ( k6 F( W6 a; c: I* M
  587.             (subtitles->color >> 10) & 0xFF,
    $ ]9 ~, A. F/ W4 u* g* Z6 T, c" \
  588.             (subtitles->color >> 18) & 0xFF,
    # a4 g! Z" ?$ w# J! _; u! P
  589.             (subtitles->color >> 26) & 0xFF);
    - I! w7 j9 B% Q8 C0 V4 l3 G; }
  590.         for (y = 0; y < subtitles->h; y++)
    + d) u5 e; W  @/ o
  591.         {
    ; ^( e' X4 o( C/ V: `
  592.             subtitle_ptr = &subtitles->bitmap[y * subtitles->stride];
    0 \( r1 p6 I) c
  593.             frame_ptr = &frame[(subtitles->dst_y + y) * width + subtitles->dst_x];) q/ K- X* ]3 m  n( @# z, {; F
  594.             for (x = 0; x < subtitles->w; x++, frame_ptr++, subtitle_ptr++)
    % t. X, l5 c/ x7 c- o) O5 r
  595.             {
    - Q) T2 |  _. M- p1 A
  596.                 if (*subtitle_ptr >= SUBTITLE_THRESHOLD)" c+ F( ?0 m8 n) [! ^: r
  597.                     *frame_ptr = subtitle_pixel;: T7 k2 O" j( m3 b
  598.             }& \% P$ @6 }" O8 q- w' @) p
  599.         }/ }& c- T; h2 }. B. X! D" f, O) C
  600.         subtitles = subtitles->next;
    ) s+ f6 M+ |5 b7 v, H  O3 z7 J
  601.     }+ y/ Y+ O7 m' J4 p- z4 }
  602. }
    ; i8 e( a$ G0 S: |

  603. " \- Q) B& x& w7 x0 |
  604. static int copy_frames(rbt_dec_context *rbt, FILE *inrbt_file, FILE *outrbt_file,2 C# N7 c" o7 t$ v0 w8 e0 b
  605.     int origin_x, int origin_y, int window_width, int window_height)
    5 |+ Y/ w, N+ l& k
  606. {% F. f7 h1 U4 q3 C6 ?
  607.     int i;
    4 s. ?- [' W5 ^- V
  608.     int j;
    % c0 b8 N8 L) [$ W2 n
  609.     int scale;9 m2 m6 j& v, P. O
  610.     int width;
    , R. Y' N( r8 T7 W
  611.     int height;9 Y5 U: v, y* u
  612.     int max_width;) ~7 ]" f- b6 }+ a/ c
  613.     int max_height;5 b0 @5 c; s) e
  614.     int frame_x;
    8 L$ B8 b: b$ J8 U/ t
  615.     int frame_y;
    ; x1 T# k( w" ?0 j' S
  616.     int fragment_count;
    7 a" T% u: Q! Z9 i# O8 J
  617.     int decoded_size;- \0 l2 z7 Y; J: k) E
  618.     uint8_t *decoded_frame;8 j9 }4 X3 L! K4 r/ m
  619.     int fragment;' U  p* \$ M# y% I
  620.     int fragment_compressed_size;
    6 S/ |( `2 P5 e- b$ f8 u. j5 k
  621.     int fragment_decompressed_size;$ a, {/ y& n7 G4 k
  622.     int compression_type;* G: k, C' G3 M, p. Z( E
  623.     int index;7 [- I5 ~, M: t& \- F1 `
  624.     int out_index;0 d4 `; E8 d+ K1 k
  625.     get_bits_context gb;3 T7 E( h: Z* D6 @
  626.     int frame_size;$ V% s2 [% G2 ~5 ^! ^! v7 ~. W
  627.     int video_frame_size;8 V0 x8 l' Q; F' r
  628.     int audio_frame_size;4 X! g/ c0 G& z1 [/ _

  629. 1 A' b) ~$ }8 t% C, e, L* o
  630.     int back_ref_offset_type;
    6 W: f7 p7 }5 z0 g/ [1 j3 R0 W& B
  631.     int back_ref_offset;
    # M2 y3 ], W+ m% q7 a
  632.     int back_ref_length;
    ' R: @' q! C+ s
  633.     int back_ref_start;
    % O( C, {$ R) H: t
  634.     int back_ref_end;
    & q- x2 @4 w) E
  635. & Q/ z3 f0 \3 K2 Y& Z$ V: d# |
  636.     uint8_t *full_window;
    5 n0 X' G7 e4 S) A3 V9 V
  637.     int full_window_size;
    8 ~1 l( ^& s2 {0 ?, p  o7 \; u
  638.     int y;
    * S% T+ @! [* r
  639.     int window_top;2 R" O, n' s& M* d5 ~
  640.     int window_bottom;% D5 B. C! X  F* z8 L
  641.     int window_left;
    2 {& Y: w; i0 v5 ~' q: H
  642.     int window_right;
    - `$ U4 q+ t. h, d) U1 [
  643.     int window_size;
    + U. X1 ~2 c0 P7 `! [& A
  644. . E: i0 z$ ?7 t( `" L, Q8 s
  645.     char filename[30];7 B2 _* N! {/ r2 Z
  646. * y& E9 ?' m& h; I9 I, L3 F- D+ H
  647.     put_bits_context *pb;
    9 z5 i6 U5 e! C, p7 Z

  648. / E1 Z0 T. f; T+ G  [' N
  649.     full_window_size = window_width * window_height;* `( d: D' ^, W" E) @* U$ n
  650.     full_window = malloc(full_window_size);+ V- O! p% _2 n2 ^& W$ b+ z- N
  651.     pb = init_put_bits();/ m2 Y; N" o+ c4 `3 k3 @

  652. ' @7 o" G# A# Z6 m% W2 a/ `; `
  653.     max_width = 0;
    . ?& M( t* T6 A7 h- _
  654.     max_height = 0;9 g, L3 ]8 l8 \  H1 S6 N
  655. " \5 K6 k# C2 l5 ^( y+ u/ A
  656.     for (i = 0; i < rbt->frame_count; i++)
    . w) ]4 }. I7 j" T
  657.     {; E& J; `" _5 R; e$ a
  658.         /* read the entire frame (includes audio and video) */
    5 p7 f' Q: R+ n/ T% b0 L
  659.         frame_size = LE_16(&rbt->frame_size_table[i*2]);
    $ J9 O. V1 ]# u( R3 a7 F/ n9 u1 [
  660.         video_frame_size = LE_16(&rbt->video_frame_size_table[i*2]);
    9 e9 J8 ^5 H" i& _, j: t
  661.         audio_frame_size = frame_size - video_frame_size;
    3 g. G8 w8 ~  F. X9 r& S
  662.         if (fread(rbt->frame_load_buffer, frame_size, 1, inrbt_file) != 1)  D: j5 S+ N7 O7 q1 I. A
  663.         {+ |7 ]- O* C, b9 S5 G4 H' t
  664.             printf("problem reading frame %d\n", i);  c5 Y2 |* F' ^4 [
  665.             return 0;
    8 {! O, e- w9 h& B
  666.         }
    - n6 |& t% W. |9 @$ f
  667. " A) ?. m9 p/ r3 G
  668.         scale = rbt->frame_load_buffer[3];& g+ t3 ?, t0 F, |
  669.         width = LE_16(&rbt->frame_load_buffer[4]);! v" j9 U1 ?5 z
  670.         if (max_width < width)
    7 F, F! t- T( F- t4 Z5 L
  671.             max_width = width;0 Y% O( R" H& g. V
  672.         if (max_height < height)5 F. g/ ?+ `' O+ [7 s3 ]
  673.             max_height = height;
    9 l, G+ t+ s" Q! @* _- M
  674.         height = LE_16(&rbt->frame_load_buffer[6]);2 y0 U6 w0 t) m5 u# _  i$ T8 i9 }
  675.         frame_x = LE_16(&rbt->frame_load_buffer[12]);
    ; x0 ?0 b! u2 b  a- b( K
  676.         frame_y = LE_16(&rbt->frame_load_buffer[14]);
    1 h3 E5 Z( k, [- [3 K6 c/ ]4 s
  677.         fragment_count = LE_16(&rbt->frame_load_buffer[18]);- G& ?( o- H: u3 c8 ]/ t$ K
  678.         decoded_size = width * height;
    - ?' H' l5 M9 L  O" {* K# W

  679. 2 i( v5 a3 V  t4 N
  680.         printf("processing frame %d: %d%%, %dx%d, origin @ (%d, %d), %d fragments\n", i, scale, width, height, frame_x, frame_y, fragment_count);
    ) o* c' }4 S2 W8 s4 `- w
  681. / D$ b! a$ S* v, n$ ?. x; h- T
  682.         /* decode the frame */
    5 o1 c! T$ ~: i6 X
  683.         decoded_frame = malloc(decoded_size);9 X1 \' m6 o6 v7 }
  684.         index = 24;  J7 D2 o0 [* [0 Y
  685.         out_index = 0;
    ) q( i1 R4 T& c' x5 e
  686.         for (fragment = 0; fragment < fragment_count; fragment++)9 U4 ~, t+ v* h; p! b: a, n4 e
  687.         {
    # I4 e4 C8 K! p  ^+ |' u: e
  688.             fragment_compressed_size = LE_32(&rbt->frame_load_buffer[index]);" D4 _- `" j# U* O) Z) p) o
  689.             index += 4;
    ( N  B, H9 C5 l/ }
  690.             fragment_decompressed_size = LE_32(&rbt->frame_load_buffer[index]);7 Q2 {5 h0 n2 }3 A) G/ B4 h7 [
  691.             index += 4;, f& \8 W0 g! |. M8 R
  692.             compression_type = LE_16(&rbt->frame_load_buffer[index]);
    : w* }5 X4 y% q! T; N) G' A6 I
  693.             index += 2;
    & R4 F$ h! }0 X; x3 w! b# {
  694. ( O" E  }) ?7 Z: B/ X4 t
  695.             if (compression_type == 0)" j6 W- V3 [5 n2 H: v2 A  ~! G/ B% Z
  696.             {, x- C. ^: R4 ^( J5 z
  697.                 init_get_bits(&gb, &rbt->frame_load_buffer[index],' ~1 Q% U& n3 I. r; T, b
  698.                     fragment_compressed_size);  i" @+ U: y5 u: X+ i

  699. + Q6 n# N2 t8 |) {! [1 U
  700.                 while (out_index < fragment_decompressed_size)+ H+ s# G% b/ W" H9 d$ k
  701.                 {
    , l7 D  \, F6 n! m1 v" h6 p
  702.                     if (read_bits(&gb, 1))* Q* O" t; O$ s, Q. X
  703.                     {: t0 X. j  `2 E0 ]! O
  704.                         /* decode back reference offset type */) E2 G1 C# g6 @: X* L1 q
  705.                         back_ref_offset_type = read_bits(&gb, 1);
    - ~1 f! l" [/ D

  706. + r; F% @7 O7 D) z2 @. i- u% N
  707.                         /* back reference offset is 7 or 11 bits */
    ) g) i8 h' e! O% R' i3 A( }
  708.                         back_ref_offset = read_bits(&gb,% N% x' W9 s3 ?6 t9 m. a
  709.                             (back_ref_offset_type) ? 7 : 11);5 v; y% o+ x# B0 }
  710. - W1 \& A/ Z2 r. G3 j& n2 r0 ~
  711.                         /* get the length of the back reference */0 v6 c. M5 K- K1 w* {6 c4 ~" Y  z3 b
  712.                         back_ref_length = get_lzs_back_ref_length(&gb);0 z' @; s8 m1 ?& t+ a5 e: H% E, n
  713.                         back_ref_start = out_index - back_ref_offset;5 }8 r2 m& V; \/ B' w; E, Q3 [
  714.                         back_ref_end = back_ref_start + back_ref_length;
    0 N% D" Q: c5 P  o, ]
  715. " a' P2 S; Y" `) O: K9 j1 R8 Z
  716.                         /* copy the back reference, byte by byte */" {" d: @  ^0 o' T
  717.                         for (j = back_ref_start; j < back_ref_end; j++)$ S. Z4 M! s. A+ \- j! ~1 I
  718.                             decoded_frame[out_index++] = decoded_frame[j];
    : ^+ [9 `$ b* \5 Z. Y3 H2 j
  719.                     }: `, W4 z/ F& j1 V! q
  720.                     else; w2 a- p; W! [3 D
  721.                     {0 z7 E" t) \, F! y: F; U7 [
  722.                         /* read raw pixel byte */7 |2 f% l7 I$ P/ K" M" t8 c
  723.                         decoded_frame[out_index++] = read_bits(&gb, 8) & 0xFF;
    2 n( [, n9 O# X% o9 D5 h- o+ N
  724.                     }
    ! ~* d" u- V9 R2 a# T
  725.                 }
    ) S' I( r* U! @& e1 d8 ?' n& _5 q

  726. : w* f0 n6 z- b; g, ^/ b' n
  727.                 delete_get_bits(&gb);7 [4 G" d( T2 |
  728.             }
    1 |# ~8 e5 ~, _) U- }

  729. . m. d; S$ q. s
  730.             /* next fragment */
    % c6 l- J$ j+ D# J7 W) X
  731.             index += fragment_compressed_size;
    " _8 ^  u9 r  M! x: r$ q# d
  732.         }
    2 G. u( k: ~0 e: `$ v

  733. 8 V: \; J6 [$ a( p5 F  }/ L
  734.         if (rbt->dump_frames)
    # C% H; E9 a0 p  E. D# A7 _
  735.         {
    ' e% j) u7 @! K9 o) _( S" u
  736.             /* dump the original frame */7 S& F4 c9 v% E5 _& B
  737.             sprintf(filename, "original-frame-%03d.pnm", i);
    ) `. i0 A/ {* O
  738.             dump_pnm_file(filename, rbt, decoded_frame, width, height);4 a( H* F4 Y4 u6 t: R
  739.         }
    $ n2 t/ p: f* `% L0 s; X
  740. - y5 T. }/ S5 q7 P
  741.         /* transfer the image onto the frame window */
    1 S3 E7 y9 i+ U- B* G# u4 a: ]
  742.         memset(full_window, 0xFF, full_window_size);4 g# |+ f4 U) S6 R* Z
  743.         index = 0;' l- f- p( {. @* v* B
  744.         for (y = 0; y < height; y++)
    5 x* ?( S  Q3 U% ?
  745.         {
    ' s9 L- y! F3 H* u8 o* \$ ]
  746.             out_index = window_width * (frame_y + y) + frame_x;
    0 }6 v4 g! r1 s4 R' L
  747.             memcpy(&full_window[out_index], &decoded_frame[index], width);0 d+ {+ c& b% C) Q6 Y; J( k; L
  748.             index += width;8 O! ^; R3 y2 G. N& }0 P" y
  749.         }
    ' ]5 W  Y2 p- e: ^4 V4 {

  750. $ y5 z, d# j9 U1 k1 O  W
  751.         /* write the subtitle */
    $ _: q6 k" a7 \. t
  752.         subtitle_frame(rbt, full_window, window_width, window_height,
    % F9 e* N/ v# B- I& t9 x% l
  753.             i * MILLISECONDS_PER_FRAME);
    ) r# {# V- H# p" h5 v/ z

  754. 7 u2 e! Y$ ?$ c; }  v
  755.         /* figure out the smallest change window */
    4 F0 O2 c' z4 u. Q4 C
  756.         window_top = frame_y;1 |  x  v" B, X# p% Y
  757.         window_bottom = window_height;
    5 H+ n9 ]5 T3 |+ M
  758.         window_left = 0;
    ! }9 W3 _" V7 t
  759.         window_right = window_width;0 Z5 E  h( D4 o4 d$ \
  760.         window_size = (window_right - window_left) * (window_bottom - window_top);
    . J/ E. W" M( Z4 Q2 l8 z1 o3 O
  761. / L1 j4 i, O1 E2 L* f& w
  762.         /* compress the frame */
    , Y7 v, N& W: r6 d% P/ x. R6 M
  763.         reset_put_bits(pb);$ s! g* z* T; `; K3 T6 H$ T/ W
  764.         compress_window(pb, full_window, window_width, window_top,
    ) m  q3 D6 w3 @) a# \3 t( D; A+ G0 `
  765.             window_bottom, window_left, window_right);
    ' h+ j: m1 x! o' g+ G' u4 P" N0 Z
  766. % Z( W! ~( O+ ]7 X' f( }+ k' n
  767.         if (rbt->dump_frames)* P' h- L2 y& X& C6 T; w4 R/ g  y
  768.         {
    , J2 L8 r3 r  ?# b( @
  769.             /* dump the frame plotted onto the full window prior to encoding,/ G' k2 f4 `& Z/ O
  770.              * with subtitle */
    3 O, A8 g+ K  @* w9 d
  771.             sprintf(filename, "pre-encoding-frame-%03d.pnm", i);5 D, E( k% w1 X0 R. n8 B  C  p
  772.             dump_pnm_file(filename, rbt, full_window, window_width, window_height);
    3 W: \. N1 N) r( C+ b2 W
  773.         }
    ; n  W, G7 A3 h8 B: h7 [7 U9 r

  774. . g3 i& k3 d& b; H
  775.         free(decoded_frame);" E$ u! u6 s) q/ t5 O$ m
  776. 9 E# k5 q: \. c3 `
  777.         /* update the frame header */
    0 [% B( v7 t) \2 r
  778.         /* width */: h: L; c6 l* b5 S5 I9 _: t
  779.         rbt->frame_load_buffer[4] = (window_right - window_left) & 0xFF;# l" }7 y+ X+ D- a: ^) q
  780.         rbt->frame_load_buffer[5] = (window_right - window_left) >> 8;0 P( V: S* I, v- x
  781.         /* height */
    , a+ O( t& l4 ]3 R4 y& D
  782.         rbt->frame_load_buffer[6] = (window_bottom - window_top) & 0xFF;
    # Q" s& T8 q+ {* S6 U: ~
  783.         rbt->frame_load_buffer[7] = (window_bottom - window_top) >> 8;
    % v  X( I8 m0 L0 w& E
  784.         /* origin X */
    3 h6 g. m& _& |6 v. J+ x' q
  785.         rbt->frame_load_buffer[12] = window_left & 0xFF;
    2 T) ^7 J3 d$ Y4 U* y$ Q; X
  786.         rbt->frame_load_buffer[13] = window_left >> 8;9 I2 }- M1 C5 @# ~% K1 o9 c
  787.         /* origin Y */
    6 u0 x( X% k& N
  788.         rbt->frame_load_buffer[14] = window_top & 0xFF;* Q# Q3 h' s* v
  789.         rbt->frame_load_buffer[15] = window_top >> 8;% ?: t1 y9 u; t3 e0 i8 V3 C: E
  790.         /* fragment payload size */6 H* o* [9 G* W) Q4 I
  791.         rbt->frame_load_buffer[16] = (pb->byte_index + 10) & 0xFF;
    * ^8 N- N( v  T4 }1 G1 m0 Q2 N( L
  792.         rbt->frame_load_buffer[17] = (pb->byte_index + 10) >> 8;7 a: r7 ?+ K. p% S
  793.         /* fragment count (1) */3 g' G7 I6 O  G! l# \7 M. ^
  794.         rbt->frame_load_buffer[18] = 1;% M3 L1 U& [: F1 X) K) C' p# v  s
  795.         rbt->frame_load_buffer[19] = 0;
      c1 }9 E0 \- n& x; v
  796. 6 c2 H: E9 a1 s3 w4 k* b
  797.         /* update the fragment header */
    + L; ~7 o% K8 e1 J3 e7 b
  798.         /* compressed size */
    5 ^; T  V( z# R: B& U* g
  799.         rbt->frame_load_buffer[24 + 0] = (pb->byte_index >>  0) & 0xFF;" j; t0 e9 d' P- Z8 J
  800.         rbt->frame_load_buffer[24 + 1] = (pb->byte_index >>  8) & 0xFF;, e% L+ S/ F2 Y8 T( g
  801.         rbt->frame_load_buffer[24 + 2] = (pb->byte_index >> 16) & 0xFF;
    * r) ^& W! x6 G( s4 k% g7 Z
  802.         rbt->frame_load_buffer[24 + 3] = (pb->byte_index >> 24) & 0xFF;) ]9 y# l2 s& L2 `
  803.         /* decompressed size */
      t. W5 J- S& K& C
  804.         rbt->frame_load_buffer[24 + 4] = (window_size >>  0) & 0xFF;: X" r% m/ V; u* h
  805.         rbt->frame_load_buffer[24 + 5] = (window_size >>  8) & 0xFF;
    / M* `. s3 F% y* L& H$ {
  806.         rbt->frame_load_buffer[24 + 6] = (window_size >> 16) & 0xFF;
    . ^) A5 U) s+ g% o4 v% o- a
  807.         rbt->frame_load_buffer[24 + 7] = (window_size >> 24) & 0xFF;
    7 A1 l! r# m4 y% Y0 F
  808.         /* compression format 0 */8 ]  T& Z2 H* I2 V$ ]! J% R
  809.         rbt->frame_load_buffer[24 + 8] = 0;
    - T* O" I5 p/ K9 o, Y# u
  810.         rbt->frame_load_buffer[24 + 9] = 0;3 {7 Q- ~3 J+ M( v9 U+ Z/ H: @
  811. 2 F; _) f, \" g0 |# ]! ]
  812.         /* write the 24-byte frame header and the 10-byte fragment header */
    $ \" t. s5 @8 b7 o, P9 Z6 \- C
  813.         if (fwrite(rbt->frame_load_buffer, 24 + 10, 1, outrbt_file) != 1)
    : V6 T1 y) H: R' D$ y! }6 E/ Q% h4 u
  814.         {. o' \2 G1 I3 S
  815.             printf("problem writing frame %d\n", i);4 U" A7 U' N. d  U3 E/ n- D% l. u) D
  816.             return 0;6 J4 `6 l, ~  V! ?( D
  817.         }6 n9 s2 s' j* g2 R8 x% B8 B
  818. * H; p# @- K! o" u7 }/ v; t
  819.         /* write the new compressed frame data */! W* W! m) p  C" [* e
  820.         if (fwrite(pb->bytes, pb->byte_index, 1, outrbt_file) != 1)
    ) D# d# z: k! `: F, ?' z( g" O/ w. ~( z
  821.         {4 m9 ]7 \) n* y2 u" H( c, `7 H
  822.             printf("problem writing frame %d\n", i);
    - R6 p$ g! m3 l7 W
  823.             return 0;
    9 W. H6 n& l; W& f( L
  824.         }
    ( N! P9 B% Q! D1 V

  825. + `( D+ X  i3 X& w5 u/ h1 L' v
  826.         /* write the audio data */
    % K5 d. _/ {" P2 Z. I
  827.         if (fwrite(&rbt->frame_load_buffer[video_frame_size], frame_size - video_frame_size, 1, outrbt_file) != 1)1 v8 N1 W3 z6 q$ v6 I7 \
  828.         {
    # v  n: F8 W6 {# h) o
  829.             printf("problem writing frame %d\n", i);7 n% W( Q) ]6 |& x  ^
  830.             return 0;8 y3 @2 g' ~, `% @1 G' y
  831.         }
    . P3 b5 A+ G) r& M9 ?* D8 N
  832. / t7 A5 e2 O" n7 w
  833.         /* update the table entries */' b8 }6 L! c3 P/ A. @
  834.         video_frame_size = pb->byte_index + 24 + 10;! a+ Q% T, C# c: S. }5 a
  835.         frame_size = video_frame_size + audio_frame_size;, ~. L" z! ]  H
  836.         rbt->frame_size_table[i*2+0] = frame_size & 0xFF;
    ) Q- q3 Q/ x& K$ J8 V
  837.         rbt->frame_size_table[i*2+1] = frame_size >> 8;5 Z0 {& T. g' @
  838.         rbt->video_frame_size_table[i*2+0] = video_frame_size & 0xFF;
    + G2 h7 n" k7 U9 _" C
  839.         rbt->video_frame_size_table[i*2+1] = video_frame_size >> 8;" O5 A; K9 T' b- o+ _+ |
  840.     }
    6 ~& e! w8 r- N, x/ P. X8 k
  841. ; X2 }3 H" q, a; z
  842.     printf("maximum dimensions seen are %dx%d\n", max_width, max_height);
    ! f3 b& F) Y4 S6 B1 i- [

  843. 8 ~* C* n7 I8 c0 h- L1 z
  844.     delete_put_bits(pb);
    ; Z) D- J4 `+ B) a1 _+ |$ I- b
  845.     free(full_window);
    ; W, f; t1 Q9 L9 o' N
  846. * F! |6 `: P* l  C0 c) W+ E4 a( K
  847.     return 1;* N' q/ |+ S' A4 D
  848. }
    7 G! V9 J& r6 b  \8 k& g
  849. / z# h1 N# c: m, O+ E$ W# L
  850. int main(int argc, char *argv[])
    & D9 @- }1 M9 o% ]) W
  851. {
    0 A! ]  T: J3 S% x- a. t7 h
  852.     char *subtitle_filename;1 B7 b+ W+ P( j, ^  L5 P9 v$ G
  853.     FILE *subtitle_file;' @4 C9 \2 R4 p5 @
  854.     char *inrbt_filename;
    : g7 i( V  g- y3 k
  855.     FILE *inrbt_file;# V- d" d5 J- ~! y) K' E8 `
  856.     char *outrbt_filename;: H1 w% T3 \6 |% g
  857.     FILE *outrbt_file;; g% {1 T; l) y; \  J8 W% M7 ^5 F" _
  858.     rbt_dec_context rbt;
    1 T3 w6 b! P4 j9 z& y: l, G% X* |
  859.     int origin_x;
    4 X6 o5 K6 B, J0 q2 C: G  ]
  860.     int origin_y;. `6 O7 F) u/ r* B1 _  a+ d" o
  861.     int window_width;
    4 L* A+ V7 j7 s+ \' {$ r8 `+ k9 J
  862.     int window_height;2 J" |+ M3 k' [2 m4 o) N' Y9 E

  863. % u, q: m8 a3 s; h8 X6 V. t
  864.     /* testing the bit functions */
    ) s: [6 w" \0 u" C
  865. #if 0
    ! x% g3 F7 M* r; W6 X
  866.     int i;
    0 X  E. C" M# B1 l
  867.     uint8_t bytestream[] = { 0x55, 0xAA, 0x00, 0xAA, 0x55, 0x77, 0xFF, 0x1B, 0x70, 0x8F };+ V2 W/ t9 |, g
  868.     int bytestream_size = 10;+ H2 ~+ q' ^. A' G
  869.     get_bits_context gb;
    - ^) A5 ]0 f5 \( H# J
  870.     put_bits_context *pb;1 E8 F3 g- v3 F' g* O$ }; u7 w
  871.     int bits;
    ) ^4 q2 {$ X9 u6 p: U% N+ A
  872. % ?+ k* J* Y- T3 H; Q
  873.     init_get_bits(&gb, bytestream, bytestream_size);
    2 e, m" t$ ~/ P4 a: R: k% T5 {
  874.     pb = init_put_bits();
    ) u' }7 I$ ?) Q8 d; w0 j' e
  875. ( k" X1 o' \" v
  876.     for (i = 1; i <= 12; i++), V7 ~0 H# K% D' ~' ~0 ~
  877.     {" L6 l( I1 U: s% [
  878.         bits = view_bits(&gb, i);0 ^1 J' J6 [/ u  z$ v) s! v
  879.         printf("view %d bits: %d\n", i, bits);& F  J$ \+ g- i" y
  880.         printf("read %d bits: %d\n", i, read_bits(&gb, i));& o: n! E$ x  c
  881.         put_bits(pb, bits, i);
    8 H# `2 Z4 e! U3 \
  882.     }
    9 R. P* B; G6 o8 d' z
  883.     put_bits_flush(pb);3 m  W) G- Q: E) e! X
  884. 5 \$ R3 B* v. {: a$ F
  885.     printf("original bytestream:\n");( d& ~% X9 `  k' k1 p
  886.     for (i = 0; i < bytestream_size; i++)2 K! X( J2 L1 V
  887.         printf(" %02X", bytestream[i]);' r% X0 D# X& g& p
  888.     printf("\nnewbytestream:\n");2 h( v; ]$ b  ~: p9 `, }. [
  889.     for (i = 0; i < pb->byte_index; i++)
    ( I% P9 W$ Z9 v" b# G, `, y
  890.         printf(" %02X", pb->bytes[i]);0 d. ]& K% k. s9 W+ ~
  891.     printf("\n");
    ) k' H( c) s- t( c* w- h
  892. , @$ y+ |- ~8 H1 G% `7 O
  893.     delete_get_bits(&gb);3 f0 \; T- r2 J
  894.     free(pb);1 G7 s2 l* w7 j: x9 w5 \
  895. #endif
    & V# H$ o& ?: m; A. J/ {

  896. ' ^( M) k% _& N: J; E. V$ z$ M+ Z& N
  897.     /* validate the number of arguments */% [- j2 S& C* N# ]1 y
  898.     if (argc != 8 && argc != 9)
    : |# D& m! K  C+ P" m
  899.     {
    % R& o; @6 a0 }3 x. b: y! F
  900.         printf("USAGE: subtitle-rbt <subtitles.ass> <in.rbt> <out.rbt> <origin X> <origin Y> <width> <height> [dump_frames]\n");
    / R8 A1 g- @8 Q) ?  T5 @
  901.         return 1;2 Q/ T/ U5 p8 `# Y  f8 }3 ]* y
  902.     }
    7 F6 G9 }' o1 C7 d* @+ k, }- ^
  903.     subtitle_filename = argv[1];
    , ?$ T4 g6 X: s0 }- I6 y
  904.     inrbt_filename = argv[2];
    6 E# t% R$ Q; i
  905.     outrbt_filename = argv[3];
    2 f+ {/ g" z; Y) u# R
  906.     origin_x = atoi(argv[4]);
    4 e/ {8 {) y  l/ Q
  907.     origin_y = atoi(argv[5]);
    ) M) M% Y: U, U: y% j" J0 N% f! H
  908.     window_width = atoi(argv[6]);
    ; u) C6 @. |' Q& g2 A$ C8 o- e2 ?0 b
  909.     window_height = atoi(argv[7]);
    " h9 A( n1 n+ h( [  K. r
  910.     rbt.dump_frames = 0;
    9 C% \3 R4 K2 p
  911.     if (argc == 9)
    ) _: i' r3 a* F% x, a, K3 T8 J
  912.         rbt.dump_frames = 1;! T$ ^' A- m$ U, |5 P7 F
  913. ! i" _; h9 I6 |" }4 Q$ N
  914.     /* verify that the specified input files are valid */" r( P9 U0 o+ \- L) m
  915.     subtitle_file = fopen(subtitle_filename, "r");
    : I3 [7 ~+ n" f- c  b$ Q( Y* t
  916.     if (!subtitle_file)+ S! w) ?6 B$ v5 Z- V
  917.     {
    5 n$ k  _( ^4 c, I6 }9 l& R
  918.         perror(subtitle_filename);
    $ l. H& ^4 x  D8 {* a; ]+ V' F
  919.         return 1;9 U$ I6 ], h: w
  920.     }
    2 L% [. n7 `: Z6 q% z' S
  921.     fclose(subtitle_file);5 m+ |$ H; o' i0 o, G* R
  922.     inrbt_file = fopen(inrbt_filename, "rb");0 u/ W. m& o% i0 @
  923.     if (!inrbt_file)5 O& c5 ~( i0 D, t
  924.     {
    6 W5 v+ Z; \- ~/ W0 q" Y
  925.         perror(inrbt_filename);1 e7 Q0 @$ y  o* w
  926.         return 1;( J* N: v. ]$ y: E5 E0 n4 x
  927.     }
    2 K& C7 |- g" }8 n6 T$ t
  928. 4 j+ h/ E1 p) t! e
  929.     /* initialize the subtitle support */5 i; \, C' [; }3 e- Z2 ?
  930.     rbt.ass_lib = ass_library_init();
    5 @* j" _9 a7 \- T$ E" l
  931.     rbt.ass_renderer = ass_renderer_init(rbt.ass_lib);" l* V( P. Q/ c
  932.     rbt.ass_track = ass_read_file(rbt.ass_lib, subtitle_filename, "UTF-8");: f7 Y$ R2 ~5 M; K5 H
  933.     ass_set_frame_size(rbt.ass_renderer, window_width, window_height);
    ( O: q: q6 ?3 \; W
  934.     ass_set_fonts(rbt.ass_renderer, NULL, NULL, 1, NULL, 1);( q( b3 h/ F2 s9 v5 u# `
  935. ; u. \$ b1 a0 G9 v/ `
  936.     /* open the output file */1 Y) f9 t7 T* v2 P& }& ~
  937.     outrbt_file = fopen(outrbt_filename, "wb");4 E/ \& S" p3 s, I# t* v! Z
  938.     if (!outrbt_file)
    3 L6 d$ `# G( c3 ^* r
  939.     {
    6 H- u  X% t. X( G
  940.         perror(outrbt_filename);( Q$ c& [7 T  R7 b/ |/ e+ V
  941.         return 1;
    & b- ^+ M2 S$ ?) p3 L
  942.     }
    + q' r/ |, e  S$ q  @# ]
  943. 8 n7 m, r& s. N2 }
  944.     /* transfer header from input to output */( I: w' h$ m% D. b0 i0 R) S
  945.     if (!load_and_copy_rbt_header(&rbt, inrbt_file, outrbt_file))
    6 c1 I  ^8 V% e( m* K: B
  946.         return 1;
    6 ]7 ~3 ?7 B! l3 q. Q
  947. ( P% ^6 g+ D4 u
  948.     /* rewrite the frames */
    ' I+ R! q2 F5 a5 l; W$ w
  949.     if (!copy_frames(&rbt, inrbt_file, outrbt_file, origin_x, origin_y,
    / |' [6 @/ i+ ?* X+ s
  950.         window_width, window_height))
    . I9 Y0 o( s0 w% S
  951.         return 1;
    / _7 M* A2 \+ K- T: _" U$ Q* n
  952. 6 b, e  L4 W) M. u7 p
  953.     /* write the modified frame size tables back to the file */' O) u& d8 S0 w
  954.     fseek(outrbt_file, rbt.video_frame_size_table_offset, SEEK_SET);) V3 x0 K, a5 t& r. d
  955.     fwrite(rbt.video_frame_size_table, rbt.frame_count * sizeof(uint16_t), 1, outrbt_file);1 U) ]1 _" d; Q
  956.     fseek(outrbt_file, rbt.frame_size_table_offset, SEEK_SET);- \1 i/ i$ i, H; }
  957.     fwrite(rbt.frame_size_table, rbt.frame_count * sizeof(uint16_t), 1, outrbt_file);
    6 P8 V! Y# [, i2 O( Z* Q+ Y

  958. ( j7 h1 G- t' [+ }: x
  959.     /* finished with files */
    7 L. {: V# v6 V8 f* b" ^# t
  960.     fclose(inrbt_file);- p! f& K7 t: X
  961.     fclose(outrbt_file);5 ]$ \9 X# Q4 C' [

  962. 3 c" G. p2 j) A% Y0 ?
  963.     /* clean up subtitle library */
    2 P; I+ v1 b5 \0 D8 s2 \
  964.     ass_free_track(rbt.ass_track);
    3 u& x% P/ J  L
  965.     ass_renderer_done(rbt.ass_renderer);$ d, q; U( A3 N0 Z, e9 ^$ M
  966.     ass_library_done(rbt.ass_lib);
    7 V  o0 R+ }4 {
  967. $ a* s! N  \+ |
  968.     /* clean up */3 t# M, {" b3 S" M+ |0 v1 D0 W
  969.     free(rbt.frame_load_buffer);
    " f* `0 S' ?. {* ]5 G
  970.     free(rbt.video_frame_size_table);
    9 v$ }2 q* w6 q8 V( \
  971.     free(rbt.frame_size_table);! r( ^+ L# W. q3 a% L: @

  972. ; Q6 w  o# v- M( A8 A
  973.     return 0;% l$ L0 l: O7 b; h4 \
  974. }
复制代码

5 J6 P7 L) o! ~7 P) Z, L1 ~6 V$ g; A" p
( s8 T# p7 X4 l7 A7 }# p9 I  Y
6 i- Z7 |. u7 N$ T
分享到:  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发表的  :. ]) U. m" S% ~7 e% F1 m1 W# B
我记得是没字幕的 比较麻烦 都是视频的
% a  n; i& x4 e4 r
给视频外挂字幕方式汉化也许能行。
7 U, f1 S, y1 g8 ]" P要结合dosbox和代理dll技术。
回复 支持 反对

使用道具 举报

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

使用道具 举报

板凳
 楼主| 发表于 2009-11-19 11:38 | 只看该作者
引用第1楼soring123于2009-11-19 11:09发表的  :
& L& X2 Y- ]" B' A7 Y0 t这游戏有字幕吗?

- D2 Q! j( H( S: s- s好像没有字幕,我说的是给视频外挂字幕方式的汉化。
" [, w2 U, c; s就像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日,是全球华人共同的冒险解谜类游戏家园。我们致力于提供各类冒险游戏资讯供大家学习交流。本站所有资源均不用于商业用途。

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