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

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

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

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

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

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

本帖最后由 shane007 于 2021-1-2 13:56 编辑   ]" m2 O3 W) ^" V+ y6 G  W

7 ]! t# V  D0 g最近找到了一些和幽魂系列Phantasmagoria 有关的资料,- {7 f1 Z& y* J. r; Z! j& w# f
也许将来可以用于汉化。. {( u! X3 k! R: k" S! L- Y

2 j+ Z7 r- l( z6 @! R) D) m2 j/ Q和日文版有关的信息
2 ~& Z. P1 X: T" `, qhttp://anthonylarme.tripod.com/phantas/phintgtp.html! k5 @9 ?0 r9 L* G7 D4 w# t! f) o; z
( D* b4 ~$ O  |9 D0 s, w! N5 y
相关工具
! P3 R6 p# G; X! u& }/ f8 O+ thttp://anthonylarme.tripod.com/phantas/phcheats.html
1 k" h+ I+ Y9 o; J  ~3 Q-----------------------------------------------------------------------5 _1 ]( z% _; ~, |- O% p
2012/1/2  更新
- I$ p9 _1 J$ k% ?8 I& C关于幽魂游戏的字幕
1 B* l" Z, X# B( Z/ w& aPhantasmagoria subtitles function discovered - ScummVM :: Forums
+ g- d- s3 F9 }; B. {; k3 c
0 X( P7 l+ L; p# u' I4 j: oVMD文件% B# T( \- J0 s& B
Subtitling Sierra VMD Files | Breaking Eggs And Making Omelettes (multimedia.cx)VMD - MultimediaWiki. T6 ]! p; ~% c/ u! R' c6 e% l( u

: G# A, s; t/ l字幕
( m5 f' ^+ P! V- h3 @9 {Subtitling Sierra RBT Files | Breaking Eggs And Making Omelettes (multimedia.cx)/ C, t) X* U# R0 R, V& \
7 u' i9 v1 }1 c4 k1 M
FFmpeg/subtitle-rbt.c at feature/VMD_encoder · multimediamike/FFmpeg · GitHub: {0 o1 c( w* S5 A  x5 |0 b
  1. /*. n' d! P* s& p" ^$ N( N
  2. * subtitle-rbt.c& I  ?9 W+ g# T. ~' h8 B; o5 {
  3. *  by Mike Melanson (mike -at- multimedia.cx)
    + c2 `4 U' s( _7 s  B- ?
  4. *
    : z/ [* y% I1 g* u: K
  5. * build with this command:2 a; D, ~4 @& V* u) [2 L- j
  6. *   gcc -g -Wall subtitle-rbt.c -o subtitle-rbt -lm -lass
    , D9 S$ ?6 T) \* @; p' `  a
  7. */
    * B9 ]& e: s7 _
  8. $ e6 B, E1 y' g6 G& f  W/ Q
  9. #include <inttypes.h>5 l7 C0 }5 L" O4 H2 K& x1 R
  10. #include <math.h>
    2 _$ {. a0 S! k* F# s" [
  11. #include <stdio.h>; k/ F3 [4 p2 R/ z
  12. #include <stdlib.h>. w% Z! t8 V7 c0 r$ U" P$ H
  13. #include <string.h>
    ! B7 c1 @& y9 {8 p
  14. " T; `' d) p: Q' [, Q" E
  15. #include <ass/ass.h>) i; e. n  H9 }) i# u) x. s
  16. ! u& s& h7 [9 l/ v! v; D
  17. #define LE_16(x) ((((uint8_t*)(x))[1] <<  8) | ((uint8_t*)(x))[0])) ^2 d$ A8 s: u, I9 s- k/ A8 Y

  18. 7 A% K8 |1 \# z) G
  19. #define LE_32(x) (((uint32_t)(((uint8_t*)(x))[3]) << 24) |  \% s! o( h8 V, n* d7 ?/ K9 [
  20.                              (((uint8_t*)(x))[2]  << 16) |  \
    1 N& x$ O3 z% s# t% ~6 A
  21.                              (((uint8_t*)(x))[1]  <<  8) |  \- ^$ [: r$ W1 d/ `
  22.                               ((uint8_t*)(x))[0])
    4 I3 g1 h" H2 j  I5 q; Z; w

  23. 9 O# `2 i6 g! \4 D/ r& u
  24. /*********************************************************************/
    5 w& o2 I- ?7 h* k  r% j  ^

  25. . ^- A# ~/ v/ ]
  26. /* Bit reader stuff */- Z$ N8 E& d, S* V

  27. ) U, Z' L2 a- e6 a3 W; j
  28. typedef struct
    / b6 S1 [/ y$ i9 j) q
  29. {, `. ^2 _! Q7 m- u
  30.     uint8_t *bytestream;
    4 M) |6 g5 j. t' n6 Q7 k
  31.     int bytestream_size;7 i( g; G" O; ?* j. t) u" u5 X
  32.     int index;/ ^% p0 c8 l- \  z2 S$ I! O1 W
  33.     uint32_t bits;
    - W( G4 r5 R8 t* I
  34.     int bits_in_buffer;0 l; f" ~) ~. u# c$ ?
  35. } get_bits_context;9 ^7 v) y' s1 ?: |

  36. 5 E0 F6 O) m/ V* Z6 R
  37. static inline void reload_bits(get_bits_context *gb)
    * ^3 d  W( W, x! r
  38. {% d! B5 K6 x( T3 ^; I+ c7 w
  39.     while (gb->bits_in_buffer <= 24)  D; A( O: M' ?4 n: N/ w/ I
  40.     {- _7 @: B- J. e
  41.         if (gb->index < gb->bytestream_size)
    ) ?, g. }$ A$ U% n! @% r
  42.             gb->bits |= (gb->bytestream[gb->index++] << (24 - gb->bits_in_buffer));% l, e& W3 V, g9 o, Y: z7 T
  43.         gb->bits_in_buffer += 8;
    , S9 V7 K+ k# O5 \4 R" a" }
  44.     }* f3 d* H/ V9 n8 A9 Y; S3 H
  45. }" ^6 B& |& {& r/ R; H6 p
  46. $ m% H  _& N1 U/ B- j
  47. static void init_get_bits(get_bits_context *gb, uint8_t *bytestream, int size)
    5 k) l% E) y/ ]- m6 i9 n
  48. {6 \( R& @0 _/ a/ d- {$ b, D
  49.     gb->bytestream = malloc(size);
    ) p$ B/ R/ r3 @" ]6 e/ }
  50.     memcpy(gb->bytestream, bytestream, size);
      r6 b9 N: B# x; [+ q" }' X
  51.     gb->bytestream_size = size;3 W1 x1 j% {7 b5 H
  52.     gb->index = 0;' U3 H) s! k+ S" m- a' S
  53.     gb->bits = 0;3 z% |& \0 C  F6 g5 C6 L6 q
  54.     gb->bits_in_buffer = 0;
    " e' T5 C1 B8 J! }0 R4 |

  55. ( |0 P9 \6 L6 F% `/ H
  56.     reload_bits(gb);
    . b2 n7 M- F6 j) v% n
  57. }
    ( X; P: S8 Y5 a  E2 v' y9 F

  58. 5 ^$ g9 s) m; b$ ?3 |$ _1 G1 n
  59. /* read bits without consuming them from the stream */
    " Q8 P6 W' g$ Q  z* Y3 \
  60. static int view_bits(get_bits_context *gb, int count)( C$ ~8 a6 i& Q2 i4 D' z
  61. {
    ' I. q9 p. X7 b6 E: ?
  62.     if (count >= 24)# ?6 [4 x. _% r# ?' x3 ]& b
  63.         return -1;! i5 z/ S4 e: b" A5 s
  64.     if (gb->bits_in_buffer < count)1 Q6 c! C8 }. ^7 W4 H/ }
  65.         reload_bits(gb);- P/ E8 [: y7 O0 K- X
  66.     return (gb->bits >> (32 - count));1 @/ X# H6 a- F1 u- Z
  67. }$ v2 k/ T2 S( ?' C5 o0 |

  68. / I8 i$ m! [9 h9 m0 g
  69. /* read and consume bits from the stream */
    : a& @4 ?% e/ Y! l( G. v8 ?
  70. static int read_bits(get_bits_context *gb, int count)
    5 y! @3 B/ o# }: s, X, @% G
  71. {1 n- a& @7 [5 b7 e
  72.     int value;
    ; X( n% e4 C) a5 h2 n

  73. ' j$ \# }0 l; A, I
  74.     if (count >= 24)5 m7 X- ?  Y+ l/ k1 a/ x
  75.         return -1;  g* p! B) ~$ D5 b$ a
  76. 8 h2 g* y: N4 E
  77.     value = view_bits(gb, count);: |  d. ^# `% V: u% O# n& v& K& `, G
  78.     gb->bits <<= count;
    ' V6 H4 s1 R7 `1 E7 R8 j4 W2 u1 k
  79.     gb->bits_in_buffer -= count;2 P1 U: p* Z1 X- `$ U) c8 V
  80. - N( z, T5 o9 S' Y$ R
  81.     return value;
    9 o- v+ Q) X3 S# I8 e' X; \
  82. }
    5 G& M9 z+ Q" j& E; V, `* Q3 z

  83. 7 l6 S1 j( l: c
  84. static void delete_get_bits(get_bits_context *gb)2 k9 T5 j0 d! C4 K% G  i
  85. {
    + q6 e  v6 g% q0 T' p9 J' ?
  86.     free(gb->bytestream);
    6 [% J' q) ]3 W5 f6 \
  87. }) E  ?% f; V7 o& N+ r4 t7 c
  88. # d+ l' ^' d4 E$ M/ {" @* ^/ I
  89. /*********************************************************************/( S  N2 S$ V2 X" w
  90. $ x* t' C! M% A, `+ z! O
  91. /* Bit writer stuff */8 t# ?1 e5 p, @3 a
  92. : ~( z0 C$ }- q0 Z. _1 g
  93. #define MAX_PUT_BITS_BYTES 63000
    & c, s! R. p6 s5 h* ^
  94. typedef struct
    ; w/ r. _" W* a8 q5 _
  95. {
    # a" P- y+ {" `- N
  96.     uint8_t bytes[MAX_PUT_BITS_BYTES];
    # R) X" Q% _2 L
  97.     int byte_index;
    - q3 p0 O. p2 a  N
  98.     uint32_t bit_buffer;! C8 q/ f9 a* G& C5 D% W* b. ]
  99.     int bits_buffered;1 l6 X/ p: `$ m2 c+ ?& t7 T
  100. } put_bits_context;! \' Y3 ~; w* Q9 {/ p
  101. ' E5 A9 s% C1 z
  102. static void reset_put_bits(put_bits_context *pb)$ r+ y7 a* y! J' @
  103. {" ?' V% D+ Z, l/ o! u
  104.     memset(pb->bytes, 0, MAX_PUT_BITS_BYTES);. X# G3 r% H# V0 w4 a
  105.     pb->byte_index = 0;
    + `( w0 o$ f  ?* F1 E
  106.     pb->bit_buffer = 0;# |1 N4 X+ U8 j7 ?
  107.     pb->bits_buffered = 0;
    0 j2 g$ k3 n4 _& `
  108. }
    . d' {+ Y' j$ f6 J4 k% v% m
  109. ; `3 H% I& m% K0 _
  110. static put_bits_context *init_put_bits()$ b! n$ Y, v, v0 @3 q! J
  111. {
    ( |$ t9 A) c# O5 {" V; y
  112.     put_bits_context *pb;7 E, G% Z# N! _. F( w
  113.   ~) A& ^: R0 S* P: }
  114.     pb = malloc(sizeof(put_bits_context));+ E7 e; u- \7 \
  115.     reset_put_bits(pb);
    8 @! T' J6 v" G" o8 w/ E! I1 m

  116. , N8 S9 [4 S: J
  117.     return pb;
    / |% Y9 o: I! Y2 z% w5 C
  118. }
    % ~( h) ~& d# E* q

  119. % h, Z2 |7 {0 Q' L$ V4 _8 w
  120. static void put_bits(put_bits_context *pb, int bits, int count)  i# y. ?) x$ s/ ~$ J. l4 Q* m
  121. {  T: z$ p7 |" p9 a6 ^5 l$ n
  122.     pb->bit_buffer <<= count;! V; p! c) G' W" G
  123.     pb->bit_buffer |= (bits & (~(0xFFFFFFFF << count)));
    3 f  ]9 G: y2 i5 n5 Q- m
  124.     pb->bits_buffered += count;. R3 T9 T( q7 k: w  l+ ]
  125. ' d) C7 C/ p8 G* r, Z) x
  126.     while (pb->bits_buffered >= 8)
    $ _, j6 T/ d6 O& Z1 r, u! x
  127.     {
    # W+ m' p* |# q4 d3 u
  128.         pb->bytes[pb->byte_index++] = pb->bit_buffer >> (pb->bits_buffered - 8);
    7 T# [4 z" ~8 M/ ?. G% X; Q
  129.         pb->bit_buffer &= (~(0xFFFFFFFF << (pb->bits_buffered - 8)));
      R: q1 B: u0 A1 e* b% Z/ `
  130.         pb->bits_buffered -= 8;/ b6 J( \2 V+ x2 Q5 O& [7 c9 w
  131.     }
    . {3 o# _( c9 ~& `  o
  132. / R8 ^: b( ^4 o) x& ?5 B" F
  133.     if (pb->byte_index >= MAX_PUT_BITS_BYTES)
      Z& \5 W2 w" d1 t7 w* q
  134.     {) {1 p) ?- i4 ^. D; w
  135.         printf("HELP! Bit overflow\n");
    ) Q! w2 u8 j# m7 d& J2 i7 f( f* I) \
  136.         exit(1);$ F6 ]' W3 K0 w" f: _% t& M
  137.     }! P2 X3 U; P5 ^1 s8 T* y" v7 u
  138. }/ `) z1 z, ]; I! `) y+ z/ s# x
  139. 8 V. F+ ?# u+ \7 ~% c
  140. static void put_bits_flush(put_bits_context *pb)7 u4 f' f9 l0 U
  141. {0 [" q' Y  }$ J5 L4 B
  142.     if (pb->bits_buffered > 0)
    3 F6 R2 ^" @5 h
  143.         pb->bytes[pb->byte_index++] = pb->bit_buffer << (8 - pb->bits_buffered);# Z* w# H; I2 W1 Z& v8 [
  144. }5 k- u* ^; L+ l! F' T3 I

  145. " W0 g! D4 x3 w  e
  146. static void delete_put_bits(put_bits_context *pb)
      G3 ?1 y& T: n5 Q. b' F5 R; v
  147. {  L. l2 _# f: w" ^) Y9 G
  148.     free(pb->bytes);; N6 ?- q! k' m2 e. D
  149. }8 K' U! [# @& m' ]/ C
  150. % n! N. h! _1 B; b, M! m8 k
  151. /*********************************************************************/  A5 j# u" Q  g7 s! f, F, S. `5 ~

  152. 7 A* o' Y" o' `/ J3 _% S& m
  153. /* RBT functions */
    & c) A6 L; s0 [& b7 P  [2 y
  154. 6 D) @$ W3 c9 r! J8 A+ R( _3 s& W
  155. #define PALETTE_COUNT 256
    4 W6 k- {0 e# c, |) J+ o4 R  w
  156. #define RBT_HEADER_SIZE 60
    8 z( x1 o5 K7 a
  157. #define UNKNOWN_TABLE_SIZE (1024+512): N5 ]9 j: A/ j7 s3 T
  158. #define SUBTITLE_THRESHOLD 0x70) l' O8 w2 w% S1 H& s
  159. #define MILLISECONDS_PER_FRAME 100/ b% C2 c3 t2 r" W( }) Q$ _5 E
  160. 5 b$ }4 W! E* s% n
  161. /* VLC table */  x  O  n. M+ z* r8 G" V
  162. #define VLC_SIZE 44 I! s; U) N: E$ @$ O6 l
  163. static struct' X+ Y: n  J% T
  164. {$ |( X% N# L& _) k# Y
  165.     int count;& R0 s/ E7 r/ B0 A9 V. l: c
  166.     int value;
      J* I5 _7 i3 |0 z# W9 D
  167. } lzs_vlc_table[] =
    ) v! g$ R, |6 v$ Z6 W8 \1 W/ D8 Q
  168. {
    * t6 {5 ]7 A8 N3 ~8 ^. L# r
  169.     /* code length = 2 bits; value = 2 */( y" x* |, a/ o7 a0 e) q
  170.     /* 0000 */ { 2, 2 },
    " d1 d! X9 }+ L3 P. e5 M2 ]
  171.     /* 0001 */ { 2, 2 },! p4 c* s1 P* q0 Y- z  V# a
  172.     /* 0010 */ { 2, 2 },: [' @( W% Z1 p
  173.     /* 0011 */ { 2, 2 },9 u* ^5 h+ s6 S% W. x4 p# |
  174. / ~# o$ I& ^# x  Z" y4 }, e0 F. v
  175.     /* code length = 2 bits; value = 3 */
    2 k: s: b& b4 W% k" \
  176.     /* 0100 */ { 2, 3 },
    3 t. B# r4 J: M+ u$ o: P
  177.     /* 0101 */ { 2, 3 },
    ( i3 o/ G3 |+ i  c% Z; |
  178.     /* 0110 */ { 2, 3 },5 M: t  l3 _6 }! t. v' r4 [
  179.     /* 0111 */ { 2, 3 },
    % M! I; w5 r* ^5 ~' Q" w

  180. ) b/ J8 I- M$ |# L- H0 F7 S4 _
  181.     /* code length = 2 bits; value = 4 */
    3 Y) q) w% g8 O" g5 k9 \4 F
  182.     /* 1000 */ { 2, 4 },
    8 ^) S* p) [4 Z1 y
  183.     /* 1001 */ { 2, 4 },
    ; w' t# l/ L$ R4 K8 C2 [* u( C
  184.     /* 1010 */ { 2, 4 },
    ) _4 b; {  e0 q/ F; y, C
  185.     /* 1011 */ { 2, 4 },2 \6 e5 ?- }) p

  186. % ^. x. s- w% y/ Z0 ^
  187.     /* code length = 4 bits; value = 5 */
    / m9 d, {: L- i2 I1 ?) r, P! |" L
  188.     /* 1100 */ { 4, 5 },
    . O  L$ d, n" [/ _- \( y

  189. 6 m; ?! Z# H" d. _( n
  190.     /* code length = 4 bits; value = 6 */' {/ B0 q4 A4 {: Y1 \6 ^/ U0 a7 }: Y& z
  191.     /* 1101 */ { 4, 6 },) m) [/ q  y, B3 Q
  192. 2 L/ I6 \# P* V8 I" P$ Q, |
  193.     /* code length = 4 bits; value = 7 */2 i6 Q8 {( q, Z. C" y
  194.     /* 1110 */ { 4, 7 },$ |3 X" M% q2 Y9 G2 F

  195. ! r! q& r6 O% D/ H0 L$ k
  196.     /* special case */6 @" h& \1 o2 K( [7 |. m1 b% v, _' [
  197.     /* 1111 */ { 4, 8 }
    . c& I8 b. W. c; w: s
  198. };( o5 P: `  o4 i) d4 a
  199. $ V1 Z8 ^+ O% i& X  S
  200. typedef struct+ g7 r% o3 [+ d1 O
  201. {
    $ P- k; K, y. ^: }1 ^* a; _
  202.     int version;
    " _- g- Y4 |% ~! H! Z" b4 k/ P$ n
  203.     int width;
    % m8 W+ Q. i3 S8 T( U
  204.     int height;
    + Q, N! a4 \0 H
  205.     int frame_count;
    1 Y) {' _: D! \5 w0 w+ U, e
  206.     int audio_chunk_size;
    # v# z! X" {( i6 j. M' [
  207.     uint8_t palette[PALETTE_COUNT * 3];( C/ c/ X# `+ I) A) `' h4 l
  208.     off_t video_frame_size_table_offset;! g; i. C# x4 s6 E! t
  209.     uint8_t *video_frame_size_table;8 V* A# T9 i* ~
  210.     off_t frame_size_table_offset;/ ?6 p5 ?+ }; J8 }1 [/ r! _
  211.     uint8_t *frame_size_table;
    6 w2 y1 `. z# K; \  n' C
  212.     uint8_t *frame_load_buffer;
    ) u; k: C4 P& p* H
  213.     int dump_frames;) t/ `1 E8 P- W# D0 F# `# S
  214. 6 j1 `6 N& u6 j* A# D8 T3 r
  215.     /* subtitle library */' Y+ s  Z  \* V; k4 ]
  216.     ASS_Library *ass_lib;; k% {. U% e, m
  217.     ASS_Renderer *ass_renderer;
    ' d! U2 T/ f; X- Q* v; n0 c! `
  218.     ASS_Track *ass_track;/ u4 z+ Q" I: T$ @, I1 e
  219. } rbt_dec_context;
    - i) ]: Z7 I# p

  220. : G! u: T9 V: k& k
  221. static void dump_pnm_file(char *filename, rbt_dec_context *rbt,; K" s6 s) E# i) {: T
  222.     uint8_t *image, int width, int height). w7 Y- {* _! X& u/ M9 g. x2 Q  ]  Z& p
  223. {  b7 v) z6 _: u: _9 N
  224.     FILE *outfile;
    5 U' H: b( ]) ]- e
  225.     uint8_t bytes[3];
    " d5 S  G' ]) U
  226.     int p;
    0 ~2 Q( X' S0 L; B  ^
  227.     uint8_t pixel;
    # R  F" o, T1 L4 p; |- m6 V

  228. $ t* ?3 e/ z% P) i) X
  229.     outfile = fopen(filename, "wb");& f! {5 P; B5 v- H
  230.     fprintf(outfile, "P6\n%d %d\n255\n", width, height);
    8 l- k, \1 M* k0 R5 {6 V$ C
  231.     for (p = 0; p < width * height; p++)
    * s, D# f2 ~% V/ E  F+ W7 ]" o$ i
  232.     {
    - J  q5 w& |% _6 ~% {  `
  233.         pixel = image[p];! @6 o& R, c- K) C2 L
  234.         bytes[0] = rbt->palette[pixel*3+0];
    7 W  d4 X& x% ?' C4 X4 ?5 s
  235.         bytes[1] = rbt->palette[pixel*3+1];
    3 P# {7 J7 f, r/ [, S
  236.         bytes[2] = rbt->palette[pixel*3+2];
    $ Y; r5 \( D+ g7 H% _
  237.         fwrite(bytes, 3, 1, outfile);' {2 T; Z6 x$ [# ^! t4 T4 ?
  238.     }' |7 g! n  g  h
  239.     fclose(outfile);9 x  n$ C6 r# k' [- U
  240. }
    8 z7 v; c$ Y5 }) P
  241. : W3 \4 v8 c$ o0 R
  242. static int load_and_copy_rbt_header(rbt_dec_context *rbt, FILE *inrbt_file, FILE *outrbt_file)
    2 y' `" T5 c8 n% a* U
  243. {! r  `- _( X# Z: S
  244.     uint8_t header[RBT_HEADER_SIZE];, o8 Q+ ?/ c4 S' G
  245.     int palette_data_size;9 X9 z% X4 I9 ?# E( S5 K& O# C
  246.     uint8_t *palette_chunk;
    , Y: H2 X$ o" P3 r9 T2 ?  i/ x+ g
  247.     int unknown_chunk_size;, c) v+ w" B3 H" |: y8 w/ Y
  248.     uint8_t *unknown_chunk;: h3 L7 P# W& W' S) M3 `/ c. d
  249.     uint8_t unknown_table[UNKNOWN_TABLE_SIZE];. F2 ~6 v: g+ e' Z' a" e
  250.     off_t padding_size;  @$ i! h8 C& `' L5 z9 V/ r
  251.     uint8_t *padding;: {% m+ E5 {5 L' ?
  252.     int i;
    1 G- e! ~- ~* d% ~1 E" G& e0 U
  253.     int frame_size;
    $ S% r9 T' P" i. T/ {( y) w2 a" t
  254.     int max_frame_size;
    5 C0 x; }" m5 M2 w
  255.     int first_palette_index;
    9 k! |' e! H% t# q: m
  256.     int palette_count;0 I# c6 }: \: L# c+ e) H. a& O9 [+ A
  257.     int palette_type;
    , G& O* c  N3 `5 V% G
  258.     int palette_index;
    ! C! R5 M+ b1 O! i2 r4 |- a% @

  259. & I# Y7 E# d& E, a( o
  260.     fseek(inrbt_file, 0, SEEK_SET);% Q$ t( o" k$ D; E# X  D
  261.     fseek(outrbt_file, 0, SEEK_SET);: M- d* y: U4 `) ]  W  }7 R

  262. * g& y9 k4 m0 B+ {' G( O
  263.     /* load the header */8 v) X4 Z4 Y. {/ m9 t6 E. ]$ Q8 f2 q% w2 y
  264.     if (fread(header, RBT_HEADER_SIZE, 1, inrbt_file) != 1)
    4 [) W: ]# K: j3 z4 H
  265.     {
    # l0 ^  ^3 t9 d* q
  266.         printf("problem reading initial RBT header\n");
    3 r) n( J1 m6 o$ S* R" n$ u
  267.         return 0;/ t+ X9 s" l2 m+ \& t( X  b; q) `
  268.     }( I; D% D- e& V
  269. 6 X& n) W. C$ m+ I6 l7 b7 v" }9 l9 ?. P
  270.     /* copy header to the output */- ~$ V. K0 H; M/ j% x) z
  271.     if (fwrite(header, RBT_HEADER_SIZE, 1, outrbt_file) != 1)
    # X$ H" I& m6 G9 F
  272.     {$ z. V2 z& I0 s7 ]8 N5 [* T: Y
  273.         printf("problem writing initial RBT header\n");- x' B9 |8 `3 V5 G9 h
  274.         return 0;7 F1 v/ X; D# M+ T% ^
  275.     }' o$ m8 r6 o+ }

  276. / U, G& `4 J7 T5 u( \6 v
  277.     rbt->version = LE_16(&header[6]);) y: q0 F3 d5 e& B
  278.     rbt->audio_chunk_size = LE_16(&header[8]);$ z, l0 a1 S2 R: t
  279.     rbt->frame_count = LE_16(&header[14]);
    1 _* v! E1 e. E6 T

  280. ; k  b2 i+ V0 i  x; D
  281.     /* transfer the unknown data, if it's there */
    1 \+ Q9 c2 l! ^2 d
  282.     unknown_chunk_size = LE_16(&header[18]);
    2 N9 i7 f2 Z1 z2 K/ M
  283.     if (unknown_chunk_size > 0)) e8 Z0 }! l3 C, T+ E  Z! ~% \' v
  284.     {: P9 ]" `0 E# B( d5 G6 A3 @
  285.         unknown_chunk = malloc(unknown_chunk_size);
    2 u) m1 O. x$ v* C; C& s
  286.         if (fread(unknown_chunk, unknown_chunk_size, 1, inrbt_file) != 1)4 [" V& x, U- e6 f; p& J
  287.         {
    # r) F7 P! |: X* C- r! P/ ^2 `( A
  288.             printf("problem reading unknown data\n");# ?0 y5 W) K6 }7 k
  289.             return 0;
    % C4 }. R# Y, Y
  290.         }# o0 v- H2 L/ G' q) j
  291.         if (fwrite(unknown_chunk, unknown_chunk_size, 1, outrbt_file) != 1)) r4 I' N+ o1 ^1 E; [9 S
  292.         {6 T3 Y& a$ \. e" G; i: k) C) e
  293.             printf("problem writing unknown data\n");
    . e' I6 P, C) t. W
  294.             return 0;$ L. i. p8 S' `! {
  295.         }8 _) t/ C: Z+ h9 V
  296.         free(unknown_chunk);3 e9 V0 k2 Q- F4 Z; p% c, ]# }) e
  297.     }, _1 ?% U! w/ S( ^0 ?
  298. % o( H* S' b! V, J- I
  299.     /* transfer the palette chunk */) v/ F: ]- p- s" W. ~' x7 O
  300.     palette_data_size = LE_16(&header[16]);
    9 J/ Q; t' ~! u$ @; W4 E! k
  301.     palette_chunk = malloc(palette_data_size);
    # A. [+ U4 a" K1 k4 i- [( I
  302.     if (fread(palette_chunk, palette_data_size, 1, inrbt_file) != 1)
    & K+ A. G$ Q. v, y# y
  303.     {
    & y5 a1 E2 i) `
  304.         printf("problem reading palette\n");* A. p8 W  Y  Z$ ~& H
  305.         return 0;
    ' ~; T  l5 N' ~1 v
  306.     }
    2 j, J- k- J' B) p) @1 a
  307.     if (fwrite(palette_chunk, palette_data_size, 1, outrbt_file) != 1)! R: C' ?- w) w* x
  308.     {
    * V) }* @. n. h: h# [7 O
  309.         printf("problem writing palette\n");$ g% A7 m  u! w9 \! D
  310.         return 0;' v8 T( Z+ @8 A4 _6 Z
  311.     }
    ( _$ U1 X+ L' [3 m# Y" ^" W
  312.     /* load the palette into the internal context */
    ! f2 ?6 ?; [  O9 \  T
  313.     memset(rbt->palette, 0, PALETTE_COUNT * 3);( x3 e6 p3 ?2 P( n5 D% ^7 J6 q* j
  314.     first_palette_index = palette_chunk[25];
    # r7 X5 d7 m2 u3 O' [0 y0 x% }
  315.     palette_count = LE_16(&palette_chunk[29]);8 w1 X+ p: s, g$ {& X4 q- x
  316.     palette_type = palette_chunk[32];* B' W7 V; J6 ^4 d
  317.     palette_index = (palette_type == 0) ? 38 : 37;6 [6 F8 W) i' f- a* B' S' U) ]
  318.     for (i = first_palette_index; i < first_palette_index + palette_count; i++)
    ( b; R/ b) u8 i+ w4 N7 Z. m
  319.     {
    8 h. x5 e7 i5 p
  320.         rbt->palette[i*3+0] = palette_chunk[palette_index++];' `; Z# C3 q) S  T- Q8 E
  321.         rbt->palette[i*3+1] = palette_chunk[palette_index++];6 b9 p6 d  s7 a) @
  322.         rbt->palette[i*3+2] = palette_chunk[palette_index++];2 W+ r' X( P8 G! m; e" B
  323.     }; u4 s- w4 k& u
  324.     free(palette_chunk);
    7 j; d' c" n9 @3 h6 i& G; y
  325. * O! c& L6 D. I, A1 k, F
  326.     /* copy the video frame size table (2 bytes per frame), as a placeholder */: G4 R+ W( o2 R8 R+ g
  327.     rbt->video_frame_size_table = malloc(rbt->frame_count * sizeof(uint16_t));
    ! b' }# m$ L4 N2 K; `% Y1 d! H
  328.     if (fread(rbt->video_frame_size_table, rbt->frame_count * sizeof(uint16_t), 1, inrbt_file) != 1)
    ( o2 D2 {8 E, Z5 G  Q- Z
  329.     {
    4 n! \" Y1 R/ [3 O* _3 C
  330.         printf("problem reading frame table\n");
    # T: z  k/ R0 n) \8 i6 Y
  331.         return 0;
    % w4 `: A+ t/ u/ Q! b/ x! n8 a
  332.     }0 D% J) s" q, \4 j  s
  333.     rbt->video_frame_size_table_offset = ftell(outrbt_file);1 C& s2 `7 z* [/ ]
  334.     if (fwrite(rbt->video_frame_size_table, rbt->frame_count * sizeof(uint16_t), 1, outrbt_file) != 1)7 N+ L- M9 [& U5 p
  335.     {
    , [1 [* T+ p4 L! m+ U7 j
  336.         printf("problem writing frame table\n");
    9 B- E' b, N) g8 h( j; Y
  337.         return 0;
    3 W7 d6 p1 |1 W- B8 {; v
  338.     }
    + e4 S8 b) q8 Q5 [0 ^: i& O
  339. ; h5 M3 |$ E9 c  b; ?
  340.     /* copy the frame size table (2 bytes per frame), as a placeholder */
    ) g3 \" a+ c( s& a
  341.     rbt->frame_size_table = malloc(rbt->frame_count * sizeof(uint16_t));
    ( J/ M! `1 y" b. P/ k/ _% T
  342.     if (fread(rbt->frame_size_table, rbt->frame_count * sizeof(uint16_t), 1, inrbt_file) != 1)5 m4 z" @& X6 C. |2 m, {5 H
  343.     {2 P3 H6 b& q% q+ g  i
  344.         printf("problem reading frame table\n");
    * o5 j4 d# ?5 U0 M
  345.         return 0;
    9 C  D4 s- W9 M/ N1 e7 p
  346.     }
    0 r0 b. E3 Y. X9 i% D8 B# O6 h
  347.     rbt->frame_size_table_offset = ftell(outrbt_file);0 V: A3 V4 O; \. F* g& @
  348.     if (fwrite(rbt->frame_size_table, rbt->frame_count * sizeof(uint16_t), 1, outrbt_file) != 1)
    & o2 G6 ^( U- Z( N9 y
  349.     {
    9 [# M. ]3 R. r# z4 ^+ t/ ]
  350.         printf("problem writing frame table\n");
    / C1 d$ Y7 u/ ?
  351.         return 0;) |- Z  j; w; ?* n" M. l3 c7 B7 o# [9 r
  352.     }: E7 S/ y! z' A! J  ~0 {6 ?: z

  353. 1 r8 [5 ]: e- {" n
  354.     /* find the max frame size */
    . }0 f4 i0 ~' R. _
  355.     max_frame_size = 0;# ^% w. U2 E) W- ^# e
  356.     for (i = 0; i < rbt->frame_count; i++)
    / a6 |8 U8 j4 y1 E0 l- m
  357.     {
    . F3 m8 U1 |; W0 r  s
  358.         frame_size = LE_16(&rbt->frame_size_table[i*2]);! d' N7 N5 Q6 y
  359.         if (frame_size > max_frame_size)0 @  S1 _# S/ X+ |  K' H  z
  360.             max_frame_size = frame_size;
    " j( C' |& U/ s- k$ n4 D- L( w
  361.     }- u  s+ C8 z" u1 {$ F$ D. ]
  362.     rbt->frame_load_buffer = malloc(max_frame_size);
    4 g1 C$ N$ x  T; `7 z

  363. ( h  p; S  M( M- C# I
  364.     /* transfer the unknown table(s) */
      T% w/ ?# ?0 T) r0 [& {
  365.     if (fread(unknown_table, UNKNOWN_TABLE_SIZE, 1, inrbt_file) != 1)
    9 H; G- Q' r: u! G& o- b5 G& v% O
  366.     {# F/ ?  [, M  ^
  367.         printf("problem reading unknown table\n");( f8 z& R6 r( A9 A
  368.         return 0;
    , T, i% m( z) n* j& D
  369.     }) z7 B8 P: h3 a/ c& D
  370.     if (fwrite(unknown_table, UNKNOWN_TABLE_SIZE, 1, outrbt_file) != 1)
    6 ^8 ]/ M( j# }* r. e: R
  371.     {& u) k. c0 L- ]( X  o
  372.         printf("problem writing unknown table\n");1 S5 t! K! s4 N" {/ t
  373.         return 0;
    2 s5 Y1 M3 p# I# h6 f
  374.     }
    & z) l, _& E% T2 K' A. @

  375. + r7 D$ Y/ Y9 M
  376.     /* copy over padding */
    ; ~2 e) q$ R8 G! V( X
  377.     padding_size = 0x800 - (ftell(inrbt_file) & 0x7FF);; ]6 o- U, F" \$ P; H' @8 a2 u6 {
  378.     if (padding_size)
    5 S" f% m/ B% L
  379.     {
    + B/ E* h- }4 [5 f- H3 X
  380.         padding = malloc(padding_size);
    & I5 ^* o  A( B1 G& B1 j/ @
  381.         if (fread(padding, padding_size, 1, inrbt_file) != 1)
      H7 x3 O. N+ R6 n/ E
  382.         {; ]( X2 y2 S  g/ C" p/ d( ]
  383.             printf("problem reading padding\n");
    ! u( f3 a* ?/ s) M9 v) M
  384.             return 0;
    $ }  {# [. K4 m! C/ i8 v2 @2 L2 t
  385.         }. n& q$ R. {. ~. x1 C4 x
  386.         if (fwrite(padding, padding_size, 1, outrbt_file) != 1)
    * Q/ N/ @1 T, L, w6 L5 ]! Z; P
  387.         {
    : u3 \5 Y7 q* r$ |; U# v; B
  388.             printf("problem writing padding\n");! l6 u7 p1 }9 ]
  389.             return 0;0 h# f: i9 O) C
  390.         }
    6 R' k$ c& h/ c1 d/ D6 p. W/ Z) U
  391.         free(padding);4 f- j: X' s# y# d( q5 J( w9 d, [
  392.     }
    , I& I7 Z9 X6 k: D
  393. " r3 r9 Q3 e: E+ V; {
  394.     return 1;
    $ h7 R/ j7 K  a/ ?6 {! `, G
  395. }
    ) _4 k# c3 M8 @3 l2 K

  396. " B# s) n5 ^/ y' S. v' H
  397. static int get_lzs_back_ref_length(get_bits_context *gb)
    / T& i" W7 s/ r* K
  398. {
    1 v: W: A6 q' i! v5 H+ Y2 u' x
  399.     int vlc;
    ' N* L+ l0 s$ L# q) T' D( e8 b
  400.     int count;" V' b2 |* D1 m, N8 N
  401.     int value;
    8 w+ K% f) ~$ u" O
  402. " }) [9 M# o1 z+ X( a$ k
  403.     vlc = view_bits(gb, VLC_SIZE);. ^3 f2 j( R) X# p+ d
  404.     count = lzs_vlc_table[vlc].count;) [3 K5 O6 _  p5 Y
  405.     value = lzs_vlc_table[vlc].value;4 n/ U' t4 Z: y% E! L  X4 N

  406. 3 t3 x+ q& B4 [. f
  407.     read_bits(gb, count);  Q% u" g  Z% G0 P4 A4 }
  408.     if (value == 8)
    $ Z: t; O) B2 @' I" P6 Q* d
  409.     {
    * F6 N" k, Y4 }% M7 j. F
  410.         do
    " u7 S2 G2 S2 N+ Z2 W
  411.         {+ d4 v; Z/ h, ~, k
  412.             vlc = read_bits(gb, VLC_SIZE);
    & p9 u( t* B3 p
  413.             value += vlc;
    # K' u9 Q: S3 k; A) f# n9 E
  414.         }
    ' Q& [$ {$ Q/ y
  415.         while (vlc == 0xF);6 m- v. u4 f1 u& n, h2 p; P
  416.     }& J+ j9 C) M/ s. W- q/ a

  417. 9 |6 y& ?, t0 C4 z3 ]$ {: s; w2 `
  418.     return value;
    ) w+ U# ~/ R" Y$ S
  419. }5 L% G% H0 c( M, o- J! {
  420. ' D$ Q, B' e; T+ m9 R- `2 a
  421. static void compress_window(put_bits_context *pb, uint8_t *full_window,- I9 F  U6 j# o- R2 u& o
  422.     int full_window_stride,
    - A1 a0 S5 }7 Y5 ^: m7 O
  423.     int window_top, int window_bottom, int window_left, int window_right)
    & `. M$ a' A# K
  424. {6 j2 p2 q; ~' h/ @, g* T
  425.     int last_pixel;
    $ G! Y. t3 @" E
  426.     int run_size;
    7 d- g4 j/ |9 E$ O) b: \& s- L
  427.     int x;
    6 K4 \- m/ {) l2 K
  428.     int y;) p/ ~" P4 t. t6 S* z6 R' l8 u! y
  429.     int start_index;
    ) b5 f) S0 v: y% H- n) S4 V+ z
  430.     int end_index;
    ( H" d3 G. @) S- m
  431.     int encode_last_run;7 T; Z2 m. X5 g; E  ?4 f0 c
  432. $ Z: s3 q, q4 c$ g
  433.     last_pixel = full_window[0];3 h9 \. u5 `5 H$ ]$ c2 y
  434.     run_size = 1;, |4 b: B! Q* Y! p8 q  U
  435.     for (y = window_top; y <= window_bottom; y++)
    6 F3 L. e& D- v/ J; R; t0 L
  436.     {
    2 z/ t9 Y4 A0 D
  437.         start_index = y * full_window_stride + window_left;9 n" N, W+ |4 B$ e5 Q' ^. G( D" V( a
  438.         if (y == window_top)
    4 ~9 q# b  O/ ?2 Y( ^$ J
  439.             start_index += 1;/ k% p  {: K: M" l
  440.         end_index = y * full_window_stride + window_right;
    $ a$ q5 ]: n+ u! {% Q6 O( ~' }
  441.         if (y == window_bottom)4 y8 G3 `* j* [. u0 i- K
  442.             encode_last_run = 1;
    9 ^+ ?% d( f; Q, }9 a
  443.         else
    0 G4 U" L' Q. R; F: g/ `2 N3 m
  444.             encode_last_run = 0;
    7 T' k! o% o* V( L
  445.         for (x = start_index; x < end_index; x++)8 ^) `5 Y1 \8 ^1 k: P3 Z
  446.         {" T7 n7 v$ Y; B, W+ i: p% X  F
  447.             if (!encode_last_run && full_window[x] == last_pixel)0 E1 \' E3 d6 k! K7 T
  448.                 run_size++;
    $ f1 g, Y, ^8 \8 [0 P& G
  449.             else
    * J. D# w$ M, _: \
  450.             {
    + B( G2 W$ p! z! Q3 Q; N
  451.                 if (run_size == 1)
    * T0 u4 ^& A+ W2 p! p! r6 ^4 i
  452.                 {
    $ {3 o# r5 a0 \% s: X9 d
  453.                     /* encode a 0 bit followed by raw pixel byte */
    9 t( D& ~' K; |& s$ P
  454.                     put_bits(pb, 0, 1);
    ! a. R  W- D0 t1 T. D8 m- l+ a  ?
  455.                     put_bits(pb, last_pixel, 8);; n7 _! _( K; r  H! y0 h! ?1 k# Y
  456.                 }
    9 u+ G9 g0 ^5 s4 t0 Q; f
  457.                 else if (run_size == 2)% j: ^7 `- K$ l7 `3 T! h( q0 n. L
  458.                 {
    ) x, ]6 T+ b6 E& \) V' g
  459.                     /* encode a 0 bit followed by raw pixel byte */7 G& B: m, W  ]! E7 J  J0 d! n
  460.                     put_bits(pb, 0, 1);0 x" T- m! y: B0 ^6 X" R
  461.                     put_bits(pb, last_pixel, 8);
    % [; K; Z# P9 \/ F: U
  462.                     put_bits(pb, 0, 1);
    : a9 v9 d+ Z' J9 [% M0 {
  463.                     put_bits(pb, last_pixel, 8);
    ; O, e4 i) A# l5 }8 ?5 x4 [
  464.                 }
    / `) j5 S3 G# E
  465.                 else
    1 p  P' g2 y. M4 z4 Q5 ?8 A3 G( W2 J
  466.                 {
    / i( N1 ^# b3 i
  467.                     /* encode a 0 bit followed by raw pixel byte */, n- m) @% l2 S  A+ x/ l
  468.                     put_bits(pb, 0, 1);$ r" ^* e, r; ]- S
  469.                     put_bits(pb, last_pixel, 8);1 R( R5 Z) l, \9 p* E
  470.                     run_size--;
    ; l, B$ {; `. M
  471.                     /* encode a run: a 1 bit, followed by a back reference9 D  M+ z1 B: n; i" F' A
  472.                      * offset (-1), followed by a length */" Q' f! U3 \9 C1 e/ n
  473.                     put_bits(pb, 1, 1);. X" ?) k8 a* m8 e2 e
  474.                     put_bits(pb, 1, 1);  /* 1 = 7-bit offset */
    . l9 }. F: D1 w; K
  475.                     put_bits(pb, 1, 7);
    8 g( S8 Y# K% D* f3 b# y
  476.                     if (run_size <= 4), M! P5 i, O6 S& M
  477.                     {
    0 l4 y% |! s! G$ s0 @' c
  478.                         /* lengths 2, 3, and 4 are 2 bits */
    0 M6 D! _7 N4 j' q( u; s8 k4 t
  479.                         put_bits(pb, run_size - 2, 2);0 ~( U/ M6 N7 }& ^3 p$ d
  480.                     }
    5 v* `# ?0 }7 |$ a. V6 K
  481.                     else if (run_size <= 7)
    6 p) z8 H: u, `" h& z
  482.                     {
    , s3 z" v# H% C- q$ L
  483.                         /* lengths 5, 6, and 7 are 4 bits */
    4 `, u. L/ d& Q6 Z# e
  484.                         put_bits(pb, run_size + 7, 4);
    0 O8 m# q( T# f! B/ @0 S
  485.                     }
    9 l0 L# I0 H. q! E7 Q) W( _4 H
  486.                     else
    - t0 s: i2 f/ \' Z
  487.                     {+ Z3 J, T$ i+ x$ [9 z. ]6 g
  488.                         /* arbitrary length; start by encoding 0xF which0 m8 R# k( E) N' q1 S
  489.                          * stands in for an initial version of 8 */
    % `" A" q6 K8 N% Z. W( }
  490.                         put_bits(pb, 0xF, 4);% q% u) ^- @7 y) z0 p* _% d
  491.                         run_size -= 8;' a7 S' t/ t3 n7 h  f9 O1 I

  492. . R/ P/ m5 {& L# G! h7 l* M8 ~6 J
  493.                         /* encode blocks of 4 bits until run_size is 0 */- e1 h+ m' {! k
  494.                         while (run_size >= 0)
    8 I) Q) H9 ~0 s. M. C3 q
  495.                         {+ [( k1 S! S7 I% Q. E5 P- l9 J
  496.                             if (run_size >= 15)6 T* Z1 O8 C# B7 f& s+ k
  497.                             {4 h* b! A' q% a( ]5 ?
  498.                                 put_bits(pb, 0xF, 4);5 ]9 a* p; _! F5 ]$ L
  499.                                 run_size -= 0xF;& |# @( X. [8 ^6 g6 d, g  g
  500.                             }. H& Q3 l1 [0 Q3 [
  501.                             else8 j! _( @. s3 N5 p9 K
  502.                             {
      d+ L) ]) N* F# p: q# S. A: ^- z. S
  503.                                 put_bits(pb, run_size, 4);1 G$ G) |1 B  s  ~7 k
  504.                                 run_size = -1;+ h& i1 E/ `( i6 O( M9 P
  505.                             }
    3 \' J7 \* m& R* L# y/ {
  506.                         }
    & L' H7 @  u1 X& k
  507.                     }
      t0 D* I$ l4 n9 |. g) o$ g
  508.                 }7 A0 Q4 K4 q# D% H

  509. $ ^+ y: r0 ?; V4 s4 T) S* Z5 r" v( N; u
  510.                 last_pixel = full_window[x];
    6 V3 @7 ?; o, U# n  M% n3 }+ B" z( J
  511.                 run_size = 1;$ H' [9 A' I, E0 f" p
  512. - [( S0 Q' g: a( D: }3 Z! A
  513.                 /* this single x iteration was only here to close the final run */* ^4 b' p, [0 n! ?" \
  514.                 if (y == window_bottom)! K' X. [/ C! W
  515.                     break;2 T) Q( P* _& U5 O9 L
  516.             }% p1 \7 V) \' a* i
  517.         }2 d: j+ N9 u9 ~* ^& H
  518.     }- P% H( t8 Z' ~  a6 o8 S
  519. + I, M) d0 `, O" U- O7 f& s1 W6 M( B
  520.     /* close the bitstream by encoding a back reference with length 0 */1 _0 w  Y6 R* Y0 j% j5 [- M6 }3 m
  521.     put_bits(pb, 1, 1);  /* back reference run */
    ! x/ w% L( W' Z, {( f
  522.     put_bits(pb, 1, 1);  /* 1 = 7-bit offset */, o3 T9 |9 @# ?
  523.     put_bits(pb, 0, 7);  /* length 0 */
    ) T) W, W* Y/ i( |1 q) W" q

  524. * J: R) k! q3 N! O0 O% G
  525.     put_bits_flush(pb);, a6 G: O* C9 `6 A, ^1 Z
  526. }
    7 k& Y3 s2 P. @' h- X8 a+ F& w

  527. 2 @: x! t+ f0 ~# t7 j' J
  528. /* compute Euclidean distance between an RGB color and the desired target */
    ; T+ f! |% w& N- q) ^& b
  529. static int compute_rgb_distance(int r1, int r2, int g1, int g2, int b1, int b2)
    + V# t0 Z  r, D
  530. {) V) H6 F- d: K
  531.     return sqrt((r1 - r2) * (r1 - r2) +
    7 v5 Q/ T3 f: y" I* t+ z: \+ n
  532.                 (g1 - g2) * (g1 - g2) +6 e% g0 d2 ~' w: a& {
  533.                 (b1 - b2) * (b1 - b2));+ w  H' H% C8 A
  534. }
    ) }0 e6 E, [: T% l( {1 Y
  535. ; p: v- N; q+ ?6 U
  536. static uint8_t find_nearest_color(rbt_dec_context *rbt, int r, int g, int b)  y/ J1 ?+ H% Y
  537. {7 v) e9 k! z0 u) n% A) G4 t: L8 n: a
  538.     int i;
    5 `2 B9 f4 s5 k, K- L
  539.     int nearest_distance;1 S* j+ I9 U3 Z0 j
  540.     int distance;
    ; Q' S. @! l- K$ ^
  541.     int rp;
    : M1 V* p+ W2 s9 j% d9 J
  542.     int gp;
    3 t# u6 R' V! X! I1 A
  543.     int bp;
    . j, {: |6 S" Q: K5 ~
  544.     uint8_t palette_index;( m, h6 L6 [% g9 o6 }4 E% R
  545. 0 L( X, ^6 E  \
  546.     nearest_distance = 999999999;
    - [( z/ ~! V0 `6 s2 y7 d! p9 k
  547.     palette_index = 0;1 g0 l, S5 C+ k- Q& n
  548.     for (i = 0; i < 256; i++)
    1 E2 [" w& j1 D7 X) x
  549.     {
    * s9 R0 V- n8 _5 {
  550.         rp = rbt->palette[i * 3 + 0];
    + M5 C' D& w7 {) ^
  551.         gp = rbt->palette[i * 3 + 1];  U: i+ l, |  m" \1 x; P" t, p$ q
  552.         bp = rbt->palette[i * 3 + 2];
    5 m* \9 g' W; K0 Y* c
  553.         distance = compute_rgb_distance(r, rp, g, gp, b, bp);
    - X: \) C  y0 n3 P8 r
  554.         if (distance < nearest_distance)& `3 S) c7 ?" L  [* y
  555.         {
    : T! X1 B8 c/ M( z7 M1 {7 i% P! T
  556.             nearest_distance = distance;
    , _/ C+ L  T3 [7 g- }: j
  557.             palette_index = i;; m5 s6 w; c  B. r/ Y2 a: P
  558.         }  Z# W. y. J' v1 B7 T, H
  559.         /* can't get closer than 0; break early */
    * c2 J) x" Y- x* c  n& Y: S: d% B
  560.         if (distance == 0)+ s  m: R7 E( j( _+ U' i0 X
  561.             break;
    8 k% {9 q7 M& V  l7 K  a
  562.     }
    " \6 w5 @! O! K4 I/ _5 W& w
  563. 9 x2 X% P6 G& q% w
  564.     return palette_index;
    / u. \" O1 G: M6 t4 f8 V' Z
  565. }6 {" g. l. x$ \* s* E) b9 D

  566. 2 B- n8 Q0 b' g
  567. static void subtitle_frame(rbt_dec_context *rbt, uint8_t *frame,% a. i1 O$ N" ?: v; r, [
  568.     int width, int height, int timestamp)1 S8 q. E. {3 N9 N2 F" s
  569. {% o7 C5 k7 ]/ C9 `& U7 x4 H/ G: v
  570.     ASS_Image *subtitles;5 |% \7 C+ C2 f# o
  571.     int detect_change;' N( c& M6 j7 V6 i
  572.     uint8_t subtitle_pixel;4 B' w. r, h6 e& o* k" R
  573.     int x, y;
    8 a# P6 O2 Z! z" x& B
  574.     uint8_t *frame_ptr;" H, F$ q- k3 i
  575.     uint8_t *subtitle_ptr;
    % X2 g  ]& C4 n8 B

  576. 6 h* M: B% s3 c3 S
  577.     /* ask library for the subtitle for this timestamp */. h* v8 a( T1 s& K. A
  578.     subtitles = ass_render_frame(rbt->ass_renderer, rbt->ass_track,
    2 Q0 [& [5 A/ |5 U% S. e2 Y- f
  579.         timestamp, &detect_change);
    % b. k$ ?: ]- {  K5 s2 M5 ^; O

  580. + J, D" C1 u( u9 D9 Y  V; c+ \  |4 @
  581.     /* render the list of subtitles onto the decoded frame */& g8 u$ l* T+ H9 V8 \% T
  582.     while (subtitles)
    : _5 s, ?  B: c  V, i9 O7 H
  583.     {
    & T7 }& B$ J3 u0 C! R5 ?
  584.         /* palette components are only 6 bits, so shift an extra 22 Q4 b- F6 Z9 h' ?1 ~. D
  585.          * bits off each component */
    6 P% l/ r  n: k$ s  _
  586.         subtitle_pixel = find_nearest_color(rbt,; H2 k. n" w) b  S$ ?& [
  587.             (subtitles->color >> 10) & 0xFF,+ _- E/ i  k" w/ N, {
  588.             (subtitles->color >> 18) & 0xFF,+ x% R2 i$ m0 }/ a! r! a
  589.             (subtitles->color >> 26) & 0xFF);
    ; Y8 t& X2 b/ E! {8 Q
  590.         for (y = 0; y < subtitles->h; y++)
    ) t" m! T- R9 R+ d$ ~
  591.         {
    : @1 k  i4 B8 ?+ y7 m! |
  592.             subtitle_ptr = &subtitles->bitmap[y * subtitles->stride];4 T8 ]7 R) o/ q8 |
  593.             frame_ptr = &frame[(subtitles->dst_y + y) * width + subtitles->dst_x];
    ) r, w; ~3 K& W! Z2 P: o. @3 f
  594.             for (x = 0; x < subtitles->w; x++, frame_ptr++, subtitle_ptr++)! o" T! }( d) K! P0 L
  595.             {
    / q- d! u9 i2 p5 z; y2 H
  596.                 if (*subtitle_ptr >= SUBTITLE_THRESHOLD)
    3 }1 t; z$ }, j. s
  597.                     *frame_ptr = subtitle_pixel;$ z, |+ p1 s3 Y$ z
  598.             }
    ' X: B, x/ h0 `
  599.         }
    0 H: @# h$ U( o+ E$ ]# ^9 X
  600.         subtitles = subtitles->next;. W4 `* z+ q/ Y) t8 e! Y4 E, |
  601.     }
    " _/ F. _! J4 W% h) [2 {
  602. }9 I) B" l# k4 B7 g, T  l
  603.   X3 H, w  n9 G2 W4 X1 c6 e$ R
  604. static int copy_frames(rbt_dec_context *rbt, FILE *inrbt_file, FILE *outrbt_file,' f. a, \+ |% i: j  v; T! R
  605.     int origin_x, int origin_y, int window_width, int window_height)
    9 _* g+ e/ d; }% P6 s+ ~7 k
  606. {
    & F* F" ]6 E' F9 h; P- b3 W
  607.     int i;/ L# ?& z% H5 r' J9 N& G# F" D
  608.     int j;' c; |; }8 k8 P1 x
  609.     int scale;# t2 l; |! R" C$ x% W- v# r  F$ c7 M
  610.     int width;
    ; B  o3 m2 ~; `/ J" {, D
  611.     int height;* a4 N9 L& V) E. M: E- V7 f
  612.     int max_width;% t# Z" ]! M6 v" R, Q! ^9 B
  613.     int max_height;4 A  g4 c+ `, r  r
  614.     int frame_x;! T9 E( D% m. L
  615.     int frame_y;
    + t# R, v1 }0 d
  616.     int fragment_count;
      O! T7 w/ J" d2 k8 X/ j
  617.     int decoded_size;) q  X' Z! p7 b, o6 Y8 o6 v
  618.     uint8_t *decoded_frame;) [, U8 S0 L5 u% f5 B/ [: ?; j
  619.     int fragment;
    6 R5 d4 ^/ c5 a; w
  620.     int fragment_compressed_size;! e: F% d- z% I' |1 m  h
  621.     int fragment_decompressed_size;
    4 a6 l- C2 l8 h6 i8 V) o
  622.     int compression_type;7 M8 ?1 Y6 S$ t8 {- ^, n
  623.     int index;5 i" c" }# e( |3 Q$ C
  624.     int out_index;6 R/ {$ g9 Q4 }- e
  625.     get_bits_context gb;( |$ l9 V* p, ]6 r; Y1 u8 U
  626.     int frame_size;. Q. x0 W, q" o* r+ S# Y. Q* m! g
  627.     int video_frame_size;0 b3 M5 w( T) Z8 I5 i( @* \
  628.     int audio_frame_size;3 L9 L" G( a" t  b" K

  629. . c% Z3 H% E7 T
  630.     int back_ref_offset_type;
    6 u# R5 N4 P2 Q# N) |
  631.     int back_ref_offset;
    & J7 Z9 q2 a! C$ [2 V" m2 o: q
  632.     int back_ref_length;
    + d  H. N6 R( C- X" _
  633.     int back_ref_start;
    5 d- n% n+ \2 w/ N! }+ \
  634.     int back_ref_end;
    # {! b& c, t  D4 I  m" W" f. Q6 R
  635. - n* N1 E# }2 ~
  636.     uint8_t *full_window;' S, C5 s+ c! I  e
  637.     int full_window_size;
    ! f: Q. C: r% K1 ?$ Q7 Y( Y" n+ Q
  638.     int y;, u( W; ^# [) T- k  Q
  639.     int window_top;
    $ m" v* D) o5 d* V: {' ~/ c2 n
  640.     int window_bottom;
    ! H2 w6 q7 a4 ?& d
  641.     int window_left;, @8 r3 E6 g4 E
  642.     int window_right;8 ~/ T3 W" a+ L( f+ \+ N9 O, c
  643.     int window_size;% J6 q  n' H  C( N+ A! M9 |  }

  644. - q5 Y# M! C) t
  645.     char filename[30];
    6 a2 T: J9 O5 T+ ], b, B1 M: f

  646. ! t4 `3 l! y# [- @. i) B0 [
  647.     put_bits_context *pb;. i4 ^0 O0 D2 ?# \

  648. ( X9 I/ b& {% K0 i% |
  649.     full_window_size = window_width * window_height;0 y, T4 Y* @+ `7 e6 L! r
  650.     full_window = malloc(full_window_size);
    # l% V3 g! i% z' v) ^
  651.     pb = init_put_bits();
    $ _/ N* ~# u$ ~, ]" f7 V% h
  652. 6 e* [0 h6 L% R  C2 w' Y/ P% O
  653.     max_width = 0;
      S2 z  Z7 p6 s9 t- G
  654.     max_height = 0;
    9 ?3 P! U( W4 p8 `6 h  @: F
  655. 0 H5 k5 f. s( O& ^8 [5 r
  656.     for (i = 0; i < rbt->frame_count; i++)
    0 w7 @2 P) y0 e2 g  D( Y
  657.     {6 K3 O9 f4 L. O: i" L& B( S
  658.         /* read the entire frame (includes audio and video) */6 [; Q4 j8 l" S& b& b% z" v
  659.         frame_size = LE_16(&rbt->frame_size_table[i*2]);
    $ R6 I* R! V- x7 p- L6 a) k4 {4 `
  660.         video_frame_size = LE_16(&rbt->video_frame_size_table[i*2]);
      z6 z8 z3 h) U$ Y* e. _: Q0 y* r
  661.         audio_frame_size = frame_size - video_frame_size;% y0 c) [6 z  U1 h+ V: d
  662.         if (fread(rbt->frame_load_buffer, frame_size, 1, inrbt_file) != 1)1 l/ G/ A& y  [' R, k( _) F
  663.         {. l# j9 H8 n$ X* E) g5 k  ?
  664.             printf("problem reading frame %d\n", i);3 O0 L( I2 w; G3 H6 h% ~
  665.             return 0;
    4 [  V$ t5 [" o
  666.         }1 Q3 x1 p% G; x0 s
  667. 2 @- W# \+ Z$ Q9 H; M
  668.         scale = rbt->frame_load_buffer[3];
    8 G/ m# x! |0 K, @( v7 b8 A
  669.         width = LE_16(&rbt->frame_load_buffer[4]);  z; ~, Y6 Q) ^- n4 }7 p, c2 {2 ?' t: H
  670.         if (max_width < width)$ ~* n/ u5 s  o& C2 i7 `& Z
  671.             max_width = width;# S6 N& r8 F4 o' D$ h
  672.         if (max_height < height)5 ~  Q( J5 `- D- |
  673.             max_height = height;
    7 \- W9 p7 p5 W  i! i( H8 }
  674.         height = LE_16(&rbt->frame_load_buffer[6]);( m) g- J7 K4 o; p) a1 J
  675.         frame_x = LE_16(&rbt->frame_load_buffer[12]);
    % M7 W) m2 O" P: e9 x/ z
  676.         frame_y = LE_16(&rbt->frame_load_buffer[14]);
    ! W+ |% ?0 @( W% V
  677.         fragment_count = LE_16(&rbt->frame_load_buffer[18]);6 j0 d0 y5 V3 u8 u7 m/ W5 ]
  678.         decoded_size = width * height;
    # U+ h$ J! D& f! z7 v5 M9 G
  679. 1 l/ @" S) y6 x5 D( K3 P
  680.         printf("processing frame %d: %d%%, %dx%d, origin @ (%d, %d), %d fragments\n", i, scale, width, height, frame_x, frame_y, fragment_count);* `6 \9 A( V. z2 M
  681. * ]+ L6 j3 T8 }% v
  682.         /* decode the frame */7 I  R4 H5 E2 U% w
  683.         decoded_frame = malloc(decoded_size);0 {+ r& s! j6 X
  684.         index = 24;
    ) j) Y( w- y+ m" y+ F3 D/ ^
  685.         out_index = 0;6 d% h; _/ M0 m& a" ^1 i
  686.         for (fragment = 0; fragment < fragment_count; fragment++)$ ~. j5 p+ v* A$ j6 [, e. `
  687.         {9 u8 T' u1 |! _
  688.             fragment_compressed_size = LE_32(&rbt->frame_load_buffer[index]);3 L& d5 H% T( R/ {
  689.             index += 4;- A' h9 T' y+ D) x8 ?
  690.             fragment_decompressed_size = LE_32(&rbt->frame_load_buffer[index]);
    1 W. D7 B$ h. e9 L
  691.             index += 4;
    3 u& c- X5 K; V# s+ F) v
  692.             compression_type = LE_16(&rbt->frame_load_buffer[index]);
    4 }! c# k$ N( F5 b3 I8 b* I
  693.             index += 2;2 s0 P0 n: U$ T' g2 x1 C7 O) i
  694. " y* N# q0 Q/ p# l2 R
  695.             if (compression_type == 0)
    " C! S* l3 @. x" `; D
  696.             {
    0 e+ v' j# t# s; T$ E- r
  697.                 init_get_bits(&gb, &rbt->frame_load_buffer[index],
    " i; k& e# g0 g7 Q% B& b. T
  698.                     fragment_compressed_size);, r. d& j0 C: v# a" }  C

  699. 6 ]! a2 Y- u  r1 Q! y5 Z
  700.                 while (out_index < fragment_decompressed_size)0 T% k* M5 N1 h% g; W0 h9 T
  701.                 {
    7 m9 K4 @- ]8 r8 j7 q  d, @; u
  702.                     if (read_bits(&gb, 1))& w& B. @8 W# M& ^
  703.                     {
    % ~5 F6 d7 l! Z5 C4 S
  704.                         /* decode back reference offset type */
    ; n0 c4 Q9 x. A  L  q
  705.                         back_ref_offset_type = read_bits(&gb, 1);: }0 P9 d+ B9 r. ^0 L( b
  706. 7 w) o6 b2 I0 z* `, d; ^
  707.                         /* back reference offset is 7 or 11 bits */7 y8 ^& Q- x6 p: f
  708.                         back_ref_offset = read_bits(&gb,7 d- B3 y/ z6 Z3 ~6 n" O: `
  709.                             (back_ref_offset_type) ? 7 : 11);% z' G9 k  v: y  k* x' G1 n: {
  710. 4 \4 `4 |: r0 I$ O+ m
  711.                         /* get the length of the back reference */
    8 k4 |% c$ I& N
  712.                         back_ref_length = get_lzs_back_ref_length(&gb);
    ! D) ^3 s: V5 \  ^3 X, p9 T
  713.                         back_ref_start = out_index - back_ref_offset;
    1 v2 b$ ^- h  \# |
  714.                         back_ref_end = back_ref_start + back_ref_length;: n( ]8 z- y( {. {! G' [
  715. * p( Q7 Y0 _8 `5 J
  716.                         /* copy the back reference, byte by byte */
    + ^! I+ Z& I0 @! Q& |
  717.                         for (j = back_ref_start; j < back_ref_end; j++)* s" D" ~1 L6 s1 o* Z
  718.                             decoded_frame[out_index++] = decoded_frame[j];5 Y2 Y& W5 Y: b3 P
  719.                     }
    & U0 u- Q% a# u; s  [/ {; @
  720.                     else6 O9 C0 U( _+ l# R
  721.                     {* d! {1 j4 H; ~- F8 ?) z
  722.                         /* read raw pixel byte */( L% v' T6 \+ L
  723.                         decoded_frame[out_index++] = read_bits(&gb, 8) & 0xFF;
    : K3 g& P# `9 U5 o5 Q' A
  724.                     }
    $ E$ u5 ^$ I7 \! D2 z7 p: }# U# t
  725.                 }
    - s, a7 e: m4 c

  726. 8 e: m+ P2 H* Y# [  d
  727.                 delete_get_bits(&gb);
    $ @, w- B/ ^6 I6 g1 ~1 N0 P
  728.             }
    2 \* T3 }- d3 _
  729.   D$ z# {- S9 I4 w* ]. Y
  730.             /* next fragment */
    % e' _# N7 m4 |  b
  731.             index += fragment_compressed_size;2 f# Q% j# m; |- |
  732.         }" f3 k. P  Y1 [# L& C

  733. 4 Q- b* X1 O; p, p& F& t& a- e
  734.         if (rbt->dump_frames)" [$ O" @% H' t% ?+ B
  735.         {; ?- H, k, u+ r" l  ^4 @7 g
  736.             /* dump the original frame */
    / d. a5 [5 M' X: [7 _
  737.             sprintf(filename, "original-frame-%03d.pnm", i);  d# B- H! h! I: M5 E* l! ]
  738.             dump_pnm_file(filename, rbt, decoded_frame, width, height);
    2 o& l. _% K+ u& V. ?
  739.         }
    5 n1 l4 e1 p1 w- u- }: {! t4 q
  740. 9 @" U3 j! q/ }4 p& ^
  741.         /* transfer the image onto the frame window */- e8 c9 [0 z1 ?0 X
  742.         memset(full_window, 0xFF, full_window_size);- L8 C- {$ u8 p' P5 F( ~& ~
  743.         index = 0;
    ) ~/ o9 G/ f% p
  744.         for (y = 0; y < height; y++)6 X. W# x; d# Q' s% W) C; X
  745.         {
    # u- e6 f* j6 t7 A: b
  746.             out_index = window_width * (frame_y + y) + frame_x;/ \5 B, m' n+ j
  747.             memcpy(&full_window[out_index], &decoded_frame[index], width);
    ; d/ U, v0 p* J2 p2 @8 V* m' y0 V0 m
  748.             index += width;
    6 k; h8 n/ S/ \% v# q7 U! f
  749.         }
    : |6 L5 i6 n& S$ ^% }
  750. & j7 [% c( u# E3 \  ~3 Q
  751.         /* write the subtitle */
    8 B; S/ O9 s- W( [0 G4 Z7 W
  752.         subtitle_frame(rbt, full_window, window_width, window_height,
    ) R0 c/ j# o  U9 c7 P
  753.             i * MILLISECONDS_PER_FRAME);  e2 D$ d0 Q+ p4 A# G
  754. ; Q" W+ v9 m, c+ h* `4 {$ M
  755.         /* figure out the smallest change window */
    . K: F4 O) Y; s! i
  756.         window_top = frame_y;
    3 ^/ w1 i, O7 l5 @5 h
  757.         window_bottom = window_height;, P  j3 w* y+ ^: t: P. q
  758.         window_left = 0;& Q5 a) h0 U( m
  759.         window_right = window_width;! F8 Z. w1 w7 ?
  760.         window_size = (window_right - window_left) * (window_bottom - window_top);2 n0 a6 _/ `/ Z' B) O
  761. 7 u7 i6 n! h7 F/ p
  762.         /* compress the frame */
    ' `) F2 e' p' q6 \8 U
  763.         reset_put_bits(pb);
    + [6 f5 O- L( q) [
  764.         compress_window(pb, full_window, window_width, window_top,# L! T. d' K: G
  765.             window_bottom, window_left, window_right);3 p" X- A. A3 L0 N, E

  766. ' C2 ]6 V" b% i5 t; N4 [
  767.         if (rbt->dump_frames)
    ' C9 u: D5 j: I0 k
  768.         {9 D& j5 ~: ?' a/ ^
  769.             /* dump the frame plotted onto the full window prior to encoding,
    ' j9 [* }% W! V& i1 ?
  770.              * with subtitle */
      ~( G) d+ u+ ]5 ]7 ?6 A
  771.             sprintf(filename, "pre-encoding-frame-%03d.pnm", i);/ J1 ?$ O6 Y; P/ x- j; i
  772.             dump_pnm_file(filename, rbt, full_window, window_width, window_height);! E; q. m7 P3 I: t. Z
  773.         }! Z/ X1 f0 S) p8 y* {* ]5 c+ R

  774. 5 ]' d5 y1 o8 l6 H8 M' O
  775.         free(decoded_frame);
    4 E7 j& ?- L' {2 H# R

  776. 8 T  h$ `8 i0 O5 [/ V! K6 a1 p
  777.         /* update the frame header */! K3 R, ]$ O5 \& m, n: P. j1 I. `" q
  778.         /* width */' k/ x; N& e5 t7 m' {) h  F
  779.         rbt->frame_load_buffer[4] = (window_right - window_left) & 0xFF;0 l- Q7 w9 V# k, y4 o: ^* D. g
  780.         rbt->frame_load_buffer[5] = (window_right - window_left) >> 8;) V/ @: P* h$ i- c
  781.         /* height */; Q5 @' N0 P5 v: R- C; }/ E& U* |
  782.         rbt->frame_load_buffer[6] = (window_bottom - window_top) & 0xFF;# n% ~# u8 y4 d# E6 |+ t& @
  783.         rbt->frame_load_buffer[7] = (window_bottom - window_top) >> 8;
    / _$ T1 b. h! Z* g9 F2 E% z0 {
  784.         /* origin X */: P2 h5 r) x7 F/ Y
  785.         rbt->frame_load_buffer[12] = window_left & 0xFF;
    & z$ w; Q( x. s# Z
  786.         rbt->frame_load_buffer[13] = window_left >> 8;
    4 d9 Y* R! k. N; y3 x# _( ~
  787.         /* origin Y */
    . ~% k% E: J( P3 Y& z* E, ~
  788.         rbt->frame_load_buffer[14] = window_top & 0xFF;
    8 [0 p, d) d( N: L4 z! `
  789.         rbt->frame_load_buffer[15] = window_top >> 8;
    ( t+ W8 ?1 N! j8 S4 K; y
  790.         /* fragment payload size */' }5 O& O3 O* B/ |3 W
  791.         rbt->frame_load_buffer[16] = (pb->byte_index + 10) & 0xFF;
    ! X- Z: c+ C- V1 n
  792.         rbt->frame_load_buffer[17] = (pb->byte_index + 10) >> 8;8 u, L6 X- b* K) @$ m( G; P! y
  793.         /* fragment count (1) */8 J0 x6 j; Y2 o9 L: h9 v
  794.         rbt->frame_load_buffer[18] = 1;/ |7 Q! d2 e5 R
  795.         rbt->frame_load_buffer[19] = 0;
    6 I. S9 [: Q0 j

  796. / C. Q, g' k7 o8 M1 j2 U6 |
  797.         /* update the fragment header */9 v4 u- \/ s/ q2 |7 ?9 F
  798.         /* compressed size */
    / S( F  f/ F7 _9 B0 U
  799.         rbt->frame_load_buffer[24 + 0] = (pb->byte_index >>  0) & 0xFF;  ~, J0 U7 i8 m7 o& }
  800.         rbt->frame_load_buffer[24 + 1] = (pb->byte_index >>  8) & 0xFF;6 z$ d& U& A, |! C& l! u  {0 L
  801.         rbt->frame_load_buffer[24 + 2] = (pb->byte_index >> 16) & 0xFF;5 R) F& g4 k, G7 i/ T& L1 S8 k, s
  802.         rbt->frame_load_buffer[24 + 3] = (pb->byte_index >> 24) & 0xFF;' y: Z' n8 d# T
  803.         /* decompressed size */
    , N; a1 ?- b3 r1 n! J
  804.         rbt->frame_load_buffer[24 + 4] = (window_size >>  0) & 0xFF;* a0 w8 q2 P: |2 e0 @
  805.         rbt->frame_load_buffer[24 + 5] = (window_size >>  8) & 0xFF;; |; m9 C, a( E& ^& n& i& [) |! Z' W
  806.         rbt->frame_load_buffer[24 + 6] = (window_size >> 16) & 0xFF;
    * h0 ]* j: L* w) K- N
  807.         rbt->frame_load_buffer[24 + 7] = (window_size >> 24) & 0xFF;
    ! Z# H3 F7 E0 n8 c: S6 R" m8 L
  808.         /* compression format 0 */
    ' S2 ^8 e# z8 W, A
  809.         rbt->frame_load_buffer[24 + 8] = 0;/ a0 D0 E: f, h! s4 b, M
  810.         rbt->frame_load_buffer[24 + 9] = 0;3 m" Y- T0 z9 P" d

  811.   b! Z& T* M7 H  z% A
  812.         /* write the 24-byte frame header and the 10-byte fragment header */: B7 Z9 X: V$ g! ]8 D6 h
  813.         if (fwrite(rbt->frame_load_buffer, 24 + 10, 1, outrbt_file) != 1)8 t- E. j- D7 ^4 C* w! Z
  814.         {
    ; Y' n! f2 m7 X/ t' G
  815.             printf("problem writing frame %d\n", i);
    - w( [: S4 S& g2 Y
  816.             return 0;
    7 Q* y1 X. V1 P5 g: T' y, _
  817.         }
    8 g5 R7 K( f" R5 [

  818. 8 U4 k) i- d+ e) G4 \
  819.         /* write the new compressed frame data */
    # s9 ]0 y0 p! {6 _2 t! `
  820.         if (fwrite(pb->bytes, pb->byte_index, 1, outrbt_file) != 1)# C/ Y2 h% V- U) b
  821.         {- i) G$ H% [+ q5 I' H/ W
  822.             printf("problem writing frame %d\n", i);1 l1 G$ e' p% U/ ?9 n# R
  823.             return 0;
    6 d9 f% D& R; k
  824.         }' Z) P! _0 E; c2 r1 j! O

  825. ; M8 E# ^+ V3 e& w5 m# @7 g  R
  826.         /* write the audio data */
    & p- w" v1 y% @+ N% a* Z5 R
  827.         if (fwrite(&rbt->frame_load_buffer[video_frame_size], frame_size - video_frame_size, 1, outrbt_file) != 1)1 u) ]5 V) G: b, n3 d7 l  ]1 G8 f- N9 p
  828.         {8 J) L' q0 O' F
  829.             printf("problem writing frame %d\n", i);
    . |, T+ u6 A- H% M
  830.             return 0;
    2 E  t- T4 H8 w  o. r( K( l$ \: P; b
  831.         }, x- g6 M" o$ l$ A$ I# e) X

  832. % P. Q3 T( \- y- |! _
  833.         /* update the table entries */+ ?( X4 J0 }& u4 g
  834.         video_frame_size = pb->byte_index + 24 + 10;# g, D% l. N& v* H4 l0 o2 K
  835.         frame_size = video_frame_size + audio_frame_size;
    5 L% u( S$ G* @$ q' T) E
  836.         rbt->frame_size_table[i*2+0] = frame_size & 0xFF;1 w$ ~3 p7 i$ e
  837.         rbt->frame_size_table[i*2+1] = frame_size >> 8;
    % w; a6 j* `7 n2 r; w8 E- F
  838.         rbt->video_frame_size_table[i*2+0] = video_frame_size & 0xFF;
    - _* w- h( h  s3 y0 T  d8 }3 R9 n
  839.         rbt->video_frame_size_table[i*2+1] = video_frame_size >> 8;
    ( c9 s/ x( |, d$ A# C
  840.     }
    . E; T: Y) j: ^  _
  841. - W8 v' ^8 j# @! l4 J
  842.     printf("maximum dimensions seen are %dx%d\n", max_width, max_height);3 l. F/ B$ w* z, T5 ^+ N) F+ m! u
  843. & T2 E/ X3 q$ U( u1 p
  844.     delete_put_bits(pb);. W1 }2 m0 n0 v3 \
  845.     free(full_window);( Y. x9 C& T; M% d
  846. 0 H+ [" V8 W+ e$ l" N% C
  847.     return 1;
    : y0 T$ e6 t0 p+ o/ A* t
  848. }7 Y$ f2 c, V& y8 \. U* Z( ^4 \2 h
  849. & J0 S0 {# x, p: i: f" v0 b1 f3 O
  850. int main(int argc, char *argv[])
    1 R5 C1 J  e& w% k' m8 x8 ~
  851. {
    . X+ ^  N# [3 i' G" z
  852.     char *subtitle_filename;
    , G7 U; j+ B1 }9 G0 O4 B# S
  853.     FILE *subtitle_file;
    - e5 Q( ^7 Y3 Z6 `- N8 c: {; k! I8 f1 _
  854.     char *inrbt_filename;
    & \3 n1 K2 _& u/ r; J3 V; f5 Z& [5 V
  855.     FILE *inrbt_file;& ?* _* \" e* E- h7 y
  856.     char *outrbt_filename;) Y/ F+ h  a6 k& A" x
  857.     FILE *outrbt_file;
    9 [* \$ R1 }# [! u4 j
  858.     rbt_dec_context rbt;$ a% j/ {/ b4 f: L; E% ^
  859.     int origin_x;
    ! }) ?- g8 C# ^8 Z
  860.     int origin_y;
    8 x; X( K' |7 S/ s+ z2 j
  861.     int window_width;4 Y" f1 f' I* {* J+ `
  862.     int window_height;
    6 a. t- f/ r+ E3 t+ F2 T% G! T
  863. ( F1 s- A( [1 X5 y
  864.     /* testing the bit functions */; g2 w# ~, G- X5 G" M" O
  865. #if 0
    & B+ F" L$ c& }
  866.     int i;
    $ H& b# m  d% j: C: _) Y# z
  867.     uint8_t bytestream[] = { 0x55, 0xAA, 0x00, 0xAA, 0x55, 0x77, 0xFF, 0x1B, 0x70, 0x8F };
    - f& g* [% @! }5 v& O1 G  s
  868.     int bytestream_size = 10;; ^, n2 x  m, O! J
  869.     get_bits_context gb;
    / F# \" o, E! V) d! p$ ~  W7 X& r
  870.     put_bits_context *pb;5 |- c( o8 r* f# G+ X2 h* d
  871.     int bits;; b; Z* N$ p  I" ~# N* a+ `
  872. $ d; P. N! F  \/ a
  873.     init_get_bits(&gb, bytestream, bytestream_size);
    2 N4 B6 g0 E/ |9 J
  874.     pb = init_put_bits();
    3 c6 M7 N6 C! O0 k1 {7 s  ~

  875. $ b  B6 G$ X6 K
  876.     for (i = 1; i <= 12; i++)
    , T& ~" l" F! V- ]5 U6 s$ W
  877.     {+ o7 H+ ~/ W+ E4 P7 g+ t
  878.         bits = view_bits(&gb, i);3 i+ I) G" F5 w+ X) Z0 [& h& X5 P0 f
  879.         printf("view %d bits: %d\n", i, bits);
    6 d: @8 y4 x* Q: @! A% t0 Q- _" y
  880.         printf("read %d bits: %d\n", i, read_bits(&gb, i));
      O; ]$ {: T; W) u
  881.         put_bits(pb, bits, i);1 T2 k, z' f' C! R3 H" Y0 j7 ]' ^
  882.     }$ X( D; X4 |2 T, m
  883.     put_bits_flush(pb);% L: T0 y( y! Q* y$ H# o
  884. & ?: D6 Z! x! m: V2 k0 }: i
  885.     printf("original bytestream:\n");+ `- L% O7 o/ \/ i  z
  886.     for (i = 0; i < bytestream_size; i++)( I$ ~( `* k( N& z' [
  887.         printf(" %02X", bytestream[i]);% {0 C) Z5 i: p+ e/ N: _" L4 N8 [
  888.     printf("\nnewbytestream:\n");8 k/ M  O2 A' Y0 I0 z& r2 J
  889.     for (i = 0; i < pb->byte_index; i++)
    % R4 I. o8 Z2 L7 X5 a7 j  ?
  890.         printf(" %02X", pb->bytes[i]);
    * _# Q  b* D. C" [: p' G+ H
  891.     printf("\n");
    0 t  P4 T! H) `

  892. 7 E* [; v. g* ^3 V8 g, [
  893.     delete_get_bits(&gb);8 \# {6 v3 {5 u1 n& i0 q5 U  v# E
  894.     free(pb);4 ?* [& f6 {+ `. _1 j* G
  895. #endif
    1 M0 H- r0 f+ Z; w

  896. ! X/ n% i9 m& z/ L
  897.     /* validate the number of arguments */
    7 E: g/ h9 h0 b  k7 V3 h1 m8 W. ^3 y
  898.     if (argc != 8 && argc != 9)+ ]- d8 J( \& H2 p) V7 N, B- u
  899.     {
    % k$ m8 P: \" q0 a6 K
  900.         printf("USAGE: subtitle-rbt <subtitles.ass> <in.rbt> <out.rbt> <origin X> <origin Y> <width> <height> [dump_frames]\n");
    . b9 y  A6 q0 ]# Z3 L
  901.         return 1;
    " {$ v+ A/ I8 T  x4 x% P7 _" l/ `
  902.     }
    9 m2 M9 O4 S1 ]4 Q/ q
  903.     subtitle_filename = argv[1];4 [2 `& ?  h2 h$ h
  904.     inrbt_filename = argv[2];
    4 Y. \8 h4 H- Y
  905.     outrbt_filename = argv[3];
    : n, L5 h0 h/ V" F
  906.     origin_x = atoi(argv[4]);
    5 N/ r! h' A6 w# T5 `2 B
  907.     origin_y = atoi(argv[5]);
    # i2 z: Y: ~2 j' v" C8 X
  908.     window_width = atoi(argv[6]);3 n" ?0 O* \* m% ]
  909.     window_height = atoi(argv[7]);
    0 N5 @; C% R3 ^2 ^7 Q! s. h$ y* a
  910.     rbt.dump_frames = 0;6 Q0 u. J. v' k  K, g
  911.     if (argc == 9)* ^1 f4 ^. p8 N: y
  912.         rbt.dump_frames = 1;
    - F: W' U: M0 U4 b$ Y8 b* d

  913. + P. A, D7 }! W8 D
  914.     /* verify that the specified input files are valid */' h9 \5 \' S9 b1 s
  915.     subtitle_file = fopen(subtitle_filename, "r");& b. f; s: X! m' F( ]
  916.     if (!subtitle_file)! y1 ]( X9 f- M9 L, i7 u
  917.     {- {5 X, j5 I! r4 V8 `
  918.         perror(subtitle_filename);3 b  y, O3 c% ^+ r; ?, \
  919.         return 1;$ I# E- X* b$ [/ B, G4 _5 D6 v
  920.     }
    7 S/ P  {2 F$ X, Z6 f& R  F
  921.     fclose(subtitle_file);
    / L/ \. T1 \+ X0 @( }
  922.     inrbt_file = fopen(inrbt_filename, "rb");
      f" ~! ~3 s& t; F' f
  923.     if (!inrbt_file)) u. f" U. h2 `& h0 N5 m2 d
  924.     {; [* y4 J8 U% \6 h* P
  925.         perror(inrbt_filename);
    , m6 x1 ~" w. Y/ @* B
  926.         return 1;
    . f3 L7 p' l; U+ o8 y1 d4 b
  927.     }
    1 P- |: J1 o5 I; [  e

  928. $ ?9 \) H6 U8 R9 h& ?+ C, r
  929.     /* initialize the subtitle support */
    8 X" D4 i, W% `: n2 Y% }3 L
  930.     rbt.ass_lib = ass_library_init();# z, ~3 ~: ?$ W8 R6 i+ i3 a
  931.     rbt.ass_renderer = ass_renderer_init(rbt.ass_lib);+ g9 P7 C( J7 X5 L' K- v" x
  932.     rbt.ass_track = ass_read_file(rbt.ass_lib, subtitle_filename, "UTF-8");
    0 n' C8 l) t9 s% E( Q
  933.     ass_set_frame_size(rbt.ass_renderer, window_width, window_height);0 b9 S4 f7 `( \1 |2 L0 R
  934.     ass_set_fonts(rbt.ass_renderer, NULL, NULL, 1, NULL, 1);  ?# X8 L2 t; w: x6 _

  935. 7 k) B  K" r" n: ]
  936.     /* open the output file */
    # N+ e: L1 Z8 k, Q: u: N
  937.     outrbt_file = fopen(outrbt_filename, "wb");
    ; C6 ]  Q% ?& m+ Q0 r6 f6 q
  938.     if (!outrbt_file)* K) L) t- M+ w  y, d3 I
  939.     {! e* V  i  W( G( z
  940.         perror(outrbt_filename);/ B4 @3 ~$ I% L7 |/ X: |
  941.         return 1;
    & q0 v4 L" r5 I" y* a$ ?
  942.     }& e  T* _7 m% @; B  B- Y2 I& v- H

  943. % Y8 d$ ~  H! s. ?
  944.     /* transfer header from input to output */
    $ ~8 N( V+ A; w7 M
  945.     if (!load_and_copy_rbt_header(&rbt, inrbt_file, outrbt_file))
    0 ~" m; s  v2 f- p) r
  946.         return 1;3 v" N% ]9 K- u- j1 Z
  947. 0 {- n7 G& ~2 c
  948.     /* rewrite the frames */! P4 k5 v6 R4 `0 l' g+ K! B: g/ L
  949.     if (!copy_frames(&rbt, inrbt_file, outrbt_file, origin_x, origin_y,
    $ G; ^  s5 y, ^* s& v4 Z9 A
  950.         window_width, window_height))# q; E' U! T/ E" y& I0 Z) g: W8 l
  951.         return 1;
    7 t1 O1 F8 e* ?7 x7 B, A" u; t
  952. 8 f) u' l2 f% E/ Q. t" [3 Y3 ~
  953.     /* write the modified frame size tables back to the file */; \4 M! T9 G9 ]' n! W
  954.     fseek(outrbt_file, rbt.video_frame_size_table_offset, SEEK_SET);
    - d1 C( c" F$ M$ ]. y% Y
  955.     fwrite(rbt.video_frame_size_table, rbt.frame_count * sizeof(uint16_t), 1, outrbt_file);
    * k$ r. `: \9 S& M3 P
  956.     fseek(outrbt_file, rbt.frame_size_table_offset, SEEK_SET);  |9 e, n, P+ ]" O, d. p: ^
  957.     fwrite(rbt.frame_size_table, rbt.frame_count * sizeof(uint16_t), 1, outrbt_file);, w0 w/ m, G' h: P5 y: W8 L
  958. 3 f6 ]% u# r1 e' C& A1 P- |% i% K
  959.     /* finished with files */
    5 L* q1 |: c  _  Z7 q* r2 X+ ?
  960.     fclose(inrbt_file);3 S9 E: R" l& x. v/ k5 \7 l# ]
  961.     fclose(outrbt_file);/ P, A) f/ Z2 n' W

  962. ' ~6 i* y! W4 m. p. F; m
  963.     /* clean up subtitle library */8 W7 k- O. w" T( j7 M/ p* A; l
  964.     ass_free_track(rbt.ass_track);, b% Y+ X% d( r& F; z8 n7 R
  965.     ass_renderer_done(rbt.ass_renderer);- o$ `) Y- r) c. `7 k0 X
  966.     ass_library_done(rbt.ass_lib);5 p) x  Q6 ?, ^8 `) k
  967. # I& L( ~! k. N) j: D3 _- K8 K
  968.     /* clean up */
    % M+ _$ E+ v! r
  969.     free(rbt.frame_load_buffer);/ r0 Z: {/ n% f1 o! H) j7 O8 ~
  970.     free(rbt.video_frame_size_table);
    ! [4 j; J: @+ a  ]
  971.     free(rbt.frame_size_table);
    8 ]" F& H" ?! J5 g6 V2 t3 q/ G+ g- f/ {
  972. : d7 Q; t6 q" \9 A. J
  973.     return 0;
    # F3 T/ C! `0 e  Z4 j
  974. }
复制代码
1 L1 S( [0 |0 x- D

& J& p5 t0 U9 N+ Q. A+ v7 q) k: k
* B, ~, T: F/ S+ w$ q
/ x4 g' D3 R/ R
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 很美好很美好 很差劲很差劲
回复

使用道具 举报

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

使用道具 举报

板凳
 楼主| 发表于 2009-11-19 11:38 | 只看该作者
引用第1楼soring123于2009-11-19 11:09发表的  :( x9 g- v2 ?( W& t
这游戏有字幕吗?
; T$ |$ d- A7 U6 B# m* g
好像没有字幕,我说的是给视频外挂字幕方式的汉化。- ]- T: t! T: \
就像syberia2汉化版下面那行字一样。
回复 支持 反对

使用道具 举报

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

使用道具 举报

5#
 楼主| 发表于 2009-11-19 17:39 | 只看该作者
引用第3楼soring123于2009-11-19 17:07发表的  :$ c9 X2 H5 L1 _- w1 N4 a$ ~
我记得是没字幕的 比较麻烦 都是视频的

: ?' H( r  z$ V8 A给视频外挂字幕方式汉化也许能行。! k! _; ?. x# I- z1 ~* d  u
要结合dosbox和代理dll技术。
回复 支持 反对

使用道具 举报

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

使用道具 举报

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

使用道具 举报

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

本版积分规则

冒险解谜游戏中文网 ChinaAVG

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

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

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

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