冒险解谜游戏中文网 ChinaAVG

标题: [第4波]幽魂系列汉化的有关资料 [打印本页]

作者: shane007    时间: 2009-11-18 23:56
标题: [第4波]幽魂系列汉化的有关资料
本帖最后由 shane007 于 2021-1-2 13:56 编辑
- W0 L9 @3 b, z1 S5 t5 C) O- L
最近找到了一些和幽魂系列Phantasmagoria 有关的资料,
$ g3 y; Y. G8 g% }也许将来可以用于汉化。
2 S0 l" V' X9 g/ ^) k+ w
" W' e7 }( b% q0 E* f4 D3 d和日文版有关的信息
+ K+ d9 y0 |7 V/ Nhttp://anthonylarme.tripod.com/phantas/phintgtp.html, x$ g' \/ V) |8 O) ~) o

. ]  C5 X3 f5 Q* r& {/ E/ V相关工具" m! I9 C5 S8 o1 n
http://anthonylarme.tripod.com/phantas/phcheats.html+ T- I. X4 {: T9 `4 t( F
-----------------------------------------------------------------------$ I2 m* a5 \0 E, z
2012/1/2  更新
4 U9 x% t) f8 r7 h. O1 k6 t关于幽魂游戏的字幕
, N$ {# x9 t; J: M* x1 aPhantasmagoria subtitles function discovered - ScummVM :: Forums( I1 i% y8 l7 f$ A) s# E0 ~
' n, s1 [' N: y" r5 _
VMD文件
+ q! Z( f( L5 U% vSubtitling Sierra VMD Files | Breaking Eggs And Making Omelettes (multimedia.cx)VMD - MultimediaWiki
% }' W, ?' a  I% }$ U3 b9 u( ~8 X, |4 f5 h& h+ k0 _
字幕# s* s8 y0 u1 Z9 p
Subtitling Sierra RBT Files | Breaking Eggs And Making Omelettes (multimedia.cx)' S! ~: L( p4 x$ r& k6 u

' R2 ]' o* R3 ~8 aFFmpeg/subtitle-rbt.c at feature/VMD_encoder · multimediamike/FFmpeg · GitHub9 b# C1 w; g8 Q9 I
  1. /*
    4 |9 I2 T% f2 w7 r1 q
  2. * subtitle-rbt.c
    5 c8 M+ c# F2 |
  3. *  by Mike Melanson (mike -at- multimedia.cx)
    3 c# a0 a, {* X, w! G0 I
  4. *
    , U. _+ c1 s7 [. _
  5. * build with this command:* @- d9 U2 m+ \; }8 `1 V; [
  6. *   gcc -g -Wall subtitle-rbt.c -o subtitle-rbt -lm -lass
    - d! B/ K9 A/ |/ ^
  7. */2 D. Q! q" s8 E. C  \: e
  8. ) u5 s5 H/ q1 @" o0 I
  9. #include <inttypes.h>! {! c* l8 Z1 g1 E' n
  10. #include <math.h>8 _4 p& C/ D+ ]3 c6 Y! b+ A1 f) H
  11. #include <stdio.h>
    / a0 ?+ L5 \- c% j; `: q: w3 M
  12. #include <stdlib.h>
    3 G% T$ \* Y7 |" y5 J* ~
  13. #include <string.h>
    / K$ U0 J% Q! `3 x

  14. 5 [1 ~+ }; h& M0 K/ Q
  15. #include <ass/ass.h>) b! o) F: g  Y' c7 @+ q* H# \
  16.   C3 A* k, S5 z$ T& g/ K- P8 Z
  17. #define LE_16(x) ((((uint8_t*)(x))[1] <<  8) | ((uint8_t*)(x))[0])7 k  u* W' G/ G1 f' a( x3 m

  18.   M! }6 }* K4 B& V2 I# u
  19. #define LE_32(x) (((uint32_t)(((uint8_t*)(x))[3]) << 24) |  \
    0 \: Z- X) G7 g, y2 i0 W) s1 K
  20.                              (((uint8_t*)(x))[2]  << 16) |  \* F6 t# }& a) ^: r7 W0 w$ M
  21.                              (((uint8_t*)(x))[1]  <<  8) |  \8 u$ e) Z/ v( \$ ^5 P7 W" _
  22.                               ((uint8_t*)(x))[0])
      u0 ^, [4 k( v+ ^

  23. 5 @$ F4 ?- A0 Z$ `6 r
  24. /*********************************************************************/7 X* ?3 b: |' T/ r' S2 H; j
  25. & f( k7 ?8 l5 Y) Y
  26. /* Bit reader stuff */
    2 d& k1 }+ C1 p5 L
  27. 0 L, M. [3 f7 Y$ ~6 C
  28. typedef struct
    1 q2 `9 q+ |1 F* F; ]
  29. {. P1 F& l" r1 F
  30.     uint8_t *bytestream;
    3 B: n) |6 A( C; [4 |* L" C4 ?
  31.     int bytestream_size;5 j2 ~6 Y" b  ]3 _( d% y
  32.     int index;
    8 \5 W9 t8 W3 h2 l4 I. K1 I
  33.     uint32_t bits;
    $ f. P! }( ^& U" ^0 I
  34.     int bits_in_buffer;1 U3 T7 K9 }% s6 t/ g  o
  35. } get_bits_context;2 K) z- N, f9 d0 v

  36. ) y  W0 K( F2 y- c5 H- R; N
  37. static inline void reload_bits(get_bits_context *gb)
    6 n. A% O3 x5 Y7 i- B+ ?# {3 T- T
  38. {
    ) E- j4 ^7 ]6 A; o. ^
  39.     while (gb->bits_in_buffer <= 24)
    $ x- r9 S3 q5 e9 A
  40.     {- f- ?% E1 s# s0 \; W3 l
  41.         if (gb->index < gb->bytestream_size). B  x3 b" S; C1 k6 O7 u2 _  n0 v
  42.             gb->bits |= (gb->bytestream[gb->index++] << (24 - gb->bits_in_buffer));2 P) {2 @8 I, P6 T+ H! t
  43.         gb->bits_in_buffer += 8;
    ( I3 ]' F3 j5 w+ O8 X
  44.     }
    ! k; f, l' h- q& _
  45. }
    - e: x4 V% A( F( D

  46. , n8 |- I! e1 g; o- p$ X
  47. static void init_get_bits(get_bits_context *gb, uint8_t *bytestream, int size)
    ( A. k( r. _! G: _
  48. {9 c+ U) J- M4 ]; s+ g
  49.     gb->bytestream = malloc(size);
    9 L* Q5 f! T; P
  50.     memcpy(gb->bytestream, bytestream, size);: v0 T: t, X! t. c2 j( _
  51.     gb->bytestream_size = size;
    " Q/ P( ~' p7 S
  52.     gb->index = 0;/ C3 Z4 R& f. f9 b, d$ |1 M
  53.     gb->bits = 0;" d4 M! A- K+ e; O7 M- _
  54.     gb->bits_in_buffer = 0;
    ' L) r1 T, [3 L! A: y  y6 f* ]

  55. * Y0 Z/ T9 V, D: h- P5 ^
  56.     reload_bits(gb);
    , E6 E! `6 t  l6 b
  57. }0 p$ c- K* u2 v8 K3 {
  58. " w8 H3 k2 {" @
  59. /* read bits without consuming them from the stream */
    + ?2 D9 j4 o3 S, l7 R' f' B9 ]
  60. static int view_bits(get_bits_context *gb, int count)
    5 B9 {! H8 z# O+ f5 O
  61. {+ Q6 H" [8 P5 Z, Z" t" n8 [4 a" }
  62.     if (count >= 24)
    ( Z5 Q8 y) T) X) R- k* T
  63.         return -1;5 T: [! }$ j) J& H' E& ]) \1 [/ k
  64.     if (gb->bits_in_buffer < count)
    " {# C- c& Z% L9 O6 i2 y! Z! K
  65.         reload_bits(gb);
    , Z% s7 f8 F% b' b
  66.     return (gb->bits >> (32 - count));9 s1 ]$ O$ j* e% u
  67. }
    / r8 A/ f$ u: m7 m0 N
  68.   u; z3 _8 h4 J' M. b# j) e
  69. /* read and consume bits from the stream */2 e3 {$ s$ h) p, h3 I9 S
  70. static int read_bits(get_bits_context *gb, int count)
      b$ b- [% V% |3 z, C. f
  71. {
    3 A3 Q  C& a- c7 S' E0 w- l
  72.     int value;4 _! P2 c  S6 Y7 i# P$ N2 B

  73. ( B; }$ T) y- B5 k
  74.     if (count >= 24)
    " w6 D; a6 N% w9 z2 T, C
  75.         return -1;9 ?1 u" C) L/ x8 n' h9 Y' w
  76. , x* e) s7 j0 }; }) y* |9 s. M4 o' \2 S3 e
  77.     value = view_bits(gb, count);0 ?, n9 C. N5 f1 R' j! M' L7 g& ]
  78.     gb->bits <<= count;0 ?% R5 t, b+ F
  79.     gb->bits_in_buffer -= count;
    ) W  R: L* Y, u/ r+ ]) g

  80. : h# B4 B. x/ ^2 t
  81.     return value;; L0 k2 D; {; ^2 @* m$ }! d5 b- @# N! F! B
  82. }
    * m4 E+ G; x$ r

  83. 0 P0 I4 S; _+ B: a- J
  84. static void delete_get_bits(get_bits_context *gb)  F: J, ^  z' |" m7 ~
  85. {, }) O6 H0 s0 }9 _- |5 e
  86.     free(gb->bytestream);
    $ k* H6 K& N: O4 n8 |  a
  87. }) R" |: k* f/ r  h

  88. ! u1 e+ m( u& R# n7 B
  89. /*********************************************************************/  [$ \0 A0 q0 G

  90. " x* k6 N4 n1 Q. g7 t6 X0 d3 b
  91. /* Bit writer stuff */
    $ t: M3 K; y: z- U$ K2 B" }/ y
  92. 5 Z8 W2 e9 _) t$ f+ N6 t3 |- i
  93. #define MAX_PUT_BITS_BYTES 63000* |% a; a) O4 {
  94. typedef struct
    1 |4 _( n& T: P
  95. {
    2 ^2 C; h4 S; u
  96.     uint8_t bytes[MAX_PUT_BITS_BYTES];
    1 w0 d+ t2 I% I  e
  97.     int byte_index;+ U! C* w' h0 R6 c1 [6 ^
  98.     uint32_t bit_buffer;
    ' _' ]: z( m2 Y5 C- T7 e6 i/ x6 D
  99.     int bits_buffered;2 H, v4 |5 v# f6 R# y/ `; j
  100. } put_bits_context;! @  E/ A8 ]4 s' s% M
  101. 4 N' f- X/ U0 Z7 R$ h  `
  102. static void reset_put_bits(put_bits_context *pb)
    : P/ l- H: X  F' L' U- [) J
  103. {
    % w) [; a' C1 v7 i6 F6 C
  104.     memset(pb->bytes, 0, MAX_PUT_BITS_BYTES);
    ( F: e2 w' B% z" K- Y
  105.     pb->byte_index = 0;
    7 X# a2 K) q& @7 n( p
  106.     pb->bit_buffer = 0;
    & ?' b, P% r2 J0 t3 M6 e; q+ M" O
  107.     pb->bits_buffered = 0;, B& A& x1 e) k- @% Z' q
  108. }
    ( X+ u+ C& `+ a" z* b5 b9 v  j

  109. 4 W+ m. a1 ~. T2 g0 A) b
  110. static put_bits_context *init_put_bits()6 H2 y# j4 v1 k& L/ D7 W% b
  111. {$ p( m, }, e- i
  112.     put_bits_context *pb;1 W1 E0 s/ p$ h3 t/ p7 |2 m

  113. 4 k" C4 s' G6 c6 i( ?8 U/ z& R- H) w: M8 I
  114.     pb = malloc(sizeof(put_bits_context));  B, N+ N0 S- Q& l3 _6 q
  115.     reset_put_bits(pb);- D/ k# Y& x( c) P" |5 z0 V) r9 S

  116. , l3 T( F: x* V
  117.     return pb;6 X; r1 M( }' z& p" e* j" a
  118. }
    1 I! n' J# i* K5 N

  119. 0 ^5 H. c/ b& R
  120. static void put_bits(put_bits_context *pb, int bits, int count)
    9 }  D1 a: I% y/ z$ s! ~
  121. {
    1 h' ~" m. @! q: l
  122.     pb->bit_buffer <<= count;
    ; P  M. ?% P1 _6 w* G
  123.     pb->bit_buffer |= (bits & (~(0xFFFFFFFF << count)));! V3 ]. `5 C; R6 d
  124.     pb->bits_buffered += count;
    3 Q9 H$ ?3 d! `% w) d8 P8 B0 o+ A
  125. 2 ^, _2 `) T2 \' D5 Z8 F( T
  126.     while (pb->bits_buffered >= 8)
    , ]' @. [, b$ V. x3 |+ ^& _: q
  127.     {* _( s' c- P' v0 r; ~+ V' N& _- X) }
  128.         pb->bytes[pb->byte_index++] = pb->bit_buffer >> (pb->bits_buffered - 8);- I/ S$ ]5 Q& H% L& q5 v
  129.         pb->bit_buffer &= (~(0xFFFFFFFF << (pb->bits_buffered - 8)));
    . H" a2 e/ [! n, W! ~, M! B) P: s
  130.         pb->bits_buffered -= 8;  T- D5 P# |: Q5 f# z0 g3 [
  131.     }9 p! x. o& ]8 d: {
  132. 1 e, C/ J5 F/ G) s# k
  133.     if (pb->byte_index >= MAX_PUT_BITS_BYTES)
      F  d1 X: Z7 k$ n# O) s; Z. L
  134.     {+ y$ s! E! ?4 |" @/ R3 F1 x
  135.         printf("HELP! Bit overflow\n");) q8 l. t" e7 \' j) c6 W# B8 ~8 k
  136.         exit(1);: C# d  [7 V& h
  137.     }
    ' J' W7 y. D4 o3 f( `  x
  138. }3 f# i! l* q9 v5 d* ^& \" L; C
  139. 7 J1 }2 I9 k/ h8 p" E
  140. static void put_bits_flush(put_bits_context *pb)9 i' h/ U  J: m$ `3 h
  141. {# F- M: X( Z1 ~, v2 K0 Y
  142.     if (pb->bits_buffered > 0)
    + N: F3 l) }: ~2 D
  143.         pb->bytes[pb->byte_index++] = pb->bit_buffer << (8 - pb->bits_buffered);
    9 x; ?" {8 M; c3 B
  144. }# Z& {5 [: N( q

  145. - i/ U. _2 _5 H+ R' o% D
  146. static void delete_put_bits(put_bits_context *pb)1 p1 v8 d. P+ ^% i
  147. {5 h) x  o  F+ n0 |% o. e- n/ S  d
  148.     free(pb->bytes);
    7 z/ `* w" ?2 K5 d' ]( h( H
  149. }
    0 q  ~; d& h! i* T0 V" h

  150. 8 }$ y8 H3 z: N8 P+ e* m1 V
  151. /*********************************************************************/
    ; Z6 E3 y( `' _, {3 n
  152. . L+ ^9 E! |% y
  153. /* RBT functions */
    % y2 Q* J$ e- ]( p; L  r9 x
  154. / S  v/ w) l. C& B8 t
  155. #define PALETTE_COUNT 256" P# ]6 ]# S5 ]% C
  156. #define RBT_HEADER_SIZE 60
    3 d: \# O4 g! ]2 G+ }
  157. #define UNKNOWN_TABLE_SIZE (1024+512)" u) x: f, @$ r- T1 [
  158. #define SUBTITLE_THRESHOLD 0x70
    * Y4 P# a+ O! S" t3 i, r& j' f
  159. #define MILLISECONDS_PER_FRAME 100
    & r- G, \% V$ O  B! s- D

  160. 5 g6 L- K/ U& O8 K/ n
  161. /* VLC table */
    ! M" a. ^% Y2 w+ k5 f
  162. #define VLC_SIZE 4
    ) W" e8 I  F" T5 u
  163. static struct
    4 B, u& g$ b  H1 |  E2 N0 G
  164. {
    $ ?( s) k; ?1 M3 N
  165.     int count;  W) C) E/ C# z; E7 j% g
  166.     int value;
    ( J/ u$ S) A& R: c  b7 ~
  167. } lzs_vlc_table[] =* V0 N0 T3 t! h. \) c9 ~
  168. {2 B% l! b+ ?/ h1 F+ a
  169.     /* code length = 2 bits; value = 2 */: m1 z$ g6 W2 p2 L7 D
  170.     /* 0000 */ { 2, 2 },
    1 `# ]* ~$ _  ~( ?
  171.     /* 0001 */ { 2, 2 },  a: F  d" {. ^: j8 \& L
  172.     /* 0010 */ { 2, 2 },
    ( a- M, g: e( X1 y
  173.     /* 0011 */ { 2, 2 },5 N2 g% n5 _' a3 h3 @

  174. - k& b8 U8 P, J8 y# J
  175.     /* code length = 2 bits; value = 3 */
      O' ~2 q+ {! I+ g
  176.     /* 0100 */ { 2, 3 },
    ' d# t9 T' `" r; s+ }8 q
  177.     /* 0101 */ { 2, 3 },
    : E; S4 R' E+ `% a' ?, j
  178.     /* 0110 */ { 2, 3 },
    ( q: j2 d3 q! w6 M& C
  179.     /* 0111 */ { 2, 3 },
    ! [4 K; V: G( d$ V
  180. + S0 c# W5 [& A6 G  h* C
  181.     /* code length = 2 bits; value = 4 */$ l; c% G& V, X: i2 b! D+ x
  182.     /* 1000 */ { 2, 4 },3 S4 U6 j$ m  W+ U1 v1 j  O
  183.     /* 1001 */ { 2, 4 },2 h3 a- m  R8 Q0 K5 T1 H
  184.     /* 1010 */ { 2, 4 },9 B; J, Y  b+ {* m- N6 {# q" r
  185.     /* 1011 */ { 2, 4 },  A2 v* d) Y! C+ L  k$ i( ~4 \% L' C
  186. * l( Y$ V. _# ?& T$ p
  187.     /* code length = 4 bits; value = 5 */
    . f2 i7 T/ K: y9 t+ e: I5 _
  188.     /* 1100 */ { 4, 5 },
    , _0 I% P1 s; _/ O
  189. . {: M- P" m: g  K8 U
  190.     /* code length = 4 bits; value = 6 */. i% w' C* l0 S$ }3 _
  191.     /* 1101 */ { 4, 6 },
    * m) p. U9 L/ ~7 g6 S) V
  192. $ y6 ~8 D8 m  t! K  v' O+ s2 ?5 n
  193.     /* code length = 4 bits; value = 7 */5 @: s# [+ L; o% |/ f
  194.     /* 1110 */ { 4, 7 }," ]7 u: n8 p# b& n1 ~! z% g# _

  195. # Q$ \2 s/ P. S2 ]
  196.     /* special case */9 Y4 u2 j; S: c, L
  197.     /* 1111 */ { 4, 8 }, V" d7 k# A8 }. a6 y+ f2 t
  198. };( M1 O9 N# S3 M8 }1 M, @

  199. 8 |+ [& {9 V5 [  J
  200. typedef struct
    + s, k7 A+ a6 m$ l2 r& w
  201. {
    ! o: k8 M* a% t& Y
  202.     int version;
    / }* V* Q6 ?% @8 e
  203.     int width;
    $ d  A8 V+ n( N* v. r0 |
  204.     int height;8 F2 h2 I2 A( v) {: D' U+ p  L
  205.     int frame_count;; i' x$ u; k: m  z; Z2 r
  206.     int audio_chunk_size;
    & ]9 c1 k4 ~* x1 p0 e
  207.     uint8_t palette[PALETTE_COUNT * 3];
    + ~3 j: c' r# @# l9 f
  208.     off_t video_frame_size_table_offset;5 q7 k; s5 \. H; A! K9 o. R/ [' l
  209.     uint8_t *video_frame_size_table;5 @5 }) r9 f1 E* A  _) T3 {4 k/ n
  210.     off_t frame_size_table_offset;/ R0 A0 \& u' O& x5 d% O0 i; b
  211.     uint8_t *frame_size_table;
      _' M- n- m4 I5 \5 @; I
  212.     uint8_t *frame_load_buffer;
    4 b( M8 _0 ?. a) {! l, q
  213.     int dump_frames;* @' {: J' ^( B$ u$ B
  214. # ~( }+ O7 Z) B
  215.     /* subtitle library */, v; _+ y, A% s# P1 o
  216.     ASS_Library *ass_lib;
    # X) }3 N. S. F' M9 I- y1 L! l+ P, K
  217.     ASS_Renderer *ass_renderer;+ ~$ u& @- q; |; ]3 E: e
  218.     ASS_Track *ass_track;
    % Q" K7 S. }# _1 R& @
  219. } rbt_dec_context;! ~. T" G9 L1 x+ e9 g* d3 o

  220. ( B9 A  y# c. S+ t& M4 N" y' G
  221. static void dump_pnm_file(char *filename, rbt_dec_context *rbt,
    # R5 T' N9 z+ j4 O1 a4 c  }' d
  222.     uint8_t *image, int width, int height)
    : L! ]8 ^! s4 b
  223. {
    , h( z# _; X' K. t/ F
  224.     FILE *outfile;  ?/ u& \0 |) Q  n- b5 U9 d$ }
  225.     uint8_t bytes[3];
    2 M( {; p* r. S8 O1 B9 p
  226.     int p;
    1 a8 }6 R; ?5 f7 a
  227.     uint8_t pixel;( v. O7 I, K6 l  ^( c! t6 Q7 m9 G
  228. ( ~0 w  S1 R* u
  229.     outfile = fopen(filename, "wb");# A& N" K- ~- t
  230.     fprintf(outfile, "P6\n%d %d\n255\n", width, height);3 Z  w- T$ }5 N% v/ z
  231.     for (p = 0; p < width * height; p++)
    * c* ]4 }/ {$ {
  232.     {
    - x8 O1 m; Z. V! k4 M
  233.         pixel = image[p];
    / y: J$ u  w8 R5 y) E7 B& t$ f4 Y# {
  234.         bytes[0] = rbt->palette[pixel*3+0];. K$ g3 L) ^3 J, e+ j
  235.         bytes[1] = rbt->palette[pixel*3+1];
    ' r7 W; y( L8 a& z. x  D" n7 U
  236.         bytes[2] = rbt->palette[pixel*3+2];
      Y; d! `) v, E# X5 J  e$ w6 M
  237.         fwrite(bytes, 3, 1, outfile);* r$ w) J) X1 F
  238.     }- m3 x. |1 O- w9 B$ X2 o
  239.     fclose(outfile);# w( P4 j9 s) Y" Z
  240. }$ Y' p# S$ d/ d* H: Y% }
  241. + c0 R# w  a: p# q  i1 v( {
  242. static int load_and_copy_rbt_header(rbt_dec_context *rbt, FILE *inrbt_file, FILE *outrbt_file). U* S( M; U) ~) r0 j  j6 ^# B
  243. {6 E; D/ G/ G2 t7 q  K7 o
  244.     uint8_t header[RBT_HEADER_SIZE];- Y( t/ y  B1 `1 n# j1 B" ]9 N
  245.     int palette_data_size;
    9 e: @% l/ ^# _) D
  246.     uint8_t *palette_chunk;3 t: {! h2 t, i& A8 z
  247.     int unknown_chunk_size;
    1 Y5 [) d, a9 J: D( c3 z
  248.     uint8_t *unknown_chunk;
    ) c; @+ [# o* H$ Z
  249.     uint8_t unknown_table[UNKNOWN_TABLE_SIZE];
    6 s" q9 t: |4 L: l$ \2 I
  250.     off_t padding_size;
    . H/ e! A# a/ _& g, N
  251.     uint8_t *padding;
    9 W2 ^4 ]6 }/ i0 `: A' I& R
  252.     int i;( e, p9 ]" R9 L) T1 m
  253.     int frame_size;5 h& [" E# ^4 Z
  254.     int max_frame_size;: t' p5 D; O% x& o% A6 w
  255.     int first_palette_index;
    $ V4 w9 E' u2 l  S1 d
  256.     int palette_count;. X0 Q  ^; P& v& B& `0 |
  257.     int palette_type;1 g( T, c, b* N. {5 b0 Q" k4 J) C
  258.     int palette_index;6 z+ ~, \* h5 I8 a- V4 U' s+ i
  259. ! P( q' w/ }: w6 k7 F& ?
  260.     fseek(inrbt_file, 0, SEEK_SET);
    6 v8 y- m. v+ e5 \7 r2 D1 O
  261.     fseek(outrbt_file, 0, SEEK_SET);
      r; I% X7 K# N7 S2 z" a  [. h
  262. ) i  T, t# C$ d& w- `" c
  263.     /* load the header */
    7 s! A; u6 ?' o" A* z/ F
  264.     if (fread(header, RBT_HEADER_SIZE, 1, inrbt_file) != 1)8 H  N# @- W, {1 _  H( l
  265.     {6 {6 [$ l7 r  @' _$ o$ x
  266.         printf("problem reading initial RBT header\n");9 v4 S! p4 m3 E0 l
  267.         return 0;
    9 n/ w: }( r1 P, e% o7 e
  268.     }
    ( R& B) K: s' B: R5 v
  269. $ X$ B" l! m) l: J2 w4 U
  270.     /* copy header to the output */( Q% [. H0 F0 d: m: h6 r! A
  271.     if (fwrite(header, RBT_HEADER_SIZE, 1, outrbt_file) != 1)" ~: K8 R3 N) N' \* o
  272.     {
    ' s2 L# e* E# ], x
  273.         printf("problem writing initial RBT header\n");/ [, N) N+ g, Y, W9 C: X
  274.         return 0;
    ! L( t9 `* h7 c9 `, I/ {
  275.     }
    + M$ W7 m* G/ S: {) s
  276.   w/ e/ ~+ s! a# L% B/ y6 w+ t
  277.     rbt->version = LE_16(&header[6]);
      Z% ]. v: O5 ?1 \
  278.     rbt->audio_chunk_size = LE_16(&header[8]);8 y9 U! r7 [( }6 C; y0 W/ p1 [
  279.     rbt->frame_count = LE_16(&header[14]);/ l) B9 F2 v# W* k  B
  280. 8 Y1 w# O2 z5 V% S
  281.     /* transfer the unknown data, if it's there */
    5 H* Y1 a, a, @+ r
  282.     unknown_chunk_size = LE_16(&header[18]);
    8 m! O' k% u; b' \' v/ O
  283.     if (unknown_chunk_size > 0)
      B% M1 E6 g5 h
  284.     {+ S! v+ O/ n1 f9 L+ q8 Q: K0 {, {" K
  285.         unknown_chunk = malloc(unknown_chunk_size);( T8 Z8 Z. k* ?4 G! R) \7 l
  286.         if (fread(unknown_chunk, unknown_chunk_size, 1, inrbt_file) != 1)/ i0 a* g3 o& @; ^8 e6 p
  287.         {3 U! Q- X$ _  e* |- r" c$ b7 @" \
  288.             printf("problem reading unknown data\n");
    ' e) h8 H( F/ w, [
  289.             return 0;. R: ^8 n% J& P$ J/ ]; Y
  290.         }
    . u/ f6 w6 n' j) ^$ F
  291.         if (fwrite(unknown_chunk, unknown_chunk_size, 1, outrbt_file) != 1)1 ~" F8 r' V; ?
  292.         {+ O9 |7 F* y: X0 {; A
  293.             printf("problem writing unknown data\n");
    $ H8 w7 s+ i7 J; }
  294.             return 0;: J- i) ~! R2 I) M- c& h/ h
  295.         }8 h2 ^: v) U$ c# y3 d
  296.         free(unknown_chunk);
    6 }# Z! U1 M7 l/ F1 ]( ]0 a
  297.     }2 g& Q$ r8 l0 c; L6 N. Y, S

  298. - c% s  _% e: s9 N. k  e6 S% F% x
  299.     /* transfer the palette chunk */
    7 Z7 {% V  K2 G! s  d
  300.     palette_data_size = LE_16(&header[16]);) N2 j' H& h0 c+ T, A9 _
  301.     palette_chunk = malloc(palette_data_size);
    % P$ y" t0 |/ s9 c
  302.     if (fread(palette_chunk, palette_data_size, 1, inrbt_file) != 1)
    4 a' ?5 L) o5 E1 ]
  303.     {
    1 e1 f' g3 Z" d
  304.         printf("problem reading palette\n");9 C2 ~4 o' k* G% q
  305.         return 0;
    % k. d9 E1 K& z& D/ E, N8 i
  306.     }
    " m2 B- [/ U" Y# R( D
  307.     if (fwrite(palette_chunk, palette_data_size, 1, outrbt_file) != 1)
    ' `# B" k: l) t/ z
  308.     {
    , ]' E" R7 g0 D' Z& D
  309.         printf("problem writing palette\n");. U5 w$ p" Z, Y: X$ v2 l0 {
  310.         return 0;" m8 h8 G0 s" z7 |7 q/ {
  311.     }& `' G) s2 [8 C5 [' p
  312.     /* load the palette into the internal context */
    % [, u! C! ^& y' z1 S! Z8 v. Q
  313.     memset(rbt->palette, 0, PALETTE_COUNT * 3);
    . Z4 P. _& W& m! I
  314.     first_palette_index = palette_chunk[25];
    # H% [( H) v; ~/ t1 E
  315.     palette_count = LE_16(&palette_chunk[29]);
    * v! B2 f1 t' @0 a$ }, C
  316.     palette_type = palette_chunk[32];
    ( W" z# v  F: p+ a
  317.     palette_index = (palette_type == 0) ? 38 : 37;
    $ Q8 G) z6 u+ r; }
  318.     for (i = first_palette_index; i < first_palette_index + palette_count; i++)# h' m, |2 ?! \2 O& a
  319.     {
    % K; b3 ~4 n. I& P9 N4 J0 v
  320.         rbt->palette[i*3+0] = palette_chunk[palette_index++];& A; ]4 l& H' N0 y
  321.         rbt->palette[i*3+1] = palette_chunk[palette_index++];
    : f# k2 g1 M' }
  322.         rbt->palette[i*3+2] = palette_chunk[palette_index++];% c: F6 Z3 E; r2 [) t
  323.     }
    - e9 H/ {' N/ t, e  ^  W1 ]$ S( c
  324.     free(palette_chunk);
    1 ^7 @3 H2 a" h4 g& T) {( b1 R

  325. 0 w  U+ c- K; B  x: J
  326.     /* copy the video frame size table (2 bytes per frame), as a placeholder */' y/ r4 m0 j6 r* n( ^& A5 D
  327.     rbt->video_frame_size_table = malloc(rbt->frame_count * sizeof(uint16_t));
    & A3 T: a/ C6 [8 V, p' i
  328.     if (fread(rbt->video_frame_size_table, rbt->frame_count * sizeof(uint16_t), 1, inrbt_file) != 1)
    6 n4 \3 A8 X; b; V- J
  329.     {
    & t+ s# X$ n* z- E0 P6 o
  330.         printf("problem reading frame table\n");, u& K8 }2 x- n+ R1 l
  331.         return 0;' B9 L% ]  f, p5 `2 u5 V! B
  332.     }  h0 E) J3 U5 F( \4 P3 M! J
  333.     rbt->video_frame_size_table_offset = ftell(outrbt_file);
    2 w+ G3 _* f2 _: v: ]
  334.     if (fwrite(rbt->video_frame_size_table, rbt->frame_count * sizeof(uint16_t), 1, outrbt_file) != 1)* U& v! ~# d( I2 R( ?
  335.     {
    1 l- v" D+ p5 y8 ^# ]- o
  336.         printf("problem writing frame table\n");0 L3 l6 I- l- ]0 X4 j& ?* h( ~
  337.         return 0;
    7 J% q, x- Q! [8 ~% w
  338.     }
    $ r7 N9 `1 ~0 A5 Z

  339. 2 v7 A7 p$ O3 [. ^
  340.     /* copy the frame size table (2 bytes per frame), as a placeholder */: G$ e9 r2 |% Z4 c% |' H
  341.     rbt->frame_size_table = malloc(rbt->frame_count * sizeof(uint16_t));; A6 J) g$ r0 t1 W" T  Q
  342.     if (fread(rbt->frame_size_table, rbt->frame_count * sizeof(uint16_t), 1, inrbt_file) != 1)* y, M! B: h6 Z( ^6 \3 Z
  343.     {
    2 V1 ]  x; ~) `0 S3 [; _" F
  344.         printf("problem reading frame table\n");+ |' t: w4 n! Q# h) Z5 D- c
  345.         return 0;
    - S* L+ ~7 u8 ~# J4 O- J
  346.     }# b7 Y0 j5 g9 l) S( n  ]
  347.     rbt->frame_size_table_offset = ftell(outrbt_file);( X) h) i( }2 s
  348.     if (fwrite(rbt->frame_size_table, rbt->frame_count * sizeof(uint16_t), 1, outrbt_file) != 1)
    4 Z8 `/ O8 M1 w% h
  349.     {
    ! J% y0 c" a1 u6 |, k/ g4 L2 u
  350.         printf("problem writing frame table\n");
    6 x& g, C! E3 K1 c& L' X
  351.         return 0;
    - T+ S! ~; ~3 Z. l6 Z
  352.     }& X; Q' V+ O/ t5 `5 L8 ]1 K
  353. + z- f4 E3 B% M: U/ G' e
  354.     /* find the max frame size */* ?( E/ `. }& g" G/ s7 b
  355.     max_frame_size = 0;
    / k' I. Y& K7 H
  356.     for (i = 0; i < rbt->frame_count; i++)
    5 g  ^& _! r+ O+ ^' |
  357.     {
    , b& x; H- z( A: y' q
  358.         frame_size = LE_16(&rbt->frame_size_table[i*2]);, l5 q* D' k1 Y( n9 o% Y% A
  359.         if (frame_size > max_frame_size)( z& l5 w+ h( H9 ]
  360.             max_frame_size = frame_size;
    " [$ R/ u$ S$ N
  361.     }
    ' s$ v( d6 O4 i  c
  362.     rbt->frame_load_buffer = malloc(max_frame_size);' w& h5 x5 _* ]; n' O
  363. * j+ T; N: Z# f- [5 o1 m4 I
  364.     /* transfer the unknown table(s) */
    4 w1 D- F* R" L
  365.     if (fread(unknown_table, UNKNOWN_TABLE_SIZE, 1, inrbt_file) != 1)* o" y: H& N& ^0 ~5 o
  366.     {( k+ B0 L% b; a4 a6 H8 n- Z! }9 Q
  367.         printf("problem reading unknown table\n");8 U; g7 O5 R( E* C: R7 G5 A' ~
  368.         return 0;% ~: Z% L9 j0 D6 K9 O3 _
  369.     }
    8 N9 v/ Q5 U8 r# _" R
  370.     if (fwrite(unknown_table, UNKNOWN_TABLE_SIZE, 1, outrbt_file) != 1)
    6 O  w9 }# Z+ \$ N. |9 g
  371.     {8 M) s: ]/ }" e1 l  {
  372.         printf("problem writing unknown table\n");
    2 I5 g" Y) o3 o9 j
  373.         return 0;
    8 h  ]3 Y3 L  F4 Z  M6 f+ j: ^/ V
  374.     }
    : B- j; \& N& s/ h: A+ w

  375. 2 G2 X2 T% P- b2 ?8 C% l
  376.     /* copy over padding */
    : p1 u1 V- r, a1 X8 \' L
  377.     padding_size = 0x800 - (ftell(inrbt_file) & 0x7FF);
    7 K) n! B1 c+ U- U* h
  378.     if (padding_size)
    9 }& B9 R* Y1 R0 H' R& n- h
  379.     {
    ! O: t, g. a* l3 S1 Z3 M
  380.         padding = malloc(padding_size);8 i2 T7 }$ P8 N% V0 b: t. L( {
  381.         if (fread(padding, padding_size, 1, inrbt_file) != 1)
    2 K/ D8 w: W$ Q8 s! B
  382.         {
    : B: {- u- x, O2 S+ Q
  383.             printf("problem reading padding\n");5 I6 z; A, u+ M  P' t' G
  384.             return 0;
    4 \% Y  G* t( `
  385.         }% d' [7 ?# ]0 D6 c# h7 {. G1 a/ c
  386.         if (fwrite(padding, padding_size, 1, outrbt_file) != 1)
    $ r8 M' J0 P9 E/ I5 A! J2 n
  387.         {+ F+ N7 O2 V3 n, _. L
  388.             printf("problem writing padding\n");
      S; v; F8 o3 a6 \, |) E) r
  389.             return 0;. z! U* i6 i' }8 `1 ^
  390.         }' T: h# ?( Y6 ?* F  W0 @0 O
  391.         free(padding);
    % @" d* P3 e/ p. N  H
  392.     }
    + i* a) M( C$ Y/ r  j6 x
  393. & I. t) ^" Z. s$ ?1 ?, J% U+ b
  394.     return 1;
    3 G2 L1 X+ y- n! M; ~
  395. }
    , y8 o% ?" V1 v. T
  396. ; n! F7 @2 B0 m* C8 G5 D7 Y9 P
  397. static int get_lzs_back_ref_length(get_bits_context *gb)) [/ U3 Y3 K$ ?. U& f- q
  398. {
    ( O; E3 u6 C! ]. ]. B
  399.     int vlc;
    2 L7 e  q& e9 I8 D, Y  W* A% L0 l" ?
  400.     int count;" d. b7 V0 D8 \6 }/ ?
  401.     int value;5 [# P( T2 S: L
  402. ' o. @" A- H+ s  O( Y9 J
  403.     vlc = view_bits(gb, VLC_SIZE);& y7 w% O/ l2 N+ A
  404.     count = lzs_vlc_table[vlc].count;2 G( k1 }8 ~8 ~4 x' G; n& [
  405.     value = lzs_vlc_table[vlc].value;
    6 A1 h$ W5 O$ n9 m+ V3 i

  406. 5 B2 Z9 r5 P& x, a" ^6 k4 K5 ]
  407.     read_bits(gb, count);  M- v  j4 k+ F& g* u- Z# d6 g4 `) N4 O
  408.     if (value == 8)" A0 z; G0 j0 Y. `1 u0 Y5 K
  409.     {# s  x7 C" U$ C* v
  410.         do
    6 O, w" A: e% f4 }5 u8 Y
  411.         {
    * G% |. n! Y5 x1 D
  412.             vlc = read_bits(gb, VLC_SIZE);! j3 o- E- y/ V0 o, Y
  413.             value += vlc;
    # Z3 O! k5 [3 p# x: p7 Z: P
  414.         }
    - s, o/ n! ?. x5 x0 ^8 c2 v/ H6 b
  415.         while (vlc == 0xF);/ ]1 m- w! ~. d7 B  {7 I
  416.     }
    / W* |/ E- a9 ?1 p+ {, i/ [
  417. 6 t* b& s8 J7 `  _+ N& a) W% ]
  418.     return value;4 O5 R6 H, @. N2 b( B" s
  419. }
    ; c4 f' P0 Y! g  ]! {
  420. ) a5 n0 E- v" W1 L
  421. static void compress_window(put_bits_context *pb, uint8_t *full_window,
    4 g1 G' ]- ?! x  t
  422.     int full_window_stride,
    4 O  S" N; W9 e4 O
  423.     int window_top, int window_bottom, int window_left, int window_right)/ O! G+ h$ x, x: C' K1 a
  424. {! ^( \- I3 n4 L- M
  425.     int last_pixel;
    0 B5 b' t( f3 l
  426.     int run_size;
    ! J, p# o0 }, u; J8 x/ r5 g
  427.     int x;0 G! f  S4 k; m4 n( i3 t1 @; C
  428.     int y;
    % j. a2 u# T9 v8 U: N+ V' n* ~
  429.     int start_index;9 }7 h/ I1 u2 J! p2 Y
  430.     int end_index;4 \* g1 h( P5 G" m
  431.     int encode_last_run;
    7 J! k' a) t9 A- |! h
  432. 7 c( }9 f- |2 F3 W
  433.     last_pixel = full_window[0];) H7 L$ t+ f- h) P" x% d
  434.     run_size = 1;
    - y) _6 [$ b+ R+ V" S
  435.     for (y = window_top; y <= window_bottom; y++)
    ( K; n% ?! o' C; m7 @
  436.     {0 v) G! X" y# S8 Z
  437.         start_index = y * full_window_stride + window_left;
    4 @" c. s8 Y1 K0 D# O% E
  438.         if (y == window_top)
    8 b* ~; V. F) K! l& ~
  439.             start_index += 1;/ U5 A) n: s: q
  440.         end_index = y * full_window_stride + window_right;
    # I  {  d6 e/ y9 y% @% T' p
  441.         if (y == window_bottom)
    9 D6 L' ?+ w0 a+ \; W2 ]$ C
  442.             encode_last_run = 1;
    + ^: |: B/ y+ X
  443.         else
    ; G+ e! `3 u+ Q- [( O# c4 |/ Z
  444.             encode_last_run = 0;
    6 f, M- m3 t# a- O) }$ h5 X! j  R; k
  445.         for (x = start_index; x < end_index; x++)
    , t! v9 m7 q  ^6 E/ r
  446.         {
    & v& N- s5 \$ ?' j& r8 ~. D, R, E
  447.             if (!encode_last_run && full_window[x] == last_pixel)
    # E& b1 I1 R7 o3 e
  448.                 run_size++;' E" L- G$ r# D8 U2 U( v
  449.             else
    0 T, @* ?: L8 V; I, E
  450.             {
    8 q4 x% d) ?9 i1 r- ?/ T
  451.                 if (run_size == 1)
    8 H, M6 d! B* w
  452.                 {
    7 E0 q8 j( O5 l% ^
  453.                     /* encode a 0 bit followed by raw pixel byte */
    4 e0 E  c" r5 c% b# \: ~. U! V
  454.                     put_bits(pb, 0, 1);
    7 k" }, J0 a/ {. I
  455.                     put_bits(pb, last_pixel, 8);
    ! u& p0 q7 F  c& L8 I; J+ a
  456.                 }
    5 P$ P  x' p8 s% M5 i# z% W4 O. D
  457.                 else if (run_size == 2)9 h4 E4 P$ {: S. P1 r
  458.                 {
    . R. ]) Q5 l) E# L5 S- ]
  459.                     /* encode a 0 bit followed by raw pixel byte */& ?0 Y% n* ?9 d3 K* m; U0 m
  460.                     put_bits(pb, 0, 1);
    : o% H6 J9 f: d+ q9 v( v
  461.                     put_bits(pb, last_pixel, 8);, b' T- y2 N& o4 w6 G2 ?' X
  462.                     put_bits(pb, 0, 1);7 o) b5 U8 y2 X4 z. e
  463.                     put_bits(pb, last_pixel, 8);; ^, [- S8 R+ Y5 y% f
  464.                 }; w! U! s6 w8 n0 P
  465.                 else6 m1 I2 t4 v) y* J
  466.                 {8 T* h1 r4 F8 e! l
  467.                     /* encode a 0 bit followed by raw pixel byte */: X5 b( \0 C" T, L1 D- S5 t3 N* C
  468.                     put_bits(pb, 0, 1);/ a/ g0 ^$ G1 T
  469.                     put_bits(pb, last_pixel, 8);
    & H7 W) `5 m" ?9 c' {/ R( R
  470.                     run_size--;
    ( d$ g9 c9 Q4 N' e" e
  471.                     /* encode a run: a 1 bit, followed by a back reference
    ) ]+ g& ?( \1 h+ ^+ O8 u! k# q7 n* d
  472.                      * offset (-1), followed by a length */
    5 z! O* v7 A6 v" q. h) |* x7 {; y
  473.                     put_bits(pb, 1, 1);
    & {' R5 E9 F. y3 U
  474.                     put_bits(pb, 1, 1);  /* 1 = 7-bit offset */
    - p: B: `4 _" P) x" b6 x2 @
  475.                     put_bits(pb, 1, 7);$ H+ V8 X, ^' m4 W  l
  476.                     if (run_size <= 4)/ w6 ^; l% F# k6 }
  477.                     {) ~. j1 U) o8 B6 r3 h* a
  478.                         /* lengths 2, 3, and 4 are 2 bits */
    4 n+ ], r. j% ~$ i- V
  479.                         put_bits(pb, run_size - 2, 2);
    % f+ V3 s, e9 w9 ^2 a
  480.                     }
    $ t2 _; g3 N( b
  481.                     else if (run_size <= 7)
    , [6 e3 O  V; z# Q
  482.                     {- ?9 S* i# M/ }1 f' p
  483.                         /* lengths 5, 6, and 7 are 4 bits */4 ~8 Z' X, j3 J" z" J
  484.                         put_bits(pb, run_size + 7, 4);; M5 d' z& _% b( ?' r0 }7 A
  485.                     }
    ' J9 O, V; _' x+ ^& [/ z# A( t
  486.                     else
    0 r- F, g5 J: h6 M7 z" z/ a
  487.                     {
    * H1 [% \, s3 Q; I# _
  488.                         /* arbitrary length; start by encoding 0xF which
    ) c9 o' }" X. k" C( j
  489.                          * stands in for an initial version of 8 */# @) \: I7 b; j% R& l, X3 f- @
  490.                         put_bits(pb, 0xF, 4);( j$ c" Q& ]1 S5 r+ ^
  491.                         run_size -= 8;, g: b( S% T1 w# ^
  492. 5 X& H% {* V4 T' K# M- f. N
  493.                         /* encode blocks of 4 bits until run_size is 0 */9 z% Q: T- `7 T4 B
  494.                         while (run_size >= 0)
    . X7 c% G3 S0 w* A- p( f# H
  495.                         {
    / s6 u# o8 }4 j% i! {: S2 ~* X* `5 L/ s* R
  496.                             if (run_size >= 15)1 T, [- ]% ]3 B7 t6 F0 K% {
  497.                             {8 P& J* c' e5 a# z. u- t4 o1 P
  498.                                 put_bits(pb, 0xF, 4);2 J, b% J2 r( `, }8 m
  499.                                 run_size -= 0xF;
    % F, B- h" ~% I9 r8 \
  500.                             }* ]' k  q8 U; o8 ?
  501.                             else8 q3 H' N, _% V3 z; L5 X  k
  502.                             {- i+ m5 P# y" n8 u7 A1 S; C
  503.                                 put_bits(pb, run_size, 4);
    - y! @9 Z8 D5 \7 G: T% U
  504.                                 run_size = -1;" W7 A5 D  H, L% g5 U/ j
  505.                             }
    # n0 M& ^# X: W% q) J
  506.                         }% q% A' _2 z9 R" g
  507.                     }$ Y8 g. \& f! O% Z# _
  508.                 }
    8 b8 E* ^# K' f. j/ }) @+ h& B
  509. ( K2 V; y+ @$ V6 M+ k  }! v2 [
  510.                 last_pixel = full_window[x];- S& X2 }) |1 @9 _+ Q1 t( @2 g
  511.                 run_size = 1;
    ( W  v3 H7 m- ]" A' P4 w7 Z" x
  512. - U5 M& c' A2 ~6 ]$ U! {
  513.                 /* this single x iteration was only here to close the final run */" f6 k; q/ y& Q  P- ?$ l: C. M
  514.                 if (y == window_bottom)0 X) j6 t- i6 h, `( o5 P
  515.                     break;$ Y% `( a% `% T& l) }
  516.             }+ ~; \* F# A0 J$ F! y' p
  517.         }6 g( h3 }% c) L0 O9 n
  518.     }
    * I; ?% A) ]$ D# @  }4 Y- I6 {/ u
  519. 1 J) {8 H, t4 O" B: ~$ t
  520.     /* close the bitstream by encoding a back reference with length 0 */2 C6 I% i. L" t, b9 \0 {2 _3 \
  521.     put_bits(pb, 1, 1);  /* back reference run */
    ' I6 i. q+ ^0 @/ U
  522.     put_bits(pb, 1, 1);  /* 1 = 7-bit offset */0 a1 g5 L% \0 w6 B* \
  523.     put_bits(pb, 0, 7);  /* length 0 */
    ' E! _  J# U- Y
  524. 1 E. j/ z  A9 _" g
  525.     put_bits_flush(pb);: }  p6 o( H7 ]+ f8 T) {- _2 O- y
  526. }
    - u: f" \; o2 e) L& Q

  527. 1 t' m& T% j& ]/ ]2 _. I3 j
  528. /* compute Euclidean distance between an RGB color and the desired target */
    $ @, \5 {- x+ m3 b- |' a. Q
  529. static int compute_rgb_distance(int r1, int r2, int g1, int g2, int b1, int b2)
    9 }8 |/ s' D  `  u' R
  530. {
    % _/ f2 g/ \% d( u
  531.     return sqrt((r1 - r2) * (r1 - r2) +! `+ ~3 L4 B* b
  532.                 (g1 - g2) * (g1 - g2) +
    + ^+ ~. o/ O( c6 `
  533.                 (b1 - b2) * (b1 - b2));' \! [- k3 U0 W6 o0 q+ n# [
  534. }* ~: ^3 R- _6 k$ n; P1 u0 I

  535. ; U' o. ?9 R. ~5 q6 l% e
  536. static uint8_t find_nearest_color(rbt_dec_context *rbt, int r, int g, int b)
    ( j7 \$ X( _" @4 ^
  537. {0 `. l. B& D. J7 R( O! U$ x7 t) B
  538.     int i;
    * u6 N6 T9 H; M' x: b) U3 h2 T( W
  539.     int nearest_distance;
    ) J2 P+ t8 i6 w& A9 l. q$ f
  540.     int distance;
    % d- w# |* x1 j, d2 q: ^
  541.     int rp;
    / ~  `! |2 r) m6 j# Y
  542.     int gp;
    7 n) Z3 V5 Z; g7 X6 E: q& s$ `. h
  543.     int bp;
    ( \/ e! m* K9 ~3 e7 T) b
  544.     uint8_t palette_index;
    7 M  y/ E3 F, p( v+ a% t% A
  545. " S* f2 c# S5 F( V2 A
  546.     nearest_distance = 999999999;
    " g( h, e& I  l) [& z
  547.     palette_index = 0;' B/ n$ `/ I7 x0 Y* F. s: R: H5 C+ [
  548.     for (i = 0; i < 256; i++)/ [! |" ^5 Q4 `% d, X3 X" y
  549.     {3 Q4 Q8 u6 {/ ?9 N
  550.         rp = rbt->palette[i * 3 + 0];
    ) g* a! k3 L/ T8 y9 S8 Y
  551.         gp = rbt->palette[i * 3 + 1];& q! l$ ^; R2 h& a: E) e$ j8 ^: `2 n
  552.         bp = rbt->palette[i * 3 + 2];
    0 M$ D* T9 ~. }7 P7 ]2 \
  553.         distance = compute_rgb_distance(r, rp, g, gp, b, bp);% f4 @$ n0 c1 X# U1 Q. E1 V
  554.         if (distance < nearest_distance)( j& d- e" L* ~( @+ v
  555.         {
    7 a# \1 Z' [! [
  556.             nearest_distance = distance;
    7 I1 S3 h1 A9 U$ l: f2 T- }
  557.             palette_index = i;
    . o8 h' J; e6 u) G$ @9 \6 o
  558.         }: w( |( n/ I# L' |3 C
  559.         /* can't get closer than 0; break early */4 M7 @0 K7 |+ h/ f
  560.         if (distance == 0)' h0 j2 @, q& r' L& q
  561.             break;2 n# t% ~' w' I) y6 l) m
  562.     }
    / U6 G" Q9 V1 O' N& H4 W2 u  A! z

  563. 8 v5 O6 w9 I$ W3 B. J
  564.     return palette_index;' C+ G' O: P+ L; \4 p
  565. }
    2 @9 {" f& T+ v' h- B+ i1 p

  566. : p9 |& N! V3 ^4 F0 Y
  567. static void subtitle_frame(rbt_dec_context *rbt, uint8_t *frame,8 q8 ?+ y) X) I& h- z
  568.     int width, int height, int timestamp)! S5 b$ G8 F+ i/ ~; ?% u
  569. {
    / R( ^' S3 T- f( S, X/ _) Z
  570.     ASS_Image *subtitles;3 w2 W% o  V/ V
  571.     int detect_change;" q; C: D& T- X7 B; Z( V' D
  572.     uint8_t subtitle_pixel;  Z, L8 o: u# r5 B4 |% L
  573.     int x, y;
    : _# g6 n& o2 V, c3 T7 G4 J; T2 Y
  574.     uint8_t *frame_ptr;! I1 H3 b$ y- u8 c) C7 y0 `6 l
  575.     uint8_t *subtitle_ptr;8 p9 N6 q% _9 G$ U0 N8 P5 `

  576. 3 T+ G' d7 x# R0 g( E
  577.     /* ask library for the subtitle for this timestamp */0 @& E/ s4 Z3 v: u) C- f% k+ B
  578.     subtitles = ass_render_frame(rbt->ass_renderer, rbt->ass_track,) c3 M& V% ~8 D: u3 s
  579.         timestamp, &detect_change);
    2 a5 p4 V4 ~0 T. d1 U$ \; t
  580. $ y& R* @5 d+ X$ [
  581.     /* render the list of subtitles onto the decoded frame */
    1 a! C. f" L- U. E! p
  582.     while (subtitles); b+ c/ j/ N2 a6 Y6 g' f
  583.     {
    ! x. \& u6 z6 X$ L0 v. `1 }
  584.         /* palette components are only 6 bits, so shift an extra 2
    ; h  X* j- t1 C2 G1 x
  585.          * bits off each component */6 S3 v8 R. M) }
  586.         subtitle_pixel = find_nearest_color(rbt,
    : k1 ~) i2 Y; S& l
  587.             (subtitles->color >> 10) & 0xFF,
    7 C8 a0 N' Z. k& ~; K0 m
  588.             (subtitles->color >> 18) & 0xFF,
    ( F, j0 P) j, K) }1 {
  589.             (subtitles->color >> 26) & 0xFF);
    + m- b8 d2 o! m, V" |+ v2 k
  590.         for (y = 0; y < subtitles->h; y++)
    3 v. Q9 |* C) n, |# T9 R
  591.         {8 B8 H0 e. z% B- |1 a9 f1 b* P
  592.             subtitle_ptr = &subtitles->bitmap[y * subtitles->stride];& m% m0 Z, ]3 F3 R
  593.             frame_ptr = &frame[(subtitles->dst_y + y) * width + subtitles->dst_x];
    8 H$ Y  A6 q( l0 t, m
  594.             for (x = 0; x < subtitles->w; x++, frame_ptr++, subtitle_ptr++)3 F% M, s( w8 e  C6 I( @' O  Q) ]1 a
  595.             {
    ( P1 Z1 ~) m, b+ G6 J; n
  596.                 if (*subtitle_ptr >= SUBTITLE_THRESHOLD)
    3 E) `1 ]/ p# l" u8 y8 \
  597.                     *frame_ptr = subtitle_pixel;8 y, L3 z; _* G7 A
  598.             }' d+ L5 Y5 s$ d% B/ V' z
  599.         }
    ' T1 E4 F* O7 G4 X  `
  600.         subtitles = subtitles->next;: T9 A9 F* J9 B- u5 [8 n1 X6 Y5 M
  601.     }2 c1 Q0 k. f; r
  602. }
    ; M6 V% E. s* E. i! O
  603. & g1 S; ]# ~1 P$ K
  604. static int copy_frames(rbt_dec_context *rbt, FILE *inrbt_file, FILE *outrbt_file,/ v9 R/ Q: G7 U+ T4 P2 @" l% V
  605.     int origin_x, int origin_y, int window_width, int window_height)7 D6 _  C8 Z' A  |# o
  606. {
    + N) [* v; f' q$ L% g! z' z& H
  607.     int i;
    0 E/ ?8 {! k# D4 f& q7 a7 O
  608.     int j;
    # _- L# N' U1 u" @
  609.     int scale;- E/ \, k6 }/ q" W' c
  610.     int width;
    9 v2 f9 O" J( n# h
  611.     int height;
    ) r9 t1 q$ {  f6 X
  612.     int max_width;
    4 l/ r9 G0 l# |8 {2 ]$ I! I
  613.     int max_height;4 j% y' P% ^; f* o( f, Q/ e3 Z
  614.     int frame_x;3 B! `4 h1 s  x
  615.     int frame_y;, J  J, k+ [) \+ i: g- R
  616.     int fragment_count;
    6 t1 k  _; Q9 c  B; Q
  617.     int decoded_size;
    4 N: ]/ V' @% {
  618.     uint8_t *decoded_frame;1 ]  C, d( V1 B* i* m. g6 s
  619.     int fragment;& e: B; H0 ^# N* [* V5 x! H
  620.     int fragment_compressed_size;
    ' ?1 K/ v& h* q" C7 ?3 G  `
  621.     int fragment_decompressed_size;$ ^% I4 A0 b. i
  622.     int compression_type;2 L: u* l, c) J# ?: v8 s
  623.     int index;) I. L6 |) g! q9 K0 w
  624.     int out_index;
    5 O5 D' K$ [, ]
  625.     get_bits_context gb;
    ( D+ {) {* Z5 R  g/ g
  626.     int frame_size;
    ( Z! z/ c$ G' j$ `; ~0 T" T
  627.     int video_frame_size;
    ( r/ t; F6 _6 n, I0 {1 m
  628.     int audio_frame_size;, W6 }* P. G% s5 r. l
  629. & X. O, z  p3 s% E
  630.     int back_ref_offset_type;
    + z5 H# h! V2 _+ D. Z+ F5 G! ?( d
  631.     int back_ref_offset;
    3 q" \1 Y" r) p8 U* w6 `
  632.     int back_ref_length;
    - @, a% u* I* R  U9 u7 ~2 \; r( U
  633.     int back_ref_start;; X* ]! q! r* I& Y0 Z$ }, ~. G# a5 L
  634.     int back_ref_end;
    1 D" k5 e: ?7 }4 D; C0 u( c# k

  635. , r  w8 B, q% D' o- X
  636.     uint8_t *full_window;2 L+ a0 v  ?+ x4 z& u: R/ h
  637.     int full_window_size;
    & g7 Q: y# R0 |9 q
  638.     int y;
    # T, x6 q; U+ G9 c% H
  639.     int window_top;
    ) G2 d. a  d" D' e% p
  640.     int window_bottom;
    % v4 p  Y/ s( Z3 ~0 x/ ^: r& W
  641.     int window_left;
    0 M$ ?8 v4 |. b& a& s+ w
  642.     int window_right;& V9 m2 r# q% m
  643.     int window_size;. K1 e& e3 Q' Q
  644. 6 V; c  V) E1 n. y5 K- q
  645.     char filename[30];
    . d" S$ E, m% z  L/ ~
  646. ) W, h7 v8 ~) e, O- G7 G1 _
  647.     put_bits_context *pb;* T6 J* d3 C) U1 v! H
  648. & F6 g4 H4 `8 K; v: G
  649.     full_window_size = window_width * window_height;; ~$ f3 s# E% y5 `, J% {+ S
  650.     full_window = malloc(full_window_size);# Q1 K4 G9 [, ]/ W
  651.     pb = init_put_bits();' e$ e1 S0 n% c' \; a8 t: u
  652. / m2 l( e& o5 w2 c9 a- r
  653.     max_width = 0;/ ^, w: Z/ O$ _8 Y
  654.     max_height = 0;$ k8 F, a6 M/ U6 n" e; C, N

  655. 2 \  c1 ?0 D+ [4 y4 w9 b
  656.     for (i = 0; i < rbt->frame_count; i++): Q' r; F8 o+ j. D
  657.     {1 z8 D6 ^- J  r  t# N: j6 t/ g
  658.         /* read the entire frame (includes audio and video) */! a1 x" ~7 ^$ s9 T( ]( j6 ?
  659.         frame_size = LE_16(&rbt->frame_size_table[i*2]);9 Z/ A8 ^- G( j* z
  660.         video_frame_size = LE_16(&rbt->video_frame_size_table[i*2]);$ z* e8 c8 a3 d3 L- j5 \, d
  661.         audio_frame_size = frame_size - video_frame_size;" _( V! e; r/ A; t
  662.         if (fread(rbt->frame_load_buffer, frame_size, 1, inrbt_file) != 1)+ p; q; d- C! H
  663.         {% I* C: _; j8 ?, n! [/ {
  664.             printf("problem reading frame %d\n", i);
    # i$ g+ X- ^- n$ V4 c8 B, Y
  665.             return 0;
    # M; j2 h# m; c7 g
  666.         }
    " l) J, @" ?- o
  667. 3 X2 J8 N' o" E- e  i& G$ J% k
  668.         scale = rbt->frame_load_buffer[3];
    : j5 s; U$ E6 u4 E9 g: ]# S  H
  669.         width = LE_16(&rbt->frame_load_buffer[4]);7 J2 n* B' @4 p" n. i6 w7 i
  670.         if (max_width < width); X9 ~& M! P) ]5 u+ W
  671.             max_width = width;
    . L7 W0 j9 ?+ O2 f* M, O5 S4 D* V9 w
  672.         if (max_height < height)! W2 H* h8 L' d9 ?7 e/ ]% b  E# Y
  673.             max_height = height;0 F! i3 d, E/ ~& k1 f/ J
  674.         height = LE_16(&rbt->frame_load_buffer[6]);
    " s( D% s- R( |* [( C7 C
  675.         frame_x = LE_16(&rbt->frame_load_buffer[12]);4 R* g) F9 X0 R( u8 H# G
  676.         frame_y = LE_16(&rbt->frame_load_buffer[14]);
    - D8 d+ J$ P: z
  677.         fragment_count = LE_16(&rbt->frame_load_buffer[18]);1 e, |# A5 h3 U2 ~# a( A7 T2 |
  678.         decoded_size = width * height;
    ' R* ~& A4 O% N( m/ s
  679. 4 D/ _: s6 a% u/ c2 b4 }9 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);
    0 U( {2 T+ T: F  W1 T5 y
  681. 2 D( ?. V7 e1 b  Z& D& l4 d2 V9 f
  682.         /* decode the frame */
    ; |2 U* f/ _  {/ q$ v, l
  683.         decoded_frame = malloc(decoded_size);( Q- G! k/ ?+ F- o0 @# ]7 e7 h& ?" S
  684.         index = 24;# S# o3 Y' o9 l1 F7 W7 u
  685.         out_index = 0;0 ]# W3 \- T% ^; \6 q, I+ A
  686.         for (fragment = 0; fragment < fragment_count; fragment++)
    1 n( T; v! {9 ~4 f
  687.         {0 ^- T' z5 }0 ^# z
  688.             fragment_compressed_size = LE_32(&rbt->frame_load_buffer[index]);
    0 H6 G! Y2 B# l' `, h/ X! U
  689.             index += 4;3 |% P8 V0 \6 R8 V
  690.             fragment_decompressed_size = LE_32(&rbt->frame_load_buffer[index]);( Y# z+ ^! _9 X; N' _4 X
  691.             index += 4;
    4 t& F  [- G3 t
  692.             compression_type = LE_16(&rbt->frame_load_buffer[index]);- a6 z) ]3 Q8 M- B, Y
  693.             index += 2;+ r3 w' E% s/ a* Q" r

  694. 3 X( {: ?- N2 @
  695.             if (compression_type == 0)
    ' t$ e' _, @/ K9 f0 S
  696.             {
    * B3 Y* j( C& h: P9 p- ]
  697.                 init_get_bits(&gb, &rbt->frame_load_buffer[index],! H  ]# q. n, X$ q7 [' O" Z
  698.                     fragment_compressed_size);1 }4 r) o, v+ E9 R( `4 ~

  699. 1 U6 U  Z9 H0 @7 q' ~6 \. }
  700.                 while (out_index < fragment_decompressed_size)
    3 `" ^* H0 f4 V+ @" }6 w: |
  701.                 {( S) ~* v: l5 H2 k& e/ m, C
  702.                     if (read_bits(&gb, 1))
    8 n) B% J( V2 E8 J/ b* H) q! s
  703.                     {) t  B0 r. w; J# J/ p& [
  704.                         /* decode back reference offset type */7 A) s& Z  I3 `, l/ }7 `  f- S$ ?
  705.                         back_ref_offset_type = read_bits(&gb, 1);2 o. Y/ w& E+ P* P

  706. ; i5 _  n2 |5 r9 |/ x5 `
  707.                         /* back reference offset is 7 or 11 bits */. \# P/ c7 [8 P8 a0 o
  708.                         back_ref_offset = read_bits(&gb,
    9 ?" v; b4 h7 l7 b! r. _. m* G8 ]
  709.                             (back_ref_offset_type) ? 7 : 11);
    9 L6 z5 X7 y  f9 S, j7 |# M

  710. 1 c+ H, }# {, m2 }
  711.                         /* get the length of the back reference */, V' x- l3 p- A: x0 B6 u
  712.                         back_ref_length = get_lzs_back_ref_length(&gb);
    % P6 a2 E: G$ \5 c' a1 V
  713.                         back_ref_start = out_index - back_ref_offset;
    % f4 U- y; H7 H$ P
  714.                         back_ref_end = back_ref_start + back_ref_length;
    * ^5 F" w, M; H% ^" c4 W( f

  715. 4 W# u& u8 m& m7 H9 w( a
  716.                         /* copy the back reference, byte by byte */# P/ y; E. f) A8 Y
  717.                         for (j = back_ref_start; j < back_ref_end; j++)
    : Q$ v6 T2 t* p" G
  718.                             decoded_frame[out_index++] = decoded_frame[j];' f1 g- [  p7 C
  719.                     }8 n3 I" J% m1 G4 ]- ?  a- p
  720.                     else/ o% e# y( D  ~6 m& z2 ]
  721.                     {
      p& I/ c. _' ?( A: i/ z
  722.                         /* read raw pixel byte */) d' l5 m7 {8 ]: U) E
  723.                         decoded_frame[out_index++] = read_bits(&gb, 8) & 0xFF;; m. u6 F6 z; o; e6 |
  724.                     }
    % s, ^# Z6 m+ B( B+ ~
  725.                 }5 r% Q5 I1 I- [5 P/ P
  726. # h1 W- d! p" \
  727.                 delete_get_bits(&gb);
    % f  f. e' z/ c1 L. @" \+ F
  728.             }
    $ ?# x' I$ m; i
  729. 1 k) o: {/ e& a
  730.             /* next fragment */
    8 `3 M1 o6 {" ^% H# u: Y  U
  731.             index += fragment_compressed_size;
    . x) X8 I% `9 ]: U
  732.         }
    , t* q) F; b8 P4 C; P

  733. 9 q7 S3 c0 i9 ^! a
  734.         if (rbt->dump_frames)  j  [# ?5 T* s! C% y1 G  h7 d/ @5 G
  735.         {. q" e  k$ X3 m8 }, G& V
  736.             /* dump the original frame */
    4 S# k* U# i$ t& z* G* d
  737.             sprintf(filename, "original-frame-%03d.pnm", i);
    ' M( T* g$ H; N6 o- T
  738.             dump_pnm_file(filename, rbt, decoded_frame, width, height);
    6 l! {6 L/ S: ]4 N6 x+ M
  739.         }
    1 U; p* a7 K' K6 _+ H. V# `2 }
  740. : W( C2 Q- D; ^$ f6 s# {
  741.         /* transfer the image onto the frame window */! E6 O' w6 T: v4 d3 ^& u$ X* \
  742.         memset(full_window, 0xFF, full_window_size);
    # S, y4 D2 x% e. c
  743.         index = 0;) X/ g& v( A  K' K
  744.         for (y = 0; y < height; y++)9 v& k6 I- }! j+ M; P: [. x* {
  745.         {1 q5 W: x5 [- i: H6 Z0 e" y
  746.             out_index = window_width * (frame_y + y) + frame_x;
    0 ?" y! y% D) @- B- \
  747.             memcpy(&full_window[out_index], &decoded_frame[index], width);7 ]' `6 {! }% |" {
  748.             index += width;
    ' p$ W6 a" U: x6 [. |
  749.         }# [7 a/ m" v, w- D8 D7 c3 S! z

  750. 9 w) J. v4 \0 K5 o6 T# Y/ j8 o8 @
  751.         /* write the subtitle */
    2 |6 J% Z/ T  p6 B
  752.         subtitle_frame(rbt, full_window, window_width, window_height,9 ^' V. D1 n8 Z( [
  753.             i * MILLISECONDS_PER_FRAME);+ V8 O- d& |) {/ b& C

  754. . U0 B4 }8 [( ^0 `
  755.         /* figure out the smallest change window */
    ! s/ N  d# i1 o5 i
  756.         window_top = frame_y;6 R+ B! F% `6 p! K# @! I) \8 c4 I( V
  757.         window_bottom = window_height;
    + ?, o: O+ J) g  Z: |
  758.         window_left = 0;1 Q3 E  q# A+ e4 ~/ ]: k
  759.         window_right = window_width;- L& O( Z2 u0 y2 T: e
  760.         window_size = (window_right - window_left) * (window_bottom - window_top);
    ) \( g% M5 O8 A7 u  I6 m: L
  761. - G+ O0 K/ n8 ]6 g+ r0 a0 ?
  762.         /* compress the frame */# A0 e1 s2 u' F) T( n
  763.         reset_put_bits(pb);( O5 d6 Y* n8 r# J4 S6 N; l
  764.         compress_window(pb, full_window, window_width, window_top,
    4 I/ L2 a$ z: E4 O" B9 x
  765.             window_bottom, window_left, window_right);; I: v8 |& H- P7 ]0 `, e% ~

  766. ) {! p9 d8 X9 x! N7 ]. j
  767.         if (rbt->dump_frames)
    # L" k6 C  B& k2 ^! k/ I
  768.         {) `8 w2 C$ m; \7 [0 b7 l
  769.             /* dump the frame plotted onto the full window prior to encoding,
    ( h9 h' X; R% P9 D5 \% }, ^  s
  770.              * with subtitle */
    & `8 Y  c9 e( n4 B* c+ F
  771.             sprintf(filename, "pre-encoding-frame-%03d.pnm", i);7 }9 H$ F8 l% ?! ]+ o' f
  772.             dump_pnm_file(filename, rbt, full_window, window_width, window_height);& m) l. J- ~/ v$ q5 z
  773.         }
    . a% ]- g  |% R$ X, c9 i2 O3 ]) N
  774. 9 l3 V# l- Y6 C; g
  775.         free(decoded_frame);
    4 e6 v5 x4 |1 g4 Q
  776. 9 D; }; {* |$ D
  777.         /* update the frame header */1 ]* K( Y+ w0 r$ S0 z- `3 b; n3 U
  778.         /* width */
    9 N. x; _* i) W, u$ q, V, Z
  779.         rbt->frame_load_buffer[4] = (window_right - window_left) & 0xFF;7 ^: p6 l+ e' |* k: j2 [4 P
  780.         rbt->frame_load_buffer[5] = (window_right - window_left) >> 8;' w" V# a' E% N9 w4 g9 r/ n0 m* N8 w, f
  781.         /* height *// f/ X0 v1 e2 V$ I: N4 u8 K1 t7 V
  782.         rbt->frame_load_buffer[6] = (window_bottom - window_top) & 0xFF;! m0 H3 J- m# J% t
  783.         rbt->frame_load_buffer[7] = (window_bottom - window_top) >> 8;- z2 \- n4 |, E8 x, l0 u  w+ S
  784.         /* origin X */
    ) g% J5 F& w8 K& S, y  _1 P& F
  785.         rbt->frame_load_buffer[12] = window_left & 0xFF;: j6 ^0 A2 w: O$ `, `
  786.         rbt->frame_load_buffer[13] = window_left >> 8;
    ( T5 E) [* B- f5 f, n
  787.         /* origin Y *// j! L$ B% a6 p+ p. }! ?
  788.         rbt->frame_load_buffer[14] = window_top & 0xFF;8 v/ q/ z7 Y0 J$ h4 t
  789.         rbt->frame_load_buffer[15] = window_top >> 8;$ H+ s4 F* K5 N9 G+ d
  790.         /* fragment payload size */
    + V, R+ I2 O+ H+ o" y' Y, D
  791.         rbt->frame_load_buffer[16] = (pb->byte_index + 10) & 0xFF;  C% s& u6 Q' C: v& K* y" ]. {
  792.         rbt->frame_load_buffer[17] = (pb->byte_index + 10) >> 8;' Q) ~/ i: X% g. }
  793.         /* fragment count (1) */
    , }' q- S6 o. `" \/ y% m
  794.         rbt->frame_load_buffer[18] = 1;
    : z3 n& ^- [9 w; y/ A
  795.         rbt->frame_load_buffer[19] = 0;
    5 ?: E4 L$ @7 R; T0 o9 w6 J- Z+ ^
  796. " P) _# R+ l* {% n! o" D) D
  797.         /* update the fragment header */' B8 s7 x: ]5 G9 x
  798.         /* compressed size */2 y3 p1 B- z. I( X; W$ X
  799.         rbt->frame_load_buffer[24 + 0] = (pb->byte_index >>  0) & 0xFF;
    $ s' b% F( {% h3 n: {  p
  800.         rbt->frame_load_buffer[24 + 1] = (pb->byte_index >>  8) & 0xFF;; r/ H8 q% D3 @
  801.         rbt->frame_load_buffer[24 + 2] = (pb->byte_index >> 16) & 0xFF;2 t7 c' {% ~& Q3 l0 H
  802.         rbt->frame_load_buffer[24 + 3] = (pb->byte_index >> 24) & 0xFF;( S- H. |2 q9 M8 [, u+ I( U
  803.         /* decompressed size */
    + B9 A; ~, j, O" D- g
  804.         rbt->frame_load_buffer[24 + 4] = (window_size >>  0) & 0xFF;
    & I! d  p' o) x4 D: v
  805.         rbt->frame_load_buffer[24 + 5] = (window_size >>  8) & 0xFF;. |0 }3 t( K. m8 ?  Y* Q
  806.         rbt->frame_load_buffer[24 + 6] = (window_size >> 16) & 0xFF;; K! S/ p1 e  n: R. }# y  q, f
  807.         rbt->frame_load_buffer[24 + 7] = (window_size >> 24) & 0xFF;8 X/ G$ i# t) [* W
  808.         /* compression format 0 */  F5 J0 E5 r0 |# B: \+ I7 }  \5 Q
  809.         rbt->frame_load_buffer[24 + 8] = 0;& G6 d- |2 R  u7 c3 L# ^& A
  810.         rbt->frame_load_buffer[24 + 9] = 0;! Z& e* g6 }( G* o3 H) E; O

  811. ; l- h# n( f7 ^* }& F% ~& S
  812.         /* write the 24-byte frame header and the 10-byte fragment header */
    ' j$ G7 b- u5 e
  813.         if (fwrite(rbt->frame_load_buffer, 24 + 10, 1, outrbt_file) != 1)
    " D0 s5 r! w8 i8 J9 J4 \5 G
  814.         {6 a% o% L+ ?% \8 s0 |) e7 u
  815.             printf("problem writing frame %d\n", i);
    0 J& d! A6 L7 O7 ~/ j7 l2 j
  816.             return 0;
    ) |3 g1 N) O$ Q' A) _. S) s
  817.         }
    + r. p5 |; k9 n# d* k9 @& E- s& \

  818. 7 e) ~# v7 C; Z
  819.         /* write the new compressed frame data */
    ( X/ p; c0 I' [
  820.         if (fwrite(pb->bytes, pb->byte_index, 1, outrbt_file) != 1)
    * d8 g6 i4 T- ~) z
  821.         {
    # F0 O# d% U0 a3 K3 C
  822.             printf("problem writing frame %d\n", i);
    6 {$ j  d* e1 ?5 P0 E$ |
  823.             return 0;5 T1 U$ |  m& h  K3 T, r
  824.         }. A& Z" R: K, v& n. O
  825. , x2 Q( P( K4 }8 I1 k, l
  826.         /* write the audio data */
    7 B  g( r4 W3 K
  827.         if (fwrite(&rbt->frame_load_buffer[video_frame_size], frame_size - video_frame_size, 1, outrbt_file) != 1)
    6 F1 ^, f( `) }" d7 _' [
  828.         {
    & F; E, r3 g" j/ P
  829.             printf("problem writing frame %d\n", i);
    - a+ h- O( G! S3 y/ f
  830.             return 0;
    : F- Q' U8 n3 \- Q2 y" y
  831.         }
    ! \  B! O4 n8 j" [  s4 v2 Z

  832. * o% X4 P. P5 ?7 ~" n& n* E
  833.         /* update the table entries */
    " Y  ~6 {! F8 U& e  P% D
  834.         video_frame_size = pb->byte_index + 24 + 10;* |/ }5 |! A* H  p$ F5 f
  835.         frame_size = video_frame_size + audio_frame_size;. T+ H! `' ~5 I
  836.         rbt->frame_size_table[i*2+0] = frame_size & 0xFF;
    . n8 f* k- m, @
  837.         rbt->frame_size_table[i*2+1] = frame_size >> 8;4 X' l8 R' S8 X; f+ ?+ Y
  838.         rbt->video_frame_size_table[i*2+0] = video_frame_size & 0xFF;
    6 ]& n$ C5 i" h1 v: J, P/ [+ ^6 S
  839.         rbt->video_frame_size_table[i*2+1] = video_frame_size >> 8;
    1 I. |* A- i  g' U) M& n6 q$ {* t
  840.     }$ R( y  U2 {$ i

  841. - C: m" Q# V' D
  842.     printf("maximum dimensions seen are %dx%d\n", max_width, max_height);( ]+ j( J7 U0 N: {

  843. - W8 N" |  t" G
  844.     delete_put_bits(pb);2 |) K: F7 A3 h2 j7 e
  845.     free(full_window);
    # G" z6 X. f8 S1 y' m4 z& m# [  ?

  846. : P& ^- t. ?& C8 L+ G; b
  847.     return 1;
    ! N) [7 }) X5 m# \4 f0 x; `3 ^
  848. }% H& d0 y4 G, b. `+ y# A. ~

  849. 7 I' K, _% z& ~
  850. int main(int argc, char *argv[])
    5 U- p( n, l( O- n! J) {2 h: x
  851. {
    6 a7 w! e) s; U: s3 h- D
  852.     char *subtitle_filename;/ v. I: Y: G0 m1 }
  853.     FILE *subtitle_file;! Q3 b' c+ z+ b+ U& M3 u
  854.     char *inrbt_filename;
    / q! m* l, O4 G6 C
  855.     FILE *inrbt_file;9 O9 c4 G9 Q3 |0 A8 p& D/ {: z
  856.     char *outrbt_filename;
    . U* O7 R% H8 H0 }
  857.     FILE *outrbt_file;
    1 o; A" Z% j7 t
  858.     rbt_dec_context rbt;
    5 ]4 J' r# u- Y8 [  I2 Q& z
  859.     int origin_x;4 @/ ~8 s9 o. s1 M0 m$ B* M
  860.     int origin_y;" R2 j& x! a( ~5 e1 E' t
  861.     int window_width;
    ( L, L" M1 n& a7 q
  862.     int window_height;
    ( g8 H- a! W5 v. N" x: Z% |- Y

  863. 0 [& a5 v+ {  t0 w2 }
  864.     /* testing the bit functions */* ^  _" D1 H1 e7 N" p. W9 p' N4 N. R
  865. #if 0. Z& P3 m% \+ `! d3 K  A: e) }* u( o
  866.     int i;
    , Q0 V5 \) {( r% n9 [9 q
  867.     uint8_t bytestream[] = { 0x55, 0xAA, 0x00, 0xAA, 0x55, 0x77, 0xFF, 0x1B, 0x70, 0x8F };
    / n4 e' L/ L) \+ Q
  868.     int bytestream_size = 10;
    4 g, h6 Z+ A+ K9 d2 i) p
  869.     get_bits_context gb;
    / d+ C, h# f: \$ I
  870.     put_bits_context *pb;
    4 x+ ?  j- E  n: {9 [% t
  871.     int bits;
    $ m* l3 I; m) m1 s+ M

  872. / U: ?: L+ t0 h5 d: B
  873.     init_get_bits(&gb, bytestream, bytestream_size);
    % `( r$ K0 R' t+ k
  874.     pb = init_put_bits();& [/ c6 L) i+ m# f$ Q
  875. - i1 r% U  n0 j  U- J& O& h7 v/ ]
  876.     for (i = 1; i <= 12; i++)8 L" }: t7 e2 |9 L% Y; N
  877.     {" L- m* S( W7 v5 ]$ [3 K
  878.         bits = view_bits(&gb, i);
    0 `. j- P, C; p+ J' G2 G' r
  879.         printf("view %d bits: %d\n", i, bits);/ y/ C& L/ ?" V5 Q
  880.         printf("read %d bits: %d\n", i, read_bits(&gb, i));
    ' u$ C9 L8 c2 J9 W* t; E$ z
  881.         put_bits(pb, bits, i);
    9 j) y7 k! l, a& `, m$ A% j9 N, h- \
  882.     }8 c- N/ W# ^% U
  883.     put_bits_flush(pb);! H+ f+ I4 E, y! m
  884. / P( Z" }, J) Y* y# o
  885.     printf("original bytestream:\n");5 T" }; J, n" v' K' {
  886.     for (i = 0; i < bytestream_size; i++)6 n7 E+ k  w1 ~
  887.         printf(" %02X", bytestream[i]);
    3 y. Q5 \0 R3 n$ P
  888.     printf("\nnewbytestream:\n");
    2 l0 T1 ~& N/ {+ h( }* Q% k
  889.     for (i = 0; i < pb->byte_index; i++)
    5 Z0 B6 `. H6 y3 ?) i+ l' H. m
  890.         printf(" %02X", pb->bytes[i]);
    + f3 b, K% w( M
  891.     printf("\n");
    % ]: |2 X9 k+ y2 J2 h( Z! y

  892. 9 B- S* R+ f/ _6 {3 |1 t1 f" e; p
  893.     delete_get_bits(&gb);
    " q7 I  d1 k/ e6 f- \
  894.     free(pb);
    4 P1 d- B. ~( L+ m: i
  895. #endif8 v+ K5 y/ D* {/ [

  896. + R0 P' M9 f: d8 v3 h' t$ b
  897.     /* validate the number of arguments */7 o( K8 j3 c1 I& s) U: W
  898.     if (argc != 8 && argc != 9)
    8 R/ X$ Q% u) ?# K! d$ \7 e
  899.     {
      ~6 @' o4 v/ I* R" `
  900.         printf("USAGE: subtitle-rbt <subtitles.ass> <in.rbt> <out.rbt> <origin X> <origin Y> <width> <height> [dump_frames]\n");+ n3 g; S8 c% n  i" `$ ~
  901.         return 1;
    , T3 j7 N9 U8 _7 ~. L$ u3 v0 J
  902.     }
    % L. n& j* g, z7 e9 k
  903.     subtitle_filename = argv[1];, T% c9 U9 G0 \1 W/ @
  904.     inrbt_filename = argv[2];
    + ^, }6 v; \) z  K
  905.     outrbt_filename = argv[3];. n' D" x! m& S* H6 g6 B3 y; h
  906.     origin_x = atoi(argv[4]);
    2 m6 n# _. g3 Q% K1 J( b  q
  907.     origin_y = atoi(argv[5]);5 f. \& b2 ?) X+ s! i
  908.     window_width = atoi(argv[6]);
    ; T- u0 \# W2 V7 l; R
  909.     window_height = atoi(argv[7]);
    - Q# D( L7 j' P! v1 U
  910.     rbt.dump_frames = 0;
    # [0 W; ~7 r* S' \9 x  g
  911.     if (argc == 9)
    . Q4 t/ K& t$ s5 L/ u0 c
  912.         rbt.dump_frames = 1;
    , p! k0 E; t4 A! B9 M
  913. 0 j2 Q* C3 d; u
  914.     /* verify that the specified input files are valid */
    : Q/ O1 z9 S' T& B2 s
  915.     subtitle_file = fopen(subtitle_filename, "r");+ I% x; c8 P3 ?, F9 Z' [) M: r
  916.     if (!subtitle_file)
    * D9 q# b/ w* X* c
  917.     {
    8 p5 _9 F# N1 V& J; Q7 F
  918.         perror(subtitle_filename);
      H3 n& ?7 @/ l! i
  919.         return 1;
    ; |6 M: D5 m9 R+ y, e# b
  920.     }# f/ Y4 I3 d8 ~! N3 V( Q7 A
  921.     fclose(subtitle_file);
    : L5 Z7 Y; L" _! s/ p, V# V6 D
  922.     inrbt_file = fopen(inrbt_filename, "rb");
    . C" G" Z5 |& D. r
  923.     if (!inrbt_file)
    2 C% L/ m9 `$ E0 w% {% ~3 x2 s  D
  924.     {
    ! d! N/ a2 z  D7 y4 J7 ?
  925.         perror(inrbt_filename);
    # y+ }6 V( n( u
  926.         return 1;" ]1 _; \0 I) Q% J
  927.     }) N/ N; V7 E& v

  928. * U/ ?5 Y" |! t
  929.     /* initialize the subtitle support */: G2 G* Y; e2 y
  930.     rbt.ass_lib = ass_library_init();# l5 g  D: Y% C2 _8 T  S
  931.     rbt.ass_renderer = ass_renderer_init(rbt.ass_lib);$ D) v5 r" S. Y9 r2 K. N8 S
  932.     rbt.ass_track = ass_read_file(rbt.ass_lib, subtitle_filename, "UTF-8");, R4 O: k- J" ]( ?9 h
  933.     ass_set_frame_size(rbt.ass_renderer, window_width, window_height);
    ! d- P. d3 ]# V: D# S% W/ L+ x* \
  934.     ass_set_fonts(rbt.ass_renderer, NULL, NULL, 1, NULL, 1);' x  }& W  i3 b/ ~/ [. K
  935. 0 n7 e# B4 C8 z, F- g& n- a0 i7 g6 Q
  936.     /* open the output file *// @/ z5 {% X' x7 o, b
  937.     outrbt_file = fopen(outrbt_filename, "wb");6 p. y8 j1 X5 o7 e; D
  938.     if (!outrbt_file)
    , k' r5 u, P7 g* `1 d3 W# u
  939.     {0 t$ U- H1 j8 _1 m( f8 h4 r+ g+ u
  940.         perror(outrbt_filename);! f6 C7 n4 H0 S: d% K8 \( _
  941.         return 1;  m6 a7 O  S5 b' f5 V5 j) K
  942.     }& d1 [9 h* R( D' N
  943. 1 j4 d& c( R& o% J) \& J# \& a& q9 x
  944.     /* transfer header from input to output */
    : a" f* }1 c. x- r* `
  945.     if (!load_and_copy_rbt_header(&rbt, inrbt_file, outrbt_file))
    - {- {% e4 {6 U1 K9 }
  946.         return 1;
    & Y+ V+ d* B; W. d* c6 V
  947. : m0 h4 j. w+ R4 D+ U- Z1 ]
  948.     /* rewrite the frames */- T$ Y% x2 E. J/ t
  949.     if (!copy_frames(&rbt, inrbt_file, outrbt_file, origin_x, origin_y,6 F1 U& c, x, ?+ m$ J6 w$ y9 e
  950.         window_width, window_height))
    0 l! S3 o: l& m# z. X8 u
  951.         return 1;
    4 g" d! C' {3 O) l. a

  952. 0 ?* c7 k- b1 p) x
  953.     /* write the modified frame size tables back to the file */' D6 N0 I6 ~! S2 x6 `
  954.     fseek(outrbt_file, rbt.video_frame_size_table_offset, SEEK_SET);
    / y. }; F# d6 m% K* C+ v3 P2 a
  955.     fwrite(rbt.video_frame_size_table, rbt.frame_count * sizeof(uint16_t), 1, outrbt_file);1 x/ @2 a+ u4 J4 H
  956.     fseek(outrbt_file, rbt.frame_size_table_offset, SEEK_SET);
    8 c% x1 a* Q7 W- j  G" M
  957.     fwrite(rbt.frame_size_table, rbt.frame_count * sizeof(uint16_t), 1, outrbt_file);' l" d: C( k" T' {' A7 j
  958. ! x; U6 G; x6 Z! q: @$ K
  959.     /* finished with files */1 t4 }" L( m0 W
  960.     fclose(inrbt_file);, U, ?6 Q' a. f
  961.     fclose(outrbt_file);& L& f; V: w* T: S* Y# O; a8 O
  962. / m3 W1 g- ~' j5 O% x
  963.     /* clean up subtitle library */5 `: P: @8 r! B& ^
  964.     ass_free_track(rbt.ass_track);
    . h* L5 W( p1 [7 T8 {4 I/ o
  965.     ass_renderer_done(rbt.ass_renderer);7 {4 q$ u. g; c8 ?
  966.     ass_library_done(rbt.ass_lib);- Y4 {( j' L: ^; v
  967. % ^7 d* w% k% }" t2 G3 q' G
  968.     /* clean up */  y2 i. R: I8 V$ R5 J2 w2 S
  969.     free(rbt.frame_load_buffer);# N4 g* O! L" r' H. g" q
  970.     free(rbt.video_frame_size_table);  [' K" o( h( n* ~; s7 ]7 E( a* f  m
  971.     free(rbt.frame_size_table);) t! p0 r5 g& X; L/ \% ?' g

  972. 8 }. B% C) ?( h+ s6 \
  973.     return 0;/ x; _4 H( M8 p6 c; W
  974. }
复制代码
, L! A0 W$ Z$ P+ }

8 l( f$ M/ C" C. Y6 u2 M+ J0 C7 Z% m5 E! z  J5 }
* A! a6 `% n/ E- ^" {1 b- q6 Q

作者: soring123    时间: 2009-11-19 11:09
这游戏有字幕吗?
作者: shane007    时间: 2009-11-19 11:38
引用第1楼soring123于2009-11-19 11:09发表的  :; N/ _5 s1 I7 ?) B/ r
这游戏有字幕吗?
5 V/ h5 b+ g- A- q: M) q# L+ x
好像没有字幕,我说的是给视频外挂字幕方式的汉化。
' r  i9 |. N& l- |就像syberia2汉化版下面那行字一样。
作者: soring123    时间: 2009-11-19 17:07
我记得是没字幕的 比较麻烦 都是视频的
作者: shane007    时间: 2009-11-19 17:39
引用第3楼soring123于2009-11-19 17:07发表的  :" E6 N: J+ e# w# D, L
我记得是没字幕的 比较麻烦 都是视频的
7 D  J  b. t6 k9 T) ?. P3 E" }. g; y
给视频外挂字幕方式汉化也许能行。1 H# k! }+ n$ {, s) U  P- X! C
要结合dosbox和代理dll技术。
作者: 宿矢    时间: 2016-7-21 23:33
求汉化啊!
作者: shane007    时间: 2021-1-2 13:50
顶上来




欢迎光临 冒险解谜游戏中文网 ChinaAVG (https://chinaavg.com/) Powered by Discuz! X3.2