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

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

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

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

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

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

本帖最后由 shane007 于 2021-1-2 13:56 编辑
4 P2 e4 l% U7 P, p( t
4 q& p# `. K- i. J最近找到了一些和幽魂系列Phantasmagoria 有关的资料,
. p/ {; j* L# y1 Q0 Q, B也许将来可以用于汉化。; {, O) K+ @7 T6 A. d

' d4 _7 N8 l1 b, k! c和日文版有关的信息" I: t3 E: z9 a1 w% w& e' |
http://anthonylarme.tripod.com/phantas/phintgtp.html- o5 Z) J$ `% K6 @" s" C/ q
. H7 f& y4 p* ~4 K
相关工具" `) Z5 I8 R( W
http://anthonylarme.tripod.com/phantas/phcheats.html
9 G* A) E0 I: t3 Y. R% M2 |-----------------------------------------------------------------------! O, U- m; [( F6 i; B& m
2012/1/2  更新
8 q: v' k) E$ }$ i; P' \/ t3 v关于幽魂游戏的字幕! a" }% T) ?& a6 l
Phantasmagoria subtitles function discovered - ScummVM :: Forums/ l/ y7 v7 q# N9 q4 d. p# R

5 K5 D0 t2 K( s; @) Z. XVMD文件
; T% ?. H4 e8 A! R4 qSubtitling Sierra VMD Files | Breaking Eggs And Making Omelettes (multimedia.cx)VMD - MultimediaWiki
5 k1 X. r" b' r4 K! z( `7 u- c; b8 m+ I3 Y/ G8 Y
字幕
' S( C4 ~' k7 f: D/ ZSubtitling Sierra RBT Files | Breaking Eggs And Making Omelettes (multimedia.cx)9 m4 i9 A, O5 @, ?( M5 _
& u5 M7 H) ]4 h2 h2 H
FFmpeg/subtitle-rbt.c at feature/VMD_encoder · multimediamike/FFmpeg · GitHub. M* `+ r: `0 B: p% |
  1. /*
    5 B1 I5 i1 ~( m! l& z
  2. * subtitle-rbt.c3 d9 L5 u; J: q$ v
  3. *  by Mike Melanson (mike -at- multimedia.cx)
    - w# \1 P6 b( u
  4. *" H. y  M0 i: w/ D+ j& ]2 ]9 b
  5. * build with this command:
    . |  G9 b; S  P' ^& U) N9 p. `
  6. *   gcc -g -Wall subtitle-rbt.c -o subtitle-rbt -lm -lass
    ; B' K2 Q" q1 j: H
  7. */
    - g) u( f+ q" T( Q5 E
  8. 0 E6 c0 q% |8 X
  9. #include <inttypes.h>
    / ~; C0 W+ `* n8 y; E
  10. #include <math.h>% p" Z5 X$ [7 K# h+ D* V$ |
  11. #include <stdio.h>5 Q' a4 Z1 y! ^! D/ H2 S
  12. #include <stdlib.h>
    $ v6 W0 Z0 {8 @! f- P1 z' a
  13. #include <string.h>
    9 w/ D3 M5 x( o3 l1 p9 U- b

  14. & V" V( ?6 S: @
  15. #include <ass/ass.h>
    0 f. l" P& d# `! ~

  16. ; s  @3 W1 B) L( Q- v& s
  17. #define LE_16(x) ((((uint8_t*)(x))[1] <<  8) | ((uint8_t*)(x))[0])% f1 `; y: R- Q9 M* V& |

  18. 5 u/ j; z0 P) K8 F4 _) K
  19. #define LE_32(x) (((uint32_t)(((uint8_t*)(x))[3]) << 24) |  \9 k7 w& t# C5 y- x4 Q
  20.                              (((uint8_t*)(x))[2]  << 16) |  \( ^$ D6 |, m% ~! z! i* U
  21.                              (((uint8_t*)(x))[1]  <<  8) |  \- v. V8 g0 `: Z- w/ s" `
  22.                               ((uint8_t*)(x))[0])4 r: `' @, z3 k7 f/ H; o

  23. " k# {2 n0 T: [
  24. /*********************************************************************/! a' ~/ g# m7 w" o0 M' l  x) g

  25. * l3 Z4 O  G9 z/ Y! |- f
  26. /* Bit reader stuff */
    " R; n* O) a& Z% {

  27. ; }5 d, V/ n+ `& r0 J, U
  28. typedef struct0 Q- ^6 i& e5 d# x
  29. {
    % [5 y* X; j3 G* c3 G- n
  30.     uint8_t *bytestream;
    6 g+ _! t, q% J; X: N$ G6 z( X/ n
  31.     int bytestream_size;
    ) X9 S% z1 M1 I+ {. U  ?# O4 k! }
  32.     int index;  @$ u( p7 P4 b
  33.     uint32_t bits;% N  ~0 r0 y4 {4 `# H! r2 D4 N3 \% R
  34.     int bits_in_buffer;* H+ N! [5 R! p& ?
  35. } get_bits_context;0 m# ]: W1 ]6 @

  36. " T: ]# x+ W& `$ H4 J' {7 o, u
  37. static inline void reload_bits(get_bits_context *gb)
    9 o0 u8 g& \: S% y+ p
  38. {
    5 @# F+ V, e0 B' V' t
  39.     while (gb->bits_in_buffer <= 24)% D' P: ^3 p3 a4 H0 Z0 D6 y
  40.     {
    % [5 A; }* b& \1 n
  41.         if (gb->index < gb->bytestream_size)& G6 I$ J) e& L7 l) \& T
  42.             gb->bits |= (gb->bytestream[gb->index++] << (24 - gb->bits_in_buffer));* A4 S0 g6 \% \/ Z  W' _" S
  43.         gb->bits_in_buffer += 8;
    8 V8 I5 D; C* U# t. k
  44.     }
    " w4 n4 B$ W! N- M
  45. }: z# c. }+ G9 f$ R3 Q. M

  46. 8 C+ `% `. B( C6 j/ J$ T
  47. static void init_get_bits(get_bits_context *gb, uint8_t *bytestream, int size)
    ) v8 C- ~' W8 O8 [% y
  48. {: [) j( O; @# D% ^6 Z& Z3 W
  49.     gb->bytestream = malloc(size);' T' F) n6 P! I$ }2 j9 {# `% N
  50.     memcpy(gb->bytestream, bytestream, size);
    , K! J; L7 ]7 A$ l8 _+ ~
  51.     gb->bytestream_size = size;+ V9 M6 n0 K3 P' G
  52.     gb->index = 0;' n5 r$ K5 A" h1 v; z5 A( p
  53.     gb->bits = 0;
    ! v+ ]* |/ u* K; b
  54.     gb->bits_in_buffer = 0;
    ) D+ }- Q8 j: O: Z! A

  55. 3 h# e$ r7 ~2 S! K. ~3 t5 t
  56.     reload_bits(gb);8 v2 q+ z8 w: k8 ~4 a1 Q) @
  57. }
    * p$ D  Y4 h4 [4 k$ |8 U" n
  58. ' G: @- Z9 D9 g% R  I- o' K
  59. /* read bits without consuming them from the stream */
    9 T! X' g0 e7 z( D1 F) C
  60. static int view_bits(get_bits_context *gb, int count)1 M1 q$ c" B3 c7 r- s5 u
  61. {
    8 l. o/ G5 c! f, |1 a* Z; p$ ?
  62.     if (count >= 24)
    & `+ q: {! |. {# |
  63.         return -1;+ v6 _3 ~9 j  `( i) Z9 Y$ s) r5 r
  64.     if (gb->bits_in_buffer < count)
    ; P0 X$ W: q6 Z* T
  65.         reload_bits(gb);
    ) c3 m( {" n8 q2 W) T# P
  66.     return (gb->bits >> (32 - count));* F6 {- S9 `  M' p: _9 q4 o+ ]) D
  67. }
    + T$ B0 R& v" R2 e+ V

  68. 4 p; P; o" a# b+ x2 r$ d
  69. /* read and consume bits from the stream */
    8 g: N4 V/ G" r6 t
  70. static int read_bits(get_bits_context *gb, int count); `/ x/ [% u( S# Z
  71. {+ m! m3 s) q2 G4 ?; \9 m0 N6 h  }
  72.     int value;! e$ r' I  K7 g+ m* `4 N( B1 k

  73. ! c1 N. R# Y( p6 v+ {1 N% t
  74.     if (count >= 24)3 T8 U7 t. p  X$ g  J5 R
  75.         return -1;) i! _" {1 c% G4 P
  76. 2 v; D# j# n# _; c
  77.     value = view_bits(gb, count);) v) i, F9 j! g5 p
  78.     gb->bits <<= count;
    7 \2 i0 u# q$ `- h8 @. C
  79.     gb->bits_in_buffer -= count;( s3 m  j% i4 O* R" i

  80. ! o3 v! [* I, l; n
  81.     return value;
    & H* |/ X) j! q  Y
  82. }
    7 U0 c7 b& n0 C; n" G& K+ j5 @& s

  83. ' ?& Z0 ~8 N: R4 q  j/ G
  84. static void delete_get_bits(get_bits_context *gb)
    1 S+ i8 a/ D6 r1 ~
  85. {: r$ q) V9 I1 {$ U7 u- |6 J  Q; g+ m
  86.     free(gb->bytestream);
    % `9 ]! {$ f& t/ L4 t* q: N9 h' ~
  87. }1 A: S: @1 P3 t* k

  88. . ~5 R) U! g" i1 q: F$ j$ F
  89. /*********************************************************************/! ~: L! M  V* z1 E. a1 Y

  90. / c' C" c+ G- h$ t
  91. /* Bit writer stuff *// \: C( `% \- c" K5 o) Z5 D+ e1 s) u

  92. - _1 c' R% }, G2 \1 k! e+ R7 `& Q
  93. #define MAX_PUT_BITS_BYTES 63000- n3 J+ |" k2 A  w4 T5 T5 I
  94. typedef struct& z5 p# Q5 N, G6 X: r
  95. {# I( t' Z$ \+ `& m4 I: e
  96.     uint8_t bytes[MAX_PUT_BITS_BYTES];( L1 ~; Q2 d% L+ o. @( w
  97.     int byte_index;
    9 s* O4 U' F' f6 U+ H* I; o- c
  98.     uint32_t bit_buffer;4 y% f6 A( \8 g  {# \% i
  99.     int bits_buffered;9 G% q, G/ ?$ r( k
  100. } put_bits_context;* r6 w! V2 w4 `- N# W6 S9 t4 d' w
  101. 7 b/ B4 t8 y2 t. ^7 ~  C
  102. static void reset_put_bits(put_bits_context *pb)  B+ I" \) D3 P8 f
  103. {9 v4 ^! a( k1 L/ t+ B1 ?3 C
  104.     memset(pb->bytes, 0, MAX_PUT_BITS_BYTES);' D- }. r: B# [. [
  105.     pb->byte_index = 0;' h) }+ n. F5 v. L' X7 f
  106.     pb->bit_buffer = 0;
    5 m: p, m6 Z8 A) x, @' U
  107.     pb->bits_buffered = 0;& m' J) N( x3 S& J
  108. }
    4 L: s5 D& G' d8 z- i
  109. 2 e1 U# h3 m/ n. t& M
  110. static put_bits_context *init_put_bits()
    - E9 z( I- r1 q( R; y  K2 N5 X
  111. {
    . |( F4 t: w! B5 j9 c
  112.     put_bits_context *pb;! [: C& X' P0 D) {

  113. 6 E' ^* ^1 {9 L* q
  114.     pb = malloc(sizeof(put_bits_context));
      M* }$ C2 i; g5 B+ F& I0 h
  115.     reset_put_bits(pb);
    ; I2 W; e8 ]" X+ ^
  116. 8 @% E" t5 q5 E9 p. v( k# J0 S. J
  117.     return pb;8 @/ s* o# A  h( Y% L) x: F
  118. }
    " f5 ^. z1 n8 `+ K: I" V( \

  119. , d8 I, g4 p& {3 `5 ~
  120. static void put_bits(put_bits_context *pb, int bits, int count)
    " s$ D% D# K1 ?
  121. {
    + l0 k9 i* ~/ l* {# {
  122.     pb->bit_buffer <<= count;5 n' p8 n# L& Y/ M* L
  123.     pb->bit_buffer |= (bits & (~(0xFFFFFFFF << count)));- L: N. U+ M4 P1 G) q
  124.     pb->bits_buffered += count;/ {5 X. ]7 `" U; @( U- f% Y- Y
  125. & }3 L5 [1 }1 a+ p
  126.     while (pb->bits_buffered >= 8)
    & s! @7 F. W$ X0 d6 t  t
  127.     {1 e9 P# a* u# O3 _, J
  128.         pb->bytes[pb->byte_index++] = pb->bit_buffer >> (pb->bits_buffered - 8);
    8 P* ?- T0 i8 s. X4 [
  129.         pb->bit_buffer &= (~(0xFFFFFFFF << (pb->bits_buffered - 8)));5 v  ]7 d) H& x: z
  130.         pb->bits_buffered -= 8;
      d' S2 s0 o- A3 V
  131.     }! ~0 A& U1 H$ v" A
  132. $ F2 m' M: W) V- e% p# {9 O, M
  133.     if (pb->byte_index >= MAX_PUT_BITS_BYTES)
    & `% K) s$ C  j* Q' c% @
  134.     {
    ; h+ ?. @7 s+ o8 K! T5 ~1 A
  135.         printf("HELP! Bit overflow\n");
    : x' b7 g2 C. K# @
  136.         exit(1);
    + G- q0 b8 C3 |6 H7 k% m& d. B
  137.     }8 D2 ?9 ^" n! U* W
  138. }
    2 a5 t. ]  G9 O) q2 J
  139. % z3 r; }+ z* t( k: [5 r
  140. static void put_bits_flush(put_bits_context *pb)" G* w* y4 b! p0 @' {
  141. {
    7 z3 P- I- }: g- |
  142.     if (pb->bits_buffered > 0)  v% h8 B; ?" X. P% I/ c9 F; H
  143.         pb->bytes[pb->byte_index++] = pb->bit_buffer << (8 - pb->bits_buffered);: i" V5 V+ _/ b7 r
  144. }' e% {4 Z9 t% M$ \- q. I- r5 I
  145. 0 Q$ N( o! |9 j+ |$ ~- J3 \# K
  146. static void delete_put_bits(put_bits_context *pb)- Y  c) s4 M2 G. i+ }  E
  147. {
    . a$ t( T3 r, C' G& f( W: q* |
  148.     free(pb->bytes);
    . x# b7 T3 ], _5 _
  149. }
    & |4 ]  q7 m9 y# p* f5 b

  150. , k/ c2 ?' j$ T
  151. /*********************************************************************/
    ' p1 a9 ^+ n0 m

  152. ; q" b+ {: T9 q
  153. /* RBT functions */. K, z& q+ T( |* [8 W$ N
  154. 6 w5 ]' g- e! D5 y2 S
  155. #define PALETTE_COUNT 256
    1 i, T& C5 M1 {2 T3 J, P
  156. #define RBT_HEADER_SIZE 60
    * C, m; s' o/ }: A6 J  [+ D
  157. #define UNKNOWN_TABLE_SIZE (1024+512)/ x8 [3 m9 C9 ~' ]
  158. #define SUBTITLE_THRESHOLD 0x709 j" l0 U, q3 J: i2 Q
  159. #define MILLISECONDS_PER_FRAME 100
    1 c1 m9 S3 g6 w2 a! C  M

  160. 1 K1 U& e; z% S0 l3 c, E' [( x( i
  161. /* VLC table */
    ) Z1 P# N9 q3 x) U/ Q6 l, |' ^6 x
  162. #define VLC_SIZE 4$ U* p* p0 y" B
  163. static struct: y- v3 u/ q3 ^! w  v" _( u1 F+ |/ {
  164. {5 \/ V7 h: h* Z5 {$ ^9 X
  165.     int count;. `' a4 _8 N7 a% Q, Y
  166.     int value;
    7 H6 i& ]0 Y2 Q4 T# K# M
  167. } lzs_vlc_table[] =
    4 B9 C8 o9 ~# k$ e* X# C
  168. {
    * Q1 J2 W1 O& V* n
  169.     /* code length = 2 bits; value = 2 */, f8 }% F! W# |. l9 K
  170.     /* 0000 */ { 2, 2 },& c0 B$ c, [: |
  171.     /* 0001 */ { 2, 2 },
    ( t" u) O; s" _( X* T; n: l
  172.     /* 0010 */ { 2, 2 },
    3 O4 I7 l0 ?! r9 w8 x9 `' h
  173.     /* 0011 */ { 2, 2 },
    4 ?* O3 w$ ^5 l8 j

  174. - R3 z5 H' y" B& u) r
  175.     /* code length = 2 bits; value = 3 */
    : q* r1 ^; L  c
  176.     /* 0100 */ { 2, 3 },4 l0 x0 W) @; q/ w% w( `9 n; l
  177.     /* 0101 */ { 2, 3 },4 o0 t! g' K9 i# Q% l
  178.     /* 0110 */ { 2, 3 },
    ; p: q5 c, `! r
  179.     /* 0111 */ { 2, 3 },
    1 H8 A% }# ~( T* ]% G

  180. 5 E4 w6 h2 Z! g( j: W+ ~0 i
  181.     /* code length = 2 bits; value = 4 */
    3 l' L  T+ l; L
  182.     /* 1000 */ { 2, 4 },, Z8 N" V5 X' e8 L1 D' P' T
  183.     /* 1001 */ { 2, 4 },
    2 F# {" M$ O. a0 K( C# n1 U
  184.     /* 1010 */ { 2, 4 },
      _) [4 ]" n, t
  185.     /* 1011 */ { 2, 4 },& {) u) f. ?+ d" a9 A9 b  ~

  186. / S+ [7 H0 f# F7 o, A3 Z
  187.     /* code length = 4 bits; value = 5 */
      h7 M" m& j! n$ Q5 B5 V9 n
  188.     /* 1100 */ { 4, 5 },, _1 R; l  I' c  V
  189. ! B: u( @1 x9 M% n& G
  190.     /* code length = 4 bits; value = 6 */( t$ z) ]$ w  |2 q
  191.     /* 1101 */ { 4, 6 },
    + ^! N: g( B6 F0 ]" |

  192. " y5 r# Y# n2 [$ j' _, Y
  193.     /* code length = 4 bits; value = 7 */8 P* b, F- @1 T% [
  194.     /* 1110 */ { 4, 7 },% V/ O& M& f! o# f) l. o9 `

  195. 6 H3 H# O9 X+ g% S2 H
  196.     /* special case */
    9 i" G' H. F9 W" Z
  197.     /* 1111 */ { 4, 8 }3 w6 h6 w) E9 c/ q8 t, N
  198. };6 D1 x! ]' x, w

  199. $ ?; {" b7 E1 b6 x1 u
  200. typedef struct
    1 G: e9 I$ C8 n, f- ^
  201. {
    # _/ j/ s3 ?( H4 Q& K+ q6 f. Q
  202.     int version;' g: y( y! l+ F3 L5 K. X
  203.     int width;
    8 h5 y/ s2 Y. g
  204.     int height;
    8 \+ h) d: U8 Z4 S
  205.     int frame_count;
    ) [9 ]! Q5 y4 l. s1 J% y  m
  206.     int audio_chunk_size;; F- j3 {" s7 x% ~9 s6 [
  207.     uint8_t palette[PALETTE_COUNT * 3];
      A0 I9 I0 V& c% o* T& u  K' F
  208.     off_t video_frame_size_table_offset;& Q1 c, i4 U& e; W
  209.     uint8_t *video_frame_size_table;' K8 D# z4 W2 ]8 Z
  210.     off_t frame_size_table_offset;
    , J' @8 S! \( s- W  e
  211.     uint8_t *frame_size_table;
    8 [, U$ f4 F" |8 R* [
  212.     uint8_t *frame_load_buffer;. |4 U* [5 R2 O: [
  213.     int dump_frames;
    $ i6 p# B/ ^; U% [& h$ F* `& Q

  214. 7 c5 P5 ~6 V" X' e; y
  215.     /* subtitle library */; K3 [5 n: ^/ c  n, H8 t4 V; L
  216.     ASS_Library *ass_lib;9 R! c+ @6 U1 p2 m2 q( ?2 O
  217.     ASS_Renderer *ass_renderer;
    ' D# c/ `. q! Q# Q! h
  218.     ASS_Track *ass_track;9 i' f: }2 T1 K$ z2 z/ O
  219. } rbt_dec_context;. Z5 l5 t; E. l8 E+ H
  220. 5 K# k. i4 _$ O2 Q
  221. static void dump_pnm_file(char *filename, rbt_dec_context *rbt,/ h9 ~8 V2 k# d, O" N# T) ]
  222.     uint8_t *image, int width, int height)
    3 Y# ^) K/ Y4 B  y! |8 b  p
  223. {
    " r# ^1 Q( I$ k% N6 w5 p# Y- j) l
  224.     FILE *outfile;- z9 C" G7 `  e+ H" H5 l( ?% [5 Q
  225.     uint8_t bytes[3];
    ( s- i5 h$ ?- x0 x& g) d
  226.     int p;
    , _+ r9 Q$ o1 |8 q' N
  227.     uint8_t pixel;
    % c& d( P3 e6 v+ g

  228. ) P0 t( S$ N  e6 R9 w
  229.     outfile = fopen(filename, "wb");
    / v) u, }: m, H4 \2 `) D
  230.     fprintf(outfile, "P6\n%d %d\n255\n", width, height);
    4 I& c: L0 T9 R5 ^
  231.     for (p = 0; p < width * height; p++)8 x6 ?9 ~1 G8 M5 H! d3 Z
  232.     {
    1 u, h+ h6 z5 l% s; k7 X# X# H7 e; C
  233.         pixel = image[p];
    6 A: s/ b0 j3 B4 n' ?
  234.         bytes[0] = rbt->palette[pixel*3+0];
    : F7 {7 I- V  F
  235.         bytes[1] = rbt->palette[pixel*3+1];7 {3 f: }+ U: d" Q% A2 N$ h- R( L
  236.         bytes[2] = rbt->palette[pixel*3+2];
    3 @7 g8 k0 L) h# \( ]5 T
  237.         fwrite(bytes, 3, 1, outfile);. U$ \* _$ ], d4 f
  238.     }7 X3 l) ?9 P9 m( ?) X8 }  s. C6 D9 u
  239.     fclose(outfile);
    8 b  C. `; f3 W$ A0 h
  240. }
    ! t0 [" n( q! B

  241. 1 T, {( @$ k- q& T0 L+ r) Z6 }
  242. static int load_and_copy_rbt_header(rbt_dec_context *rbt, FILE *inrbt_file, FILE *outrbt_file)
    4 F1 z& L1 y: G9 t* X0 K
  243. {
    6 a$ w: D1 }, k3 [- m% l% N
  244.     uint8_t header[RBT_HEADER_SIZE];
    , D# i# q3 w; r" V: }
  245.     int palette_data_size;
    , ?' r. u" o1 i* X; I7 t  Q2 F
  246.     uint8_t *palette_chunk;
    % \, \- Z4 t5 L1 D
  247.     int unknown_chunk_size;
    5 P& O$ q0 n) L. e
  248.     uint8_t *unknown_chunk;
    6 B' T: H9 Q! a% r& r+ X
  249.     uint8_t unknown_table[UNKNOWN_TABLE_SIZE];
    : w: l* n: X; [
  250.     off_t padding_size;
    + R1 i0 z* Q/ _5 j9 q4 [4 m
  251.     uint8_t *padding;% P5 d. X$ x# m' S- J! v1 g
  252.     int i;
    ' A. @$ H3 ]' }
  253.     int frame_size;) J$ _) u8 w9 J: o2 [0 \
  254.     int max_frame_size;
    6 u$ A. X) R  r2 ]9 _/ h1 x
  255.     int first_palette_index;
    5 s* l4 D  W5 g8 B$ b( ~
  256.     int palette_count;
    6 w) ?5 o7 X: M4 d
  257.     int palette_type;# @9 X- c3 f* n. s4 u- V' h
  258.     int palette_index;3 o7 b  [# y, W& h
  259. " ]4 ]& K* R5 C- G* E, c7 Y* i& C7 P
  260.     fseek(inrbt_file, 0, SEEK_SET);4 m3 h0 l. L! i' m% s
  261.     fseek(outrbt_file, 0, SEEK_SET);
    5 l! a% v) K  l' |8 X0 M
  262. 1 ~$ f2 g) v3 {: w& Y
  263.     /* load the header */! w' Q* ]" y- D3 y: y6 Q* p
  264.     if (fread(header, RBT_HEADER_SIZE, 1, inrbt_file) != 1)# @/ C4 K' d) \# I, P3 Z' j; E
  265.     {
    1 J7 L$ V0 R& N1 g9 y. y' e
  266.         printf("problem reading initial RBT header\n");. J# a7 U9 j1 @+ q3 i4 D
  267.         return 0;
    ' j. m1 B% Y% J* R3 i5 U0 E8 a% \( m& L
  268.     }2 ?+ f6 p0 t# X
  269. , i' _0 D0 H2 e+ C4 h/ x
  270.     /* copy header to the output */
    % L; h9 A/ @* S% i9 K) C' i8 Q. K
  271.     if (fwrite(header, RBT_HEADER_SIZE, 1, outrbt_file) != 1)& p) b0 i+ \. ?0 W6 T: G
  272.     {+ b/ Q, H8 p! X( I
  273.         printf("problem writing initial RBT header\n");
    : j; `; }0 f1 ]7 X9 ~: f
  274.         return 0;* ^2 s) o8 L/ Y; p1 K3 n# u
  275.     }1 D5 \$ f" [3 @% \* ?

  276. ' D1 O1 X! N$ G* h. r( v; w5 t+ D/ h" K
  277.     rbt->version = LE_16(&header[6]);% O  u1 y% i0 H; T0 b
  278.     rbt->audio_chunk_size = LE_16(&header[8]);$ Z! s, O& o% k# R4 G1 m2 K3 m
  279.     rbt->frame_count = LE_16(&header[14]);! H, r! {- p2 J4 t

  280. ' }' H3 O" M* L# r- s6 h
  281.     /* transfer the unknown data, if it's there */- O6 o6 v- _6 B. C" b* i7 Y" J4 x
  282.     unknown_chunk_size = LE_16(&header[18]);
    * k2 o! B( W% E5 t/ w
  283.     if (unknown_chunk_size > 0)9 O# Q) N% g) k& G% |3 Q' D# [# @
  284.     {4 ?' }1 n6 j! I& a/ b& {% L
  285.         unknown_chunk = malloc(unknown_chunk_size);
    ) X( s/ B0 @. C7 \+ Y
  286.         if (fread(unknown_chunk, unknown_chunk_size, 1, inrbt_file) != 1)0 Y8 W0 y& W; k( f
  287.         {
    ) S4 {. ]* B' c* L
  288.             printf("problem reading unknown data\n");
    4 N% ~7 \. i/ [5 H+ T% }8 F
  289.             return 0;# y. P; x  r+ }, G7 t
  290.         }
    ; B! b: M' B, O% z
  291.         if (fwrite(unknown_chunk, unknown_chunk_size, 1, outrbt_file) != 1)
    0 M8 G* k( E# [' _/ m" M
  292.         {; r" D8 B9 }7 x( |: |) I, U# r
  293.             printf("problem writing unknown data\n");
    2 E' i1 g$ d* c! E0 g
  294.             return 0;
    / P# O: ?5 k3 T6 j5 ?6 C# E& g$ s4 ^
  295.         }' O4 \6 p7 j/ c2 x' v7 U+ `
  296.         free(unknown_chunk);
    : C- N8 g. n6 m, }% S& Y$ E# x% x
  297.     }: u0 [# N  U2 p" A( d+ ^
  298. * y1 I6 s8 j' t% F) K5 t
  299.     /* transfer the palette chunk */
    8 d; @# t5 v; e1 |
  300.     palette_data_size = LE_16(&header[16]);
    2 W: W4 F5 w: m
  301.     palette_chunk = malloc(palette_data_size);
    , V4 C8 U8 s( t  }* T! C3 V7 H3 ~
  302.     if (fread(palette_chunk, palette_data_size, 1, inrbt_file) != 1)( e; ^0 d+ H, P8 [
  303.     {+ T/ T* Y4 _" b
  304.         printf("problem reading palette\n");
      m8 ^1 l; T- V, ^
  305.         return 0;
    9 f7 ~5 j& `$ M
  306.     }
    . S( P, ?$ P; W1 _2 I- M% M3 v: O3 Y2 v
  307.     if (fwrite(palette_chunk, palette_data_size, 1, outrbt_file) != 1)
    / R. g; [3 _7 P5 p- d9 G- j
  308.     {
    . a: E/ \2 d5 }* S8 U$ d$ M" x- h
  309.         printf("problem writing palette\n");
    ; k: @# i! G# l9 S  R
  310.         return 0;
    : Q0 M; j% _5 _3 c% t
  311.     }; r- V" X  i/ v  D. X0 R
  312.     /* load the palette into the internal context */3 D1 `/ F/ ^" Y4 C
  313.     memset(rbt->palette, 0, PALETTE_COUNT * 3);
    1 R- n" g  d6 F# G8 i
  314.     first_palette_index = palette_chunk[25];" D4 e* U/ T; m, t& f/ c. K7 @
  315.     palette_count = LE_16(&palette_chunk[29]);
    : h8 @" U1 q; \. l7 O
  316.     palette_type = palette_chunk[32];
    3 i9 H6 {( M# c( Q
  317.     palette_index = (palette_type == 0) ? 38 : 37;; i7 T$ G/ m( O) k
  318.     for (i = first_palette_index; i < first_palette_index + palette_count; i++)
    8 {3 O3 J# c  e  n
  319.     {
    8 {! w# |' Y9 k. f9 `. @
  320.         rbt->palette[i*3+0] = palette_chunk[palette_index++];
    * F( m6 z- E& ]
  321.         rbt->palette[i*3+1] = palette_chunk[palette_index++];0 [- m4 \9 ]6 y* n3 K7 t* ^+ l. [
  322.         rbt->palette[i*3+2] = palette_chunk[palette_index++];
    + B0 k$ u/ P  ]  P
  323.     }" h& M( Z9 f' l& M& L( K0 m9 X
  324.     free(palette_chunk);
    5 i# A3 O# q$ r

  325. : V$ N4 J7 U: ^; n
  326.     /* copy the video frame size table (2 bytes per frame), as a placeholder */7 m3 l! Q$ E8 B5 x9 b
  327.     rbt->video_frame_size_table = malloc(rbt->frame_count * sizeof(uint16_t));" {2 t3 N  I( d8 ~+ {3 R# r
  328.     if (fread(rbt->video_frame_size_table, rbt->frame_count * sizeof(uint16_t), 1, inrbt_file) != 1): S7 F5 ]' ]4 p  P) [! y
  329.     {1 E) m: P/ ?* q" o1 m; a
  330.         printf("problem reading frame table\n");
    4 L& ]+ ?+ A0 M0 N# X+ z# k
  331.         return 0;  c7 p2 X/ t% A: J) y( d# X
  332.     }
    # k3 X2 }# D5 ~. Z1 c
  333.     rbt->video_frame_size_table_offset = ftell(outrbt_file);3 @- Z$ R: z3 Y& X# V
  334.     if (fwrite(rbt->video_frame_size_table, rbt->frame_count * sizeof(uint16_t), 1, outrbt_file) != 1)
    $ E2 V) H7 x! }
  335.     {
    + f) Z8 _# h* B- f0 v  b8 ]
  336.         printf("problem writing frame table\n");
    % u7 u, W+ U4 b4 \9 c
  337.         return 0;- H7 T4 W& i1 U' n+ E
  338.     }/ T2 d( x, I& g

  339.   Q8 @  a, l" T  g5 R- {
  340.     /* copy the frame size table (2 bytes per frame), as a placeholder */% O" g! |9 d& t! k2 r5 L5 Y2 _
  341.     rbt->frame_size_table = malloc(rbt->frame_count * sizeof(uint16_t));
    1 L/ h) o! f, g0 m* \, x' ~
  342.     if (fread(rbt->frame_size_table, rbt->frame_count * sizeof(uint16_t), 1, inrbt_file) != 1)! v* u7 R1 l2 K
  343.     {; }0 R1 Q! k+ k) l. o7 G
  344.         printf("problem reading frame table\n");' p& c3 r! m. |) |# s+ x
  345.         return 0;
    6 S# {8 i4 z" S" k. X: U9 e+ i
  346.     }5 c5 [& K! u' J2 f+ y; y
  347.     rbt->frame_size_table_offset = ftell(outrbt_file);
    8 I/ a+ J" z( b/ v
  348.     if (fwrite(rbt->frame_size_table, rbt->frame_count * sizeof(uint16_t), 1, outrbt_file) != 1)2 @1 j/ O! V! C6 K( L) e( g8 [/ P
  349.     {
    % ?* C8 l5 ^8 r1 B
  350.         printf("problem writing frame table\n");
    / K; b$ u' j) h" K0 z7 ~
  351.         return 0;
    9 O# A3 C# p7 @5 s# c5 u! b" q
  352.     }' j$ [( v9 l: E- c
  353. 8 `* L/ M' g" d8 I
  354.     /* find the max frame size */
    / [* ]2 c( t5 s; H  j
  355.     max_frame_size = 0;! c9 l7 b% E# Z% ?( l: y9 {
  356.     for (i = 0; i < rbt->frame_count; i++)
    " U" r0 l( Y6 A5 i
  357.     {
    & n! J* x8 U; Z0 c/ `
  358.         frame_size = LE_16(&rbt->frame_size_table[i*2]);9 q5 |, e6 V0 J2 K; n  c# B. ~
  359.         if (frame_size > max_frame_size)4 f7 h8 n/ F& M9 \
  360.             max_frame_size = frame_size;/ H6 a3 Y, A. I# [7 L( x5 y4 b
  361.     }+ u. _  ~8 z3 A- U! n( q3 f
  362.     rbt->frame_load_buffer = malloc(max_frame_size);6 R) f/ s- |6 F6 P' w% T1 S
  363. 3 I' u4 f! H- R# X% I* v
  364.     /* transfer the unknown table(s) */
    3 o' R* L" [3 T& S  Q
  365.     if (fread(unknown_table, UNKNOWN_TABLE_SIZE, 1, inrbt_file) != 1)6 `  U  m, @3 B' l
  366.     {4 S& h* ?5 b% _% U) k! a2 ^
  367.         printf("problem reading unknown table\n");
    1 A9 |9 q8 b+ e. {- M
  368.         return 0;
    $ f% B% e/ }1 o$ q6 r: T
  369.     }
    5 v8 ?1 S4 @/ O$ Z! F
  370.     if (fwrite(unknown_table, UNKNOWN_TABLE_SIZE, 1, outrbt_file) != 1)! }6 L  C4 G" P
  371.     {
    ; S7 |) o' K6 |2 H
  372.         printf("problem writing unknown table\n");0 \4 ?7 t  N1 ^! z7 n/ B+ _1 u
  373.         return 0;
    4 c. N8 X- c6 ^* B; D6 {* ~- e
  374.     }
    - J' v2 u  `  I% Q" m% \8 _$ O
  375. - h/ z9 @4 }; O/ Y  C
  376.     /* copy over padding */# {) u1 r' U. _
  377.     padding_size = 0x800 - (ftell(inrbt_file) & 0x7FF);
    6 ?$ V8 |) p' s! m
  378.     if (padding_size)) d- |/ p; }/ y! ]+ f
  379.     {
    9 e+ }- \* P2 o& ~
  380.         padding = malloc(padding_size);/ N+ g' G3 [) F+ s* F3 X
  381.         if (fread(padding, padding_size, 1, inrbt_file) != 1)
    : u" t  d- n1 C6 y1 ?% c/ n5 O& h
  382.         {
    8 f( W. ~0 y/ W7 \9 Z; Z
  383.             printf("problem reading padding\n");* ?4 ?8 D; h! N* Z) l" B7 K4 S& Z
  384.             return 0;. @8 q4 t5 n6 V  V8 A/ R' q
  385.         }! i2 s, e% k1 b1 Y
  386.         if (fwrite(padding, padding_size, 1, outrbt_file) != 1)
    3 _! I4 ?5 X+ [* h; K2 z
  387.         {
    5 o" s. W- Z( V( j$ f$ t9 `
  388.             printf("problem writing padding\n");- ?( N: J$ B; K# }2 d/ _
  389.             return 0;- Q- d6 A! G  i# w6 Z
  390.         }
    ) h( a: v+ M5 t
  391.         free(padding);
      f0 s( l; C* z  a2 G2 U/ T
  392.     }- n7 T: o8 E; ^, h$ F

  393. 1 i8 r5 c) R3 x" d( G
  394.     return 1;( [/ g1 T& U: o" `/ R! m3 c& ]
  395. }
    8 _+ z+ |8 l& W

  396. ' Q2 m7 E) j+ o: X
  397. static int get_lzs_back_ref_length(get_bits_context *gb)5 j" W! B) `4 G5 H$ z
  398. {
    0 v/ l& O/ c2 K6 p
  399.     int vlc;
    5 ]0 X. Y- C/ @% U
  400.     int count;' b0 b+ C- a; Y8 I% N& Q
  401.     int value;
    # w. k& ^1 h$ z  T
  402.   P: _4 b* R2 ~' z, X% b. \
  403.     vlc = view_bits(gb, VLC_SIZE);
    / P$ p& r" {. z& a, g
  404.     count = lzs_vlc_table[vlc].count;
    ) }3 @# {1 Z7 Z4 ^
  405.     value = lzs_vlc_table[vlc].value;
    . w' r9 {- K& p. j4 @- F4 Q
  406. . E+ m# @- t6 q1 {  ^7 ?& i
  407.     read_bits(gb, count);
    . Z& G+ b9 d4 ?& }
  408.     if (value == 8)
    $ X" P9 o* K$ j6 F; u0 c( `
  409.     {  e8 _% |1 z; K7 E
  410.         do6 \3 n$ G; h# d6 b0 |, i2 ~5 W6 C$ p
  411.         {, m8 H- y4 n( v% Y$ u& [
  412.             vlc = read_bits(gb, VLC_SIZE);
    % k! `5 o) k$ i  k1 G5 x# k& h
  413.             value += vlc;
    " `6 v# s6 }7 i) N
  414.         }( |& j* W1 T9 o8 e" Y
  415.         while (vlc == 0xF);
    ! o+ o  W6 P; a3 T3 b! [4 K# V8 K
  416.     }
    8 b3 {2 g+ {4 q9 `2 _& u7 `5 M1 M

  417. ! Z0 s/ i' l( [4 t
  418.     return value;& z5 v) l; u: Y$ s. Y6 T6 K
  419. }
    ; m5 w: g& }3 R7 Z

  420. . t) l% J4 S3 P; H6 {0 B; z
  421. static void compress_window(put_bits_context *pb, uint8_t *full_window,
    - y+ x7 j9 q+ S' D. `. }+ L( a: b
  422.     int full_window_stride,
    1 F  i! N4 ]  d
  423.     int window_top, int window_bottom, int window_left, int window_right)' d: G# o* P2 b! U6 P" D
  424. {/ t2 c. `3 i- s- z# v
  425.     int last_pixel;# T0 k( q3 X  k
  426.     int run_size;
    * \5 K8 x! d( I5 W) K* R
  427.     int x;
    ! f& T: i* g' `
  428.     int y;9 D+ ?! Z3 x. L$ d
  429.     int start_index;
    ( Z1 X: O! L/ c( }6 r
  430.     int end_index;
    1 d8 Y: p* z: I, o" _) i
  431.     int encode_last_run;
    4 X. h5 P. D2 z% ~

  432. 5 ^3 [* b0 U9 Y' v. c
  433.     last_pixel = full_window[0];* m) Z7 n% }. y* K+ K
  434.     run_size = 1;1 N/ I% \6 d  u
  435.     for (y = window_top; y <= window_bottom; y++)
    % S& \  j$ S/ R0 O6 H6 l: ]
  436.     {
    2 [0 ~( L  N) x' N9 k2 T8 F
  437.         start_index = y * full_window_stride + window_left;
    9 S. |! S+ z* P6 r0 K+ ]+ p7 e( [( m  V1 o
  438.         if (y == window_top)
    " a* `: y. u+ R# F/ F- v
  439.             start_index += 1;
    6 }5 g0 O- q5 [; B- r
  440.         end_index = y * full_window_stride + window_right;
    / [! x) V3 ~# a5 [! E: {
  441.         if (y == window_bottom)3 g. S& W  E7 `5 T9 R# @
  442.             encode_last_run = 1;# f& v! {; g( T2 _7 p! B8 ~# Q
  443.         else) v9 U5 W! n9 o7 E3 ~9 ~
  444.             encode_last_run = 0;
    5 E5 q/ J' G9 c# V0 x
  445.         for (x = start_index; x < end_index; x++)" t1 I+ J# t! w7 T( U; C% O" z% |
  446.         {5 ~# l7 J" U& R( P- m/ N
  447.             if (!encode_last_run && full_window[x] == last_pixel)
    9 B" l* }2 P* D) ~) {
  448.                 run_size++;
    3 O2 C  P! B& w/ P, K
  449.             else/ a8 T1 F1 ^/ k! J: w/ o
  450.             {3 w5 _% C* x) N% a! B
  451.                 if (run_size == 1)
    $ Z; T( d, v# x. a
  452.                 {
    ; x( X; I0 T* j5 x
  453.                     /* encode a 0 bit followed by raw pixel byte */
    ( T, _3 j4 j! e7 S) `
  454.                     put_bits(pb, 0, 1);
    * I& ?4 ]8 N3 _3 [9 Q
  455.                     put_bits(pb, last_pixel, 8);9 A/ Y3 i' r# z3 e( i2 O
  456.                 }$ O, `8 G4 C2 k  O; j
  457.                 else if (run_size == 2)
    6 i3 C$ U' o. F  }
  458.                 {
    5 W) I* e: R5 v4 i, I
  459.                     /* encode a 0 bit followed by raw pixel byte */( l& D( X" z& _- f4 L
  460.                     put_bits(pb, 0, 1);
    ; H: A$ u/ W% D6 U. ?: J& c5 z
  461.                     put_bits(pb, last_pixel, 8);
    8 Q9 R6 C0 `: _) F+ e
  462.                     put_bits(pb, 0, 1);  s# I+ G" \& A: q7 x8 Q
  463.                     put_bits(pb, last_pixel, 8);5 M2 {5 N9 ?, q+ n% E3 t3 X3 K& i
  464.                 }
    9 p% e# O6 R! ]* v. p
  465.                 else1 R' u, F  X# R. x. M* ~
  466.                 {
    ) L: W" P7 {/ O" R: P5 w! Y3 H+ K
  467.                     /* encode a 0 bit followed by raw pixel byte */
    ' p' @; {! l9 p7 i+ U0 R6 k9 o
  468.                     put_bits(pb, 0, 1);/ n+ X3 @% k4 ^5 ~
  469.                     put_bits(pb, last_pixel, 8);& {: X" I$ M$ s3 {& h
  470.                     run_size--;8 c9 @9 I) f% ]% }! F( P
  471.                     /* encode a run: a 1 bit, followed by a back reference
    3 W& |$ ]9 w( x9 M* s( A
  472.                      * offset (-1), followed by a length */
    8 z( T5 a; w: w5 K, B( V
  473.                     put_bits(pb, 1, 1);5 Q: Q8 z: V' A/ d$ `- }1 w
  474.                     put_bits(pb, 1, 1);  /* 1 = 7-bit offset */
    * ~, P1 u5 P- f% Y' B0 ^% S
  475.                     put_bits(pb, 1, 7);# I. [5 R( x( W" E& n3 o
  476.                     if (run_size <= 4). T( }. l& f7 i4 S7 a" s
  477.                     {
    5 }% q6 d. C* n% c, P
  478.                         /* lengths 2, 3, and 4 are 2 bits */' h5 i6 M% B+ \7 K4 U
  479.                         put_bits(pb, run_size - 2, 2);
    8 E' r) M/ A2 c  j
  480.                     }
    1 C0 b8 Y* \3 \) q; I1 a
  481.                     else if (run_size <= 7)+ p( j- t# x8 @! T; }7 r
  482.                     {
    . @3 U+ k0 ^1 _+ a  l. s6 p. @
  483.                         /* lengths 5, 6, and 7 are 4 bits */" w$ g2 b% w5 P1 A
  484.                         put_bits(pb, run_size + 7, 4);: @# C0 {' u' m6 x. P; I4 v5 e4 \
  485.                     }4 [! w4 {" m0 ~% P- e7 b3 J2 r
  486.                     else) C! [- V  B) P& [# Q
  487.                     {; @, _0 F- }1 C! x3 W" Q) y8 e
  488.                         /* arbitrary length; start by encoding 0xF which6 g! Q0 S/ b7 t
  489.                          * stands in for an initial version of 8 */
    ! O2 C$ M  Q0 w
  490.                         put_bits(pb, 0xF, 4);7 t3 r8 W4 _! a  ?
  491.                         run_size -= 8;
    " R4 p% h' ]' E2 w$ M' L
  492. 4 T  U! U% G. f$ o/ P3 @, s! j: R
  493.                         /* encode blocks of 4 bits until run_size is 0 */  o% n) o1 l  s- j& N; A
  494.                         while (run_size >= 0)  i/ B% [! S" [% K" t
  495.                         {' m! {  z- @2 C
  496.                             if (run_size >= 15)/ }/ k- ~1 t) [2 ^2 B0 _
  497.                             {' d# V5 c2 f9 M" }% J
  498.                                 put_bits(pb, 0xF, 4);. H; W9 R, ?' U# y+ `* p0 `
  499.                                 run_size -= 0xF;) V& f# d* {" j- z% k
  500.                             }$ a, u: G! ~$ h6 z
  501.                             else( y* a! Q# W0 Z& c+ B- C7 K' g
  502.                             {3 H' B& F7 R# M* e% ~( g3 K, h# T" h: A
  503.                                 put_bits(pb, run_size, 4);6 N+ [$ G% ?5 |. z  t4 V
  504.                                 run_size = -1;
    & Z! S7 f# T: C& P
  505.                             }
    ; z' R5 d3 G9 P
  506.                         }
    9 P) @5 `0 b7 V0 Y; d; ~0 A
  507.                     }
    " K0 O1 J2 ^1 d0 p3 p( P* V/ {" |
  508.                 }
    & q6 E/ P+ @; v* U7 k
  509. . M8 A' z; C* F& [8 p" U8 G
  510.                 last_pixel = full_window[x];
    + [$ i0 H0 E" e( o! g
  511.                 run_size = 1;
    & W8 e6 E8 l& u# J5 I
  512. # p! D  {0 n$ I3 f, H* h
  513.                 /* this single x iteration was only here to close the final run */" B9 b+ s1 d; x$ K  ~
  514.                 if (y == window_bottom)
    9 b4 q' P$ [" i
  515.                     break;3 v3 g% X+ e0 c( T
  516.             }6 C. G, ~2 ~' b5 K4 Y
  517.         }( X2 H% s3 {. y0 \: a9 x* b
  518.     }
    $ S1 q9 p/ ^+ _8 ]. B- _5 m# J$ q
  519. 8 j+ R% s! m  F) R* h3 m8 p( F9 K
  520.     /* close the bitstream by encoding a back reference with length 0 */$ ]4 J: V( o# q* c' }
  521.     put_bits(pb, 1, 1);  /* back reference run *// n9 Q6 @/ d  u! C
  522.     put_bits(pb, 1, 1);  /* 1 = 7-bit offset */7 i# G, `/ p  a3 j% R3 }. T6 k
  523.     put_bits(pb, 0, 7);  /* length 0 */* d4 C; C- q/ [$ t5 w* E

  524. 0 ]3 _3 ~' K$ q0 @8 T; J% h$ U
  525.     put_bits_flush(pb);
    , K$ M8 ]9 w+ c! L; f& n
  526. }
    8 M9 y8 Q2 Y" o( m1 f

  527. + T9 L' r3 [4 d
  528. /* compute Euclidean distance between an RGB color and the desired target */
    7 K9 t! d! T9 y1 C) h
  529. static int compute_rgb_distance(int r1, int r2, int g1, int g2, int b1, int b2)) Z+ U( Z* H8 \0 b; e
  530. {
    $ _' f9 R: W7 Y
  531.     return sqrt((r1 - r2) * (r1 - r2) +
    + ?$ V# H7 R8 i- b; t( [* V) |9 a
  532.                 (g1 - g2) * (g1 - g2) +
    ) W5 H8 C- \# S, C; A
  533.                 (b1 - b2) * (b1 - b2));
    0 e9 Z! v" Y) n* Y
  534. }
    , ~# X( [8 s8 Y  O" F4 y. o

  535. / m* g" A/ M% ^& I, m' [( m, {1 r
  536. static uint8_t find_nearest_color(rbt_dec_context *rbt, int r, int g, int b)
    7 _7 Z! b& Z% s' G) C/ i$ W! B% E
  537. {
    8 D. k; C- E( w& Y# B" H
  538.     int i;
    9 z% Y' s2 p. `$ f
  539.     int nearest_distance;
    4 e* x% q  [; a9 C3 D& _
  540.     int distance;
    + V6 @% b; ?; e) `0 r4 u9 m) f, \
  541.     int rp;8 C0 t& t  _" O! ], ]  E$ V
  542.     int gp;  M' `  T+ U" a7 l% r  T3 O* U3 J
  543.     int bp;1 m4 f% i% X8 I
  544.     uint8_t palette_index;0 l/ S0 _& d- _& m) @4 c1 r% u
  545. ' w" h1 s- K8 F, Q1 ~3 l
  546.     nearest_distance = 999999999;
    8 i; b7 b$ B; I  H
  547.     palette_index = 0;
    7 Q: O/ o- r# u9 G9 M
  548.     for (i = 0; i < 256; i++)
    4 P, j. q/ P; b3 i' g1 N
  549.     {6 |6 c1 |2 C6 d) o! T
  550.         rp = rbt->palette[i * 3 + 0];
    - s! `$ ^  F# h( P* Y2 h$ C
  551.         gp = rbt->palette[i * 3 + 1];% X0 q. w9 Q& [" N! Q
  552.         bp = rbt->palette[i * 3 + 2];
    7 v$ u" K( R& _! L) l, f0 j
  553.         distance = compute_rgb_distance(r, rp, g, gp, b, bp);
    9 `; z& J6 k0 J0 D  ^. u
  554.         if (distance < nearest_distance)
    ( o6 g9 ^* _) G* u( t: g
  555.         {1 ?; I7 ]( E4 _* f9 u) O
  556.             nearest_distance = distance;" w; `# h! ?6 [' |
  557.             palette_index = i;( [& g2 y9 B/ ]" E6 m. ^4 i
  558.         }% I  y6 M: L' }3 }8 L" }: R5 ~
  559.         /* can't get closer than 0; break early */' T& a3 d" ?$ d( A$ I
  560.         if (distance == 0)
    ; L% ]4 g9 n" x
  561.             break;
    # }9 C) J9 v+ n' |0 j
  562.     }! A3 I8 f& m. z  u8 N1 z; t3 |

  563. & V% F" F" q' l
  564.     return palette_index;
    8 U) M: N( E2 l  @" Z- E
  565. }- Q$ j# c, v) V* W* `3 u
  566. ! \4 {( ~% c8 P) C6 W
  567. static void subtitle_frame(rbt_dec_context *rbt, uint8_t *frame,
    + }2 x* k/ {! H. ?6 ]: G  ]& _
  568.     int width, int height, int timestamp)0 c3 K2 s$ `& A4 v/ g
  569. {% C! Z2 ^1 w0 J8 h9 C# {
  570.     ASS_Image *subtitles;
    3 S% \/ }7 }3 P3 U8 ]
  571.     int detect_change;
    % Q6 }& D) ^( c# s: ~0 v7 Y! f
  572.     uint8_t subtitle_pixel;; R- K/ I+ L) H$ G
  573.     int x, y;
      n! o# E3 \5 h: I/ Y* M+ s% Y" V
  574.     uint8_t *frame_ptr;) p4 U5 O: O( d! o3 I
  575.     uint8_t *subtitle_ptr;
    1 J. `! b4 Y; X, S% S9 n# G/ m  f

  576. $ p4 V5 t6 k* F% ?6 k% q* [
  577.     /* ask library for the subtitle for this timestamp */
    * d% V( {( _( @7 v! y6 U: g, l' r
  578.     subtitles = ass_render_frame(rbt->ass_renderer, rbt->ass_track,
    , t  x% V4 ^: \. q" x' l
  579.         timestamp, &detect_change);4 |$ v- P9 M- K" {/ l( G

  580. 5 L: Z- B2 Z3 I
  581.     /* render the list of subtitles onto the decoded frame */9 F2 q  u' l2 K
  582.     while (subtitles)
    ! e$ o: S& `" c8 ~' [. x  e0 J
  583.     {9 p* Z  W; ^9 }/ @( |1 k6 ^7 b
  584.         /* palette components are only 6 bits, so shift an extra 2
    / }) J# I5 z2 p: |) t+ s9 E* r5 `
  585.          * bits off each component */3 t7 R7 t) I4 D( r- M0 q. L4 u5 V! T: c9 V
  586.         subtitle_pixel = find_nearest_color(rbt,+ C7 g4 `+ ]9 F" Y
  587.             (subtitles->color >> 10) & 0xFF,+ ~( }! J0 Y7 m  Y3 t, ], P/ U% V
  588.             (subtitles->color >> 18) & 0xFF,
    4 S" a0 D' [: z" Z7 |
  589.             (subtitles->color >> 26) & 0xFF);2 x8 K0 ~% a1 W. e- Z
  590.         for (y = 0; y < subtitles->h; y++)
    ; ]+ N6 W: H( S$ {( e
  591.         {
    4 b9 s; _& B; z: X0 @
  592.             subtitle_ptr = &subtitles->bitmap[y * subtitles->stride];
    & Q  A& H. \  T( n0 y
  593.             frame_ptr = &frame[(subtitles->dst_y + y) * width + subtitles->dst_x];9 a6 R) b3 E  Q) |0 T* F: A- [
  594.             for (x = 0; x < subtitles->w; x++, frame_ptr++, subtitle_ptr++)
    # f: I, C5 R) k1 M7 @' f' b
  595.             {. m! e3 w+ |: D' A5 d$ O& |
  596.                 if (*subtitle_ptr >= SUBTITLE_THRESHOLD)
    ! E* |1 t. Y. u/ N
  597.                     *frame_ptr = subtitle_pixel;
    7 ]6 C0 ~2 \7 g4 W2 [
  598.             }
    $ o4 m3 V4 W5 n  v: C
  599.         }
    0 u- ~9 A2 Z8 u! e' K+ Y% x3 d/ ]
  600.         subtitles = subtitles->next;: F( n$ `9 m" E4 g
  601.     }
    1 w+ E3 K3 Y; j/ ?
  602. }- Z+ h+ a) c5 F: i2 B# I6 c

  603. 0 a% X( t; s" u9 X7 ?$ j6 L0 x
  604. static int copy_frames(rbt_dec_context *rbt, FILE *inrbt_file, FILE *outrbt_file,
    . D: n4 q" V- F/ Y
  605.     int origin_x, int origin_y, int window_width, int window_height)
    3 c: _( f; T6 E# j: O# I) V6 l
  606. {
    7 X' L, l0 ^5 |7 g+ b
  607.     int i;
    + W" }  ?% [3 m. C7 p6 K# F
  608.     int j;; D: `' P* Q2 L% W  m- L
  609.     int scale;7 k- l5 d* j3 B, @0 d3 N% ]4 A
  610.     int width;
    + L$ o' U3 Q7 ^8 J. T
  611.     int height;
    / X& D0 q& j3 w8 G8 D" h
  612.     int max_width;6 G! D9 w! V8 K  \
  613.     int max_height;, x5 v  i5 S/ `* q) E
  614.     int frame_x;
    6 }. K+ h* _# o- |$ t9 h8 j% x
  615.     int frame_y;
      {+ r; U8 P3 Y. c. I
  616.     int fragment_count;, N2 j! P" c, w- a4 w+ }# H$ E
  617.     int decoded_size;) K/ z7 P( a  ]) T! L* Q
  618.     uint8_t *decoded_frame;* k. B) A9 X8 E& h% F( o
  619.     int fragment;% v& e6 {) Q9 ~' v1 n
  620.     int fragment_compressed_size;' x: _1 m4 i% t* [0 A# O* [
  621.     int fragment_decompressed_size;. f) b  j* }$ ]
  622.     int compression_type;$ }" ?8 q! {$ b& O' ]+ _0 b
  623.     int index;
    ( _# `" V7 B7 Y9 u/ m6 c+ E
  624.     int out_index;4 w( ?2 r) B- I- y
  625.     get_bits_context gb;
    ' D% |3 a  O. b7 d
  626.     int frame_size;/ C/ S6 Z5 ^6 O6 s* l3 z# e6 k
  627.     int video_frame_size;
    # ~6 H7 D) ], H" x
  628.     int audio_frame_size;
    0 ?, A+ p/ ~) X7 V$ x! I
  629. - k' }" b; I3 F/ o" c2 h
  630.     int back_ref_offset_type;7 d& _  R# z; {7 }; n
  631.     int back_ref_offset;
    . E! c. @0 v" M2 s5 J' T
  632.     int back_ref_length;
    - Y; m: r; a0 g' c% n9 v3 L& L
  633.     int back_ref_start;& w. M3 R  P* x6 ~% K2 B
  634.     int back_ref_end;
    ( L/ s; j8 j2 ?$ U7 K+ f+ s

  635. * l" I; n8 `( P: x; `+ K
  636.     uint8_t *full_window;
    - e! O4 J  d+ l" y
  637.     int full_window_size;
    : [) r4 r1 ]( w% O
  638.     int y;. S7 d% ]8 ^) m& b+ U$ w5 X' }
  639.     int window_top;
    % e- Z* g0 d, ^* [
  640.     int window_bottom;) u; w2 R9 i7 J  ]. o- f
  641.     int window_left;6 u4 j8 \) k( X+ D/ {/ i& L5 B( y
  642.     int window_right;
    ( S0 Q/ ~+ H  e: `
  643.     int window_size;5 k; n8 S% w7 ?' d

  644. 8 J, z9 E8 X( a+ V: B
  645.     char filename[30];: x) L7 d* D& h+ o. J7 e

  646. 5 _0 {1 `$ q0 w+ i6 D7 P
  647.     put_bits_context *pb;0 T8 z. U. g% e7 s; K3 D

  648. " M4 j5 A) G+ U& X
  649.     full_window_size = window_width * window_height;1 L6 h  o8 y- x" ~& p$ D
  650.     full_window = malloc(full_window_size);
    3 ], m( t8 D7 |$ m
  651.     pb = init_put_bits();# [6 L0 ~9 `. M5 t3 }* K4 o5 [

  652. & G$ F. v7 F5 S: p  R7 q* r
  653.     max_width = 0;
    1 C* z7 e6 g% J4 ]! x! B0 ?
  654.     max_height = 0;
    - U; Y5 C( T+ w7 b
  655. 3 i  y" }. o) d. b* X  S+ U1 Q
  656.     for (i = 0; i < rbt->frame_count; i++)
    7 n# n" k6 Y! P
  657.     {
    , u$ ~' E4 |$ w5 q
  658.         /* read the entire frame (includes audio and video) */' P3 e* ?* q# R8 p0 x4 d
  659.         frame_size = LE_16(&rbt->frame_size_table[i*2]);
    & R1 f0 @+ G9 W
  660.         video_frame_size = LE_16(&rbt->video_frame_size_table[i*2]);
    / [; q- ~5 o8 c  `
  661.         audio_frame_size = frame_size - video_frame_size;
    7 d; D5 q" O$ \& g( Y
  662.         if (fread(rbt->frame_load_buffer, frame_size, 1, inrbt_file) != 1)( P2 s5 P" {1 Z, q
  663.         {
    + U' _) I- ]0 k! L' K& P* `7 C& Z
  664.             printf("problem reading frame %d\n", i);4 X) z" L! }! H: Y
  665.             return 0;
    % g  E3 J  T+ }2 `
  666.         }
    9 r9 L8 t; X2 i6 v% D- d" P

  667. 7 h7 }/ _% I3 V
  668.         scale = rbt->frame_load_buffer[3];
    $ N! x) {( H, c, G" f1 ^
  669.         width = LE_16(&rbt->frame_load_buffer[4]);
    ; r# C/ u0 ]4 `" s- y9 P8 A0 f1 `
  670.         if (max_width < width)" Y) k+ [$ _  R) ^  D! u. R- R+ a/ l! ^
  671.             max_width = width;
    , R1 P/ i; ?  L3 M
  672.         if (max_height < height)
    ! C) L7 E# z6 q
  673.             max_height = height;& [' ~7 j6 C& x/ y. j* s
  674.         height = LE_16(&rbt->frame_load_buffer[6]);
    / N# v  \* f( v
  675.         frame_x = LE_16(&rbt->frame_load_buffer[12]);
    3 G. [/ {7 c# f, B
  676.         frame_y = LE_16(&rbt->frame_load_buffer[14]);) g+ B% {; D; V2 ]/ H
  677.         fragment_count = LE_16(&rbt->frame_load_buffer[18]);/ R" v. G2 }2 Y" ?) e
  678.         decoded_size = width * height;
    ) b' J" C( t9 e" }

  679. / I+ ^, g5 H* Z
  680.         printf("processing frame %d: %d%%, %dx%d, origin @ (%d, %d), %d fragments\n", i, scale, width, height, frame_x, frame_y, fragment_count);( Y4 z! g* [- E6 j
  681. . h9 H" H7 ]. ]. O* k1 a
  682.         /* decode the frame */) t9 }5 J8 i) g/ X3 d
  683.         decoded_frame = malloc(decoded_size);
      z( U) q3 s+ \) ^
  684.         index = 24;  ]& ]( D( J. L) r/ p# Q' B
  685.         out_index = 0;( ?5 Z* ^' x, E: Y/ E( n
  686.         for (fragment = 0; fragment < fragment_count; fragment++)
    & p) c! a/ q( ?. [& m+ J
  687.         {, A" B8 e8 q  o
  688.             fragment_compressed_size = LE_32(&rbt->frame_load_buffer[index]);- b4 T  h) Z" i% @
  689.             index += 4;% T8 g- |% k+ |+ J# I6 d$ f
  690.             fragment_decompressed_size = LE_32(&rbt->frame_load_buffer[index]);+ Z1 y' b& }. x6 t( d9 N
  691.             index += 4;
    1 j" Z" }5 }: l, r+ m  v. I5 d# D
  692.             compression_type = LE_16(&rbt->frame_load_buffer[index]);
    & _6 a2 x) E2 o/ N2 }; z, Z) j
  693.             index += 2;
    $ j4 ^' k7 ^4 B- F* o

  694. 7 c% m$ m, f& O- @, O; n
  695.             if (compression_type == 0)
    . i$ t' R  L4 p5 Z8 m( R: p
  696.             {( V; G7 K- A; w$ `& s
  697.                 init_get_bits(&gb, &rbt->frame_load_buffer[index],
    3 y/ l3 e9 T  L) T0 Y, i
  698.                     fragment_compressed_size);5 w; t/ P  X& L( s, m$ a0 n% y

  699. . R5 m4 a5 L; O1 d1 l
  700.                 while (out_index < fragment_decompressed_size)
    4 m% H/ d5 J" c8 |/ J) ~9 O+ L0 j
  701.                 {) j5 t. H9 b2 }" F
  702.                     if (read_bits(&gb, 1))
    ( z1 R5 [3 n% e) _0 w
  703.                     {
    4 ]7 l0 A) U! T% m
  704.                         /* decode back reference offset type */8 e+ U8 l+ J$ J/ y3 c' ]6 f
  705.                         back_ref_offset_type = read_bits(&gb, 1);; @8 r+ _( x: t# p. Y0 Z

  706. 6 m& q9 x9 a- U% a4 m; o) n
  707.                         /* back reference offset is 7 or 11 bits */
    4 |' _! u$ @/ V, v4 B& \# T. L2 ^% d
  708.                         back_ref_offset = read_bits(&gb,0 Q$ t, f5 I' ]( h; D
  709.                             (back_ref_offset_type) ? 7 : 11);
    ; I% k' w" X9 w( K+ ], Z) P
  710. 9 r7 T( W8 h0 A5 w5 `+ y9 N
  711.                         /* get the length of the back reference */3 n$ w8 l) ?: H( z2 D6 \' y% r% Z
  712.                         back_ref_length = get_lzs_back_ref_length(&gb);  _' S, C+ C3 \8 L9 }% Z2 h
  713.                         back_ref_start = out_index - back_ref_offset;
    / r- f1 N! }' j8 i
  714.                         back_ref_end = back_ref_start + back_ref_length;
    ) g9 k. `* u/ T" L/ `9 G8 m: z6 o

  715. ! X( k9 Q& G% v& L7 K" ^5 M
  716.                         /* copy the back reference, byte by byte */
    " b9 H# _) Y4 t2 a
  717.                         for (j = back_ref_start; j < back_ref_end; j++)) X) M5 {( ?) b* W
  718.                             decoded_frame[out_index++] = decoded_frame[j];* }* m# ]9 l0 Y, y- k+ {8 k3 v& I/ i
  719.                     }, ~% w3 ^* J8 p/ I1 x7 v  E* F
  720.                     else
    . n' @! a$ j6 J0 Q- t: D
  721.                     {
    & M, N7 B) k, {, I! g7 a. N
  722.                         /* read raw pixel byte */: J( C  W7 i6 e3 ^/ G
  723.                         decoded_frame[out_index++] = read_bits(&gb, 8) & 0xFF;
      M# u+ u! p# `, q/ V  D+ X
  724.                     }
    ! U* v6 }' _) P; ]! ~! T, `
  725.                 }
    $ S9 {0 [5 C; w
  726. , i/ b2 C) \8 o- K- ?
  727.                 delete_get_bits(&gb);
    1 M, Z- g8 F& Y) r6 g: N/ E
  728.             }
    4 F" q! }) X+ D; b
  729. * \  O: D- m* |
  730.             /* next fragment */
    0 I6 {! E! S8 f. G  g
  731.             index += fragment_compressed_size;
    3 a$ J) M' ^6 s- H0 t$ T& T% A
  732.         }# @2 d0 [5 D7 w) _$ d

  733. $ a% U% ?# }4 y/ g: }3 r( ]# D
  734.         if (rbt->dump_frames)
    # v+ [' |& _8 \: O) ?
  735.         {) k! P0 \" e/ S7 Z9 c! F: g% o
  736.             /* dump the original frame */! Y+ W7 l) u4 V( S* M# c; F" y
  737.             sprintf(filename, "original-frame-%03d.pnm", i);
    . @* K- K( q/ v$ u
  738.             dump_pnm_file(filename, rbt, decoded_frame, width, height);1 E/ U3 \2 Y& J. Q8 K1 d. [# k
  739.         }; V4 T4 b. n( c% C% o* r

  740. 0 S6 r6 ?2 g, {# D8 }# `5 Y
  741.         /* transfer the image onto the frame window */' _* |" ^  r6 w2 \& ^
  742.         memset(full_window, 0xFF, full_window_size);- W9 W% G4 ?* y# [
  743.         index = 0;& F# J! v+ v4 h- `+ J$ {
  744.         for (y = 0; y < height; y++)
    6 ?, [0 F) z4 c( c# q
  745.         {9 j8 S% ~' v  e; V: Y6 {" m
  746.             out_index = window_width * (frame_y + y) + frame_x;1 o! S  k2 |, R' c( |
  747.             memcpy(&full_window[out_index], &decoded_frame[index], width);
      D* y$ F) u: k2 x# x. s
  748.             index += width;
    : T; s9 m- E9 B  p/ F
  749.         }
    : g6 P" e1 E5 B8 K3 v$ E
  750. 0 v6 K1 E5 g# ^7 p; t
  751.         /* write the subtitle */
    % ~  T( |( I9 Z  L& N  w" }
  752.         subtitle_frame(rbt, full_window, window_width, window_height,
    2 s2 |/ F" {9 u( l5 ^
  753.             i * MILLISECONDS_PER_FRAME);8 C# ?9 ]  h1 Q& f

  754. + ^4 l8 |" d6 f, B1 [( g
  755.         /* figure out the smallest change window */& L- v+ C* u2 ]5 |4 i. M, I
  756.         window_top = frame_y;/ k) Z0 ~' g+ \' k& I
  757.         window_bottom = window_height;
    ( {4 Z: n9 T+ @0 `
  758.         window_left = 0;
    $ I6 w1 R3 R( W  u- E, s& ]' s
  759.         window_right = window_width;# `/ R) h2 c* ]
  760.         window_size = (window_right - window_left) * (window_bottom - window_top);& }) V# M2 T, D( ~

  761. 9 t! B+ `9 i, q# ]( R  r* H
  762.         /* compress the frame *// x. d$ C1 x4 P; S( }% \
  763.         reset_put_bits(pb);; j7 x5 F( E6 o
  764.         compress_window(pb, full_window, window_width, window_top,
    % B! @/ T" R* I- S+ f1 h
  765.             window_bottom, window_left, window_right);
    3 {5 `+ k/ q1 z

  766. 7 L0 y! C% S. q" e0 P; \
  767.         if (rbt->dump_frames)
    & D, P2 M* m1 P* v/ l2 g+ q9 c. W
  768.         {
    ! }1 o7 B2 V: X$ Y" P$ w) ?" M
  769.             /* dump the frame plotted onto the full window prior to encoding,
    : A" y" g/ H6 ^$ M
  770.              * with subtitle */
    3 _4 l' I' K& y" O% |
  771.             sprintf(filename, "pre-encoding-frame-%03d.pnm", i);
    ' j; m* Y1 u) ?
  772.             dump_pnm_file(filename, rbt, full_window, window_width, window_height);
    3 i5 e+ z' c! M4 E) e
  773.         }
    ( H2 g2 r+ \3 n* C

  774. " G' m4 W4 x3 r
  775.         free(decoded_frame);
    ( {8 U& F2 m% V% P4 V3 x
  776. ) J# G& k8 L4 U
  777.         /* update the frame header */  e! e  U$ \( ?6 y, c4 s& @
  778.         /* width */- [- V8 G1 L5 |, F/ I7 F8 G$ A# M
  779.         rbt->frame_load_buffer[4] = (window_right - window_left) & 0xFF;
    0 [1 v( k' K/ _
  780.         rbt->frame_load_buffer[5] = (window_right - window_left) >> 8;8 Q( B4 F2 n, @1 o3 {. _
  781.         /* height */2 }  A; G7 h9 `$ k. b8 i6 a% }
  782.         rbt->frame_load_buffer[6] = (window_bottom - window_top) & 0xFF;2 Y2 h5 u: t0 n4 D/ }6 r- B
  783.         rbt->frame_load_buffer[7] = (window_bottom - window_top) >> 8;
    + P' Y0 K( p% v: O" f2 M- _
  784.         /* origin X */
    % m% P- J% M3 ^$ U" V- d  L6 {% D
  785.         rbt->frame_load_buffer[12] = window_left & 0xFF;
    ) b2 w: G' L6 C, }- \6 m
  786.         rbt->frame_load_buffer[13] = window_left >> 8;& o  Y% e1 h. M( Y# `" I6 q
  787.         /* origin Y */5 Y, l& m/ i& v" V1 U" W0 {5 m
  788.         rbt->frame_load_buffer[14] = window_top & 0xFF;
    4 {& Y& t6 U+ a
  789.         rbt->frame_load_buffer[15] = window_top >> 8;% O9 @+ f/ M9 l) }' W+ F
  790.         /* fragment payload size */
    # k% z/ D2 k7 n! [
  791.         rbt->frame_load_buffer[16] = (pb->byte_index + 10) & 0xFF;
    3 u$ ^9 x6 ?, R5 y
  792.         rbt->frame_load_buffer[17] = (pb->byte_index + 10) >> 8;5 u% G7 k; i/ \3 t* r0 ^3 @* @
  793.         /* fragment count (1) */
    . E; @# W9 k* E1 }
  794.         rbt->frame_load_buffer[18] = 1;
    / u" M" z' ], j1 i2 ~& m
  795.         rbt->frame_load_buffer[19] = 0;
    % L/ _2 M5 F) M

  796. : ?& G/ P" R! W3 r- U$ s" K& _
  797.         /* update the fragment header */
    6 _  P. n- @# Q- B
  798.         /* compressed size */9 D8 c) B4 a0 Z/ t- O. j8 j6 e
  799.         rbt->frame_load_buffer[24 + 0] = (pb->byte_index >>  0) & 0xFF;1 ?0 @- j# e- E* N# s
  800.         rbt->frame_load_buffer[24 + 1] = (pb->byte_index >>  8) & 0xFF;
    ! N! z/ G% C9 f2 b! H3 a3 h! d: t6 P
  801.         rbt->frame_load_buffer[24 + 2] = (pb->byte_index >> 16) & 0xFF;( [4 w( _) v, c% c) H( m+ M6 t
  802.         rbt->frame_load_buffer[24 + 3] = (pb->byte_index >> 24) & 0xFF;, t3 a) f! t6 g* k. E: A1 w
  803.         /* decompressed size */
    $ V9 U5 T' b# F& j3 d5 C
  804.         rbt->frame_load_buffer[24 + 4] = (window_size >>  0) & 0xFF;/ G. g+ C) Y$ f$ o$ W: N8 F
  805.         rbt->frame_load_buffer[24 + 5] = (window_size >>  8) & 0xFF;
    " h+ l0 D* m% O9 H5 V: K2 m9 f9 O
  806.         rbt->frame_load_buffer[24 + 6] = (window_size >> 16) & 0xFF;- V+ S! ~* s7 ~) z/ _
  807.         rbt->frame_load_buffer[24 + 7] = (window_size >> 24) & 0xFF;: i" G1 N6 U. i( ^$ Z1 N
  808.         /* compression format 0 */" ], q$ z% u" N% S; J  A( G& L
  809.         rbt->frame_load_buffer[24 + 8] = 0;
    5 ?! G  |" E+ {- S8 e0 i
  810.         rbt->frame_load_buffer[24 + 9] = 0;8 B3 R: a7 P7 s) {4 n3 H' n
  811. 3 f+ z& w1 Q" k! g- f' ~! i" Y
  812.         /* write the 24-byte frame header and the 10-byte fragment header */, \2 c5 @* `) w/ Y
  813.         if (fwrite(rbt->frame_load_buffer, 24 + 10, 1, outrbt_file) != 1)+ I3 A6 b1 b" j' C2 d
  814.         {$ B0 E+ U5 }% ^# `; K2 u. g$ @) g
  815.             printf("problem writing frame %d\n", i);
    & b1 M/ W1 b# r2 m
  816.             return 0;( |4 S- D5 L+ _* F+ ]* J$ c
  817.         }
    / Q6 w4 j- u) H0 R

  818. ) L. q1 B* [+ k: d* v
  819.         /* write the new compressed frame data */
    ( X6 _+ U& F2 ~3 U- e
  820.         if (fwrite(pb->bytes, pb->byte_index, 1, outrbt_file) != 1)7 d3 g3 j9 C7 z+ p/ J$ m0 ~
  821.         {1 ?" z& y7 m* O" ~, ~0 _
  822.             printf("problem writing frame %d\n", i);( Y) F7 ?/ t: f. L/ U" H
  823.             return 0;, I1 f; m' `6 f3 H$ y+ @8 A: a( \
  824.         }/ |3 \  K; h9 V2 g5 o

  825. ' M! J3 u/ E' v+ a! O1 N
  826.         /* write the audio data */
    ( u; V0 a# v8 s6 U8 K
  827.         if (fwrite(&rbt->frame_load_buffer[video_frame_size], frame_size - video_frame_size, 1, outrbt_file) != 1)  i  A& j1 G3 Y3 ?2 \7 O4 f. h
  828.         {
    . J' t' z" n: t; b
  829.             printf("problem writing frame %d\n", i);
    . j% E; F9 e# a8 `: h3 F. t
  830.             return 0;2 S4 d% |: J+ D" p3 t4 ^6 N+ u) w
  831.         }+ w9 M# v: F! T3 j
  832. + t4 n2 l6 {8 e1 ?, `7 ~* J: x
  833.         /* update the table entries */
    % l5 v) A' f2 @) r
  834.         video_frame_size = pb->byte_index + 24 + 10;
    ' N& \+ E- @3 E/ q% g- A/ A& P
  835.         frame_size = video_frame_size + audio_frame_size;, O" g4 ~" z0 T' |* }
  836.         rbt->frame_size_table[i*2+0] = frame_size & 0xFF;
    & q& z8 `# p( Z3 y. y" r8 x! V
  837.         rbt->frame_size_table[i*2+1] = frame_size >> 8;
    # o+ n0 E. X* v9 e1 ]! Q* R6 y
  838.         rbt->video_frame_size_table[i*2+0] = video_frame_size & 0xFF;, I# U' i0 o8 o2 `/ d
  839.         rbt->video_frame_size_table[i*2+1] = video_frame_size >> 8;8 A5 f3 Y/ p' B/ k
  840.     }1 p$ x  ?, N) L  o& W

  841. ) E9 [3 j7 Z# v
  842.     printf("maximum dimensions seen are %dx%d\n", max_width, max_height);
    ' v- `+ J- T) I7 x

  843. ' N; a+ m$ s5 \0 o$ m6 T9 l0 U
  844.     delete_put_bits(pb);
    . d# P& y+ N) s$ e/ x, j
  845.     free(full_window);
    + {9 Y9 I, Y" \0 X

  846. : t0 P8 }  g( G2 v+ D  D2 ~+ m
  847.     return 1;
    * T$ h% r! r9 a8 m
  848. }/ `, s% Y# x7 V  ~7 U
  849. - J, C5 T- m' G
  850. int main(int argc, char *argv[])6 m% a, D- H2 i, I& E* d1 Y- c
  851. {
    5 A, l& G1 K( f! f* b" t* G5 a
  852.     char *subtitle_filename;( ^# B- p  L' w9 V8 a
  853.     FILE *subtitle_file;- U7 G3 s# ?+ F
  854.     char *inrbt_filename;6 F- c$ v8 r5 e' {
  855.     FILE *inrbt_file;
    0 V7 }- ]3 Z- H& h* `& E
  856.     char *outrbt_filename;
    6 |7 H4 [% E% Z% e8 {) F3 L
  857.     FILE *outrbt_file;3 q- m4 |0 a% N3 D' e6 c3 Y5 k
  858.     rbt_dec_context rbt;
    9 W/ }4 ~' X: T: |
  859.     int origin_x;# W% n+ i( p4 G$ J
  860.     int origin_y;) x2 l. `& `$ U1 z6 F4 ]% O
  861.     int window_width;
    % }( K8 G5 G/ k- G/ _' O
  862.     int window_height;$ |5 h* L9 s& l7 z
  863. 4 G% B3 {! \& c' D1 {6 X: @6 Y
  864.     /* testing the bit functions */
    9 E% h' e5 A8 @2 |4 u. _6 Q
  865. #if 0
    ) @6 i/ {) E( j4 V
  866.     int i;, R9 @0 X+ @4 _9 F% E3 v5 |- Y! n( i' }
  867.     uint8_t bytestream[] = { 0x55, 0xAA, 0x00, 0xAA, 0x55, 0x77, 0xFF, 0x1B, 0x70, 0x8F };" u. i8 A- O2 s) b
  868.     int bytestream_size = 10;
    % N( f4 r- [9 z, o
  869.     get_bits_context gb;
    ! O, P0 @+ K4 f) h/ [  S
  870.     put_bits_context *pb;# ]  f. V' N4 }) s0 h1 ?( z
  871.     int bits;  L8 s7 M5 t8 k2 L+ J# O9 k
  872. * `2 I! H$ w$ n& y. T. W+ y
  873.     init_get_bits(&gb, bytestream, bytestream_size);# _# E% F" B' B* C4 Z) [
  874.     pb = init_put_bits();
    / c* j+ W& F) S# b# @2 S* n' Q
  875. 8 \- Z- P4 z5 W
  876.     for (i = 1; i <= 12; i++)& R7 q8 {% }0 J5 L- d; S
  877.     {
    6 a4 d5 t: {  d4 N1 G, l
  878.         bits = view_bits(&gb, i);1 R8 F% t; m/ P/ T7 a0 u9 G  }
  879.         printf("view %d bits: %d\n", i, bits);$ m% \- \* D5 B% o" F- `
  880.         printf("read %d bits: %d\n", i, read_bits(&gb, i));
    ) P: n  ?" P3 k
  881.         put_bits(pb, bits, i);& }: J9 J3 R) ~( Z
  882.     }( w: z* Y2 ~. O  z* R) U" p
  883.     put_bits_flush(pb);
    - j( q0 a* y7 u" k  q8 u

  884. % c% Q3 C* P' g6 I
  885.     printf("original bytestream:\n");
    , K% k4 Q& u6 e% f
  886.     for (i = 0; i < bytestream_size; i++)
    # z- X3 U2 E9 S  h0 ^
  887.         printf(" %02X", bytestream[i]);# y& O: i" f# N
  888.     printf("\nnewbytestream:\n");5 ]4 C# V8 J( k
  889.     for (i = 0; i < pb->byte_index; i++)5 n" i8 D! o1 j0 C! F+ O5 V
  890.         printf(" %02X", pb->bytes[i]);
    # M) B& ]6 {7 w5 `+ v
  891.     printf("\n");# b2 W* F0 n" Z) L
  892. + y: W2 G6 I* X
  893.     delete_get_bits(&gb);9 q& U5 E& n! d* z: u/ P6 V3 W
  894.     free(pb);4 g. H4 s. A& Z
  895. #endif
    9 W3 g; M; I# s( A/ i

  896. # e$ K( b/ W  h
  897.     /* validate the number of arguments */: V7 W. t" N0 O- \! l3 e  X
  898.     if (argc != 8 && argc != 9)
      U0 ?/ w. ~. J  I5 I
  899.     {8 E2 i5 }& a9 }' u+ M* F2 ~* M
  900.         printf("USAGE: subtitle-rbt <subtitles.ass> <in.rbt> <out.rbt> <origin X> <origin Y> <width> <height> [dump_frames]\n");
    ! s4 U" h' _' }. H
  901.         return 1;
    " S1 g7 ~& E0 h& L. ^; @
  902.     }
    1 E, C0 Q/ i, ^! F: t
  903.     subtitle_filename = argv[1];5 E$ e# W' i0 [, _, _+ [& ^
  904.     inrbt_filename = argv[2];
    7 [0 I' ^: U& w0 Y
  905.     outrbt_filename = argv[3];5 O# Z3 a: i/ c3 r: ]5 i# Q
  906.     origin_x = atoi(argv[4]);
      G8 m( E( \! w/ Q: Y1 D4 ?  D
  907.     origin_y = atoi(argv[5]);/ ~' q" g% G9 U2 t8 l* p( o
  908.     window_width = atoi(argv[6]);& n$ p  y8 T0 I. a" m5 _/ Y
  909.     window_height = atoi(argv[7]);. {! F+ P) C. I6 o, w9 ~* Z
  910.     rbt.dump_frames = 0;) b% Y9 G1 Y7 V% q+ z  s' q
  911.     if (argc == 9): k0 S& F0 r5 ~3 q* V- B
  912.         rbt.dump_frames = 1;$ q- [& T* {! ^5 u

  913. ( |9 M2 F" F' j. u6 i" h8 u$ H
  914.     /* verify that the specified input files are valid */
    # H$ [+ y" I+ _+ X5 ]2 t
  915.     subtitle_file = fopen(subtitle_filename, "r");
    & C5 b. R, @) x: [
  916.     if (!subtitle_file)
    1 u" i- k6 d9 Q1 Y( f  a6 _
  917.     {
    : Z* J/ J" n$ k) I  f4 i* w
  918.         perror(subtitle_filename);
    ! [2 ~, C  n! C, |' b3 v) u
  919.         return 1;
    9 r8 |+ x0 j/ t# A2 }/ h
  920.     }
      p# a5 e7 Z5 h8 `: s0 t  S- O- e  K% D
  921.     fclose(subtitle_file);+ I8 p3 f# |4 b! K; p& F8 N
  922.     inrbt_file = fopen(inrbt_filename, "rb");! w5 U% l; `7 }; R$ R1 }
  923.     if (!inrbt_file)
    2 d! J9 n! X9 \  l
  924.     {
    0 c9 f4 X$ X; P% x3 }
  925.         perror(inrbt_filename);
    & o0 ]6 D( X% i. i8 \; H
  926.         return 1;# n1 K* s5 n$ D8 q. ~
  927.     }
    - x0 K/ i- [. r- R5 y4 s
  928. ' L& F9 a# {9 m, Y$ f; _+ C
  929.     /* initialize the subtitle support */
    6 y: U9 f5 ~9 s/ c2 g& X3 ]
  930.     rbt.ass_lib = ass_library_init();
    3 y( N3 O1 ]. A2 }, ]4 t$ M, a$ ~
  931.     rbt.ass_renderer = ass_renderer_init(rbt.ass_lib);/ n' g. }! T& D5 r, [/ W
  932.     rbt.ass_track = ass_read_file(rbt.ass_lib, subtitle_filename, "UTF-8");$ r3 `  P7 s1 m* b% o
  933.     ass_set_frame_size(rbt.ass_renderer, window_width, window_height);+ X9 X( y# R. y: @
  934.     ass_set_fonts(rbt.ass_renderer, NULL, NULL, 1, NULL, 1);
    / |0 R% o" X- O
  935. % k6 R& q3 h8 j6 W7 P
  936.     /* open the output file */
    ! r0 O$ h6 i2 Y
  937.     outrbt_file = fopen(outrbt_filename, "wb");$ w2 o& Q/ ?! O! ]
  938.     if (!outrbt_file)
      u+ x; L) m8 {) L/ O
  939.     {
    + h$ E$ v( A2 v4 @: B) D
  940.         perror(outrbt_filename);- m( F4 `: j2 E! R& O$ O
  941.         return 1;  \0 N6 t% S* [5 i7 n3 v7 Y! Q6 V
  942.     }
    " a3 a5 U* F# Y( D

  943. ! {2 \0 N! w* D4 c/ G. N
  944.     /* transfer header from input to output */* T4 ]' V9 `; Q( [5 D
  945.     if (!load_and_copy_rbt_header(&rbt, inrbt_file, outrbt_file))
    & Y4 U6 {# Z/ H9 N
  946.         return 1;
    " k, g& e0 j" H( L- L. G

  947. / t6 H6 j9 [+ m, R3 T
  948.     /* rewrite the frames */$ Z: j% b  S' S, u1 `7 T9 F/ [
  949.     if (!copy_frames(&rbt, inrbt_file, outrbt_file, origin_x, origin_y,/ u5 ~( Y8 G6 Y, _( E/ S
  950.         window_width, window_height))
    " ^  L( K1 @0 }$ g. A2 `
  951.         return 1;  X5 R) O# C  X1 p2 H. ^% O

  952. ! q1 M( R4 A) J( r5 ]: ]+ u. r
  953.     /* write the modified frame size tables back to the file */' e1 |% Y& Y4 K3 D: I% y
  954.     fseek(outrbt_file, rbt.video_frame_size_table_offset, SEEK_SET);$ f7 n+ j2 @2 y4 ^
  955.     fwrite(rbt.video_frame_size_table, rbt.frame_count * sizeof(uint16_t), 1, outrbt_file);
    ! `$ A$ W  d( x1 T8 J, x
  956.     fseek(outrbt_file, rbt.frame_size_table_offset, SEEK_SET);
    3 \, V: h1 L4 I0 @
  957.     fwrite(rbt.frame_size_table, rbt.frame_count * sizeof(uint16_t), 1, outrbt_file);+ P# |8 n" Z. b- O+ _, q" s$ Y0 r' b) ~
  958. + ?6 V8 x1 i( \6 T7 F0 P
  959.     /* finished with files */0 T( g5 B; D8 X+ h) |/ y; f
  960.     fclose(inrbt_file);
    " c8 Z' y1 l( O. g3 q
  961.     fclose(outrbt_file);
    ! p4 Z0 \! m1 D4 f" f7 h

  962. 8 b6 _+ H$ u9 |) A
  963.     /* clean up subtitle library */4 O5 F1 I$ @2 A4 u4 s* a
  964.     ass_free_track(rbt.ass_track);
    ' V& u3 Z9 x* e9 R( `5 T
  965.     ass_renderer_done(rbt.ass_renderer);9 v* {0 s- F6 N+ x* q# r7 j
  966.     ass_library_done(rbt.ass_lib);; U) ]7 q( v' {' B
  967. / K1 S: D7 @' ^' \5 b
  968.     /* clean up */
    5 o* T' p3 [& e, ?
  969.     free(rbt.frame_load_buffer);
    # O' G6 E8 X- o- |! a, p, w" H+ Q
  970.     free(rbt.video_frame_size_table);
    ; I7 R5 h0 u8 Y) C
  971.     free(rbt.frame_size_table);1 F' f0 |8 ]6 C" C- X0 {' N+ F
  972. 0 W2 m  V, c; N+ u: t4 U; d: ?% N
  973.     return 0;% [& p8 T+ y, D. T8 [$ J4 \7 H- B2 s
  974. }
复制代码
/ k" r4 Z. N% y1 c
$ q5 y  N+ m) K; B  Y

  W/ T9 i# }- c: ^( K) s8 d' r1 V2 ^1 y$ P
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 很美好很美好 很差劲很差劲
回复

使用道具 举报

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

使用道具 举报

板凳
 楼主| 发表于 2009-11-19 11:38 | 只看该作者
引用第1楼soring123于2009-11-19 11:09发表的  :
# X+ A) }. T9 h- |0 E这游戏有字幕吗?

3 n2 S: W. j8 J2 X! F好像没有字幕,我说的是给视频外挂字幕方式的汉化。
1 u1 a% n0 D" J9 S( ~就像syberia2汉化版下面那行字一样。
回复 支持 反对

使用道具 举报

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

使用道具 举报

5#
 楼主| 发表于 2009-11-19 17:39 | 只看该作者
引用第3楼soring123于2009-11-19 17:07发表的  :
7 Q, z( @) y! I& p; N& y我记得是没字幕的 比较麻烦 都是视频的
9 M3 R7 d5 V2 P4 Q5 g9 _
给视频外挂字幕方式汉化也许能行。
( }- o' b) W/ X9 d要结合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日,是全球华人共同的冒险解谜类游戏家园。我们致力于提供各类冒险游戏资讯供大家学习交流。本站所有资源均不用于商业用途。

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