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

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

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

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

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

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

本帖最后由 shane007 于 2021-1-2 13:56 编辑 $ z2 j4 v0 I4 v  X

+ B) o2 h6 b/ J& p( I* n& p最近找到了一些和幽魂系列Phantasmagoria 有关的资料,
' Z1 x6 U. Z: p4 o5 K: ?! H* `/ n也许将来可以用于汉化。
) S9 V' Z. O" W5 k8 U) o& K$ v, I( Q' y2 k
和日文版有关的信息4 W: x' _: @$ ~9 i# v6 g
http://anthonylarme.tripod.com/phantas/phintgtp.html5 L/ V, E4 Y; N: G2 p' r& n5 s
. Z7 e" j6 w. n
相关工具
  V6 ~+ g' Z# h7 vhttp://anthonylarme.tripod.com/phantas/phcheats.html* m5 D) O6 M3 }1 N  p$ W1 F
-----------------------------------------------------------------------
0 K' [& z6 Q9 u8 Y2012/1/2  更新/ T& w2 ]% ]3 Y+ I6 K! O* _
关于幽魂游戏的字幕
  B8 k2 B: E" z8 R& UPhantasmagoria subtitles function discovered - ScummVM :: Forums; f. H9 s+ ~+ S* Q( y# a" L) N

* J0 z% Y* ]1 G0 X  O% ?VMD文件% O! K7 m' F9 ]1 B% ^- ~! ~  P1 }# {
Subtitling Sierra VMD Files | Breaking Eggs And Making Omelettes (multimedia.cx)VMD - MultimediaWiki8 q& c/ x9 C2 v) W
) h5 c& {+ }8 u5 h( c
字幕( G( i" M) Y  k1 E* [9 @
Subtitling Sierra RBT Files | Breaking Eggs And Making Omelettes (multimedia.cx)
% v" b& T) }  H( `, N
1 u# C  R: `' s1 bFFmpeg/subtitle-rbt.c at feature/VMD_encoder · multimediamike/FFmpeg · GitHub
4 ~' _6 ]/ h$ }9 P) Z+ M% w
  1. /*
    / g0 E% W! G7 f/ f* Y. ^# x
  2. * subtitle-rbt.c  v8 X! p+ D/ p' W3 X
  3. *  by Mike Melanson (mike -at- multimedia.cx)
    2 U, K0 a$ ^0 Y2 K- ^
  4. *
    7 G% V/ F  ?4 l. B
  5. * build with this command:
    1 N$ b  L. k3 E! ?3 J' m
  6. *   gcc -g -Wall subtitle-rbt.c -o subtitle-rbt -lm -lass4 S8 b" J5 x$ s& g; w: [
  7. */2 n8 j# S$ K0 I4 i
  8. , s4 i: X7 J& N; i7 T0 Z' n+ ~
  9. #include <inttypes.h>
    - b8 u0 _& K( T' Z& u
  10. #include <math.h>
    " b7 P3 ]- O4 V/ {
  11. #include <stdio.h>; \* d: R9 m# t; D
  12. #include <stdlib.h>
    7 B) U/ c& g( p
  13. #include <string.h>
    7 j# u! I& H; v) @7 y

  14. 1 H% d& Y# S/ A4 l$ z. R. a1 r
  15. #include <ass/ass.h>
    9 E/ v. g, j  Z

  16. 9 ^- P, x; e9 |4 Z3 A
  17. #define LE_16(x) ((((uint8_t*)(x))[1] <<  8) | ((uint8_t*)(x))[0])
    : s* V% Z. s$ Y) L0 n7 D* e( r* b

  18. ) A2 P1 ]. u5 ]( R9 t
  19. #define LE_32(x) (((uint32_t)(((uint8_t*)(x))[3]) << 24) |  \
    + w: d- z) Y7 x5 f* Q* Y! a( i
  20.                              (((uint8_t*)(x))[2]  << 16) |  \
    % a% l: o, }2 Y: ~1 s, E
  21.                              (((uint8_t*)(x))[1]  <<  8) |  \) D& Q7 c5 |- s3 a
  22.                               ((uint8_t*)(x))[0])
    0 j' R+ Q- p7 {# ]2 A7 f* h0 r' }6 y

  23. ( A, L; X/ ?  K* u2 v) B
  24. /*********************************************************************/" v9 b& ]7 D& O6 ?% O

  25. 9 @, v* S) c7 A; n2 D( \: T
  26. /* Bit reader stuff */* B4 Y" T7 v- l: \2 J8 ^( n$ q& r

  27. ) T8 K3 r; j- m& X, ]9 I( _! m0 j
  28. typedef struct
    5 U+ N8 _6 f" D
  29. {# \. P4 \' ~5 ]6 H# L: `
  30.     uint8_t *bytestream;
    " r' ^1 h  V) Q, G: N3 w* `  Z
  31.     int bytestream_size;/ I) h/ y# `! c# e$ i* _
  32.     int index;8 S2 o" X' y4 W: U) `
  33.     uint32_t bits;7 Q% C& z1 k7 c5 n, g- X4 Z; W# V
  34.     int bits_in_buffer;
    4 G& p; A" a1 [% ~
  35. } get_bits_context;
    1 Z1 Q0 c. S/ D# _0 y7 x$ T' G
  36. . r; n+ i8 a' M0 z: T! S
  37. static inline void reload_bits(get_bits_context *gb)
    / f: p( V1 J+ E, B3 x. o6 x. S
  38. {
    ( n- s% C% Q. G  V4 t1 W
  39.     while (gb->bits_in_buffer <= 24)
    7 f/ O* C$ U- S
  40.     {
    , u) N+ N) H! {  R+ f. P5 ]6 Z% h
  41.         if (gb->index < gb->bytestream_size)
    0 }( `* x! R8 Y5 ~0 J7 T7 @
  42.             gb->bits |= (gb->bytestream[gb->index++] << (24 - gb->bits_in_buffer));
    6 ^/ {  }3 f& f7 |7 P
  43.         gb->bits_in_buffer += 8;0 }+ b$ s1 V, |
  44.     }( w" s( m  r$ R
  45. }+ Z  \: D0 P; X$ `* R6 {4 _
  46. + B( T3 q& z, y$ v
  47. static void init_get_bits(get_bits_context *gb, uint8_t *bytestream, int size): v( H0 N, j1 |0 a" U+ K
  48. {
    2 m5 X4 ~- Y7 }- r; q
  49.     gb->bytestream = malloc(size);
    8 F8 p" Q" m0 x* C/ t. w
  50.     memcpy(gb->bytestream, bytestream, size);
    8 `  [4 Q1 [. [# ?; q, q8 B
  51.     gb->bytestream_size = size;
    & C8 ~- q3 [& M) |  d  G3 d6 H+ K
  52.     gb->index = 0;
    & @- G5 i$ T  F1 t( e
  53.     gb->bits = 0;8 m1 n( J" n# \- W. R% T! p2 X
  54.     gb->bits_in_buffer = 0;
    9 v7 w) x6 l3 A# a* L- Y" e  n

  55. + n& f. V9 W5 o6 B5 N8 Q* e
  56.     reload_bits(gb);- r5 s; c- o) z7 _5 T$ Y
  57. }
    8 }$ _9 R. P  ]3 j
  58. # i% y! U# g3 c+ _
  59. /* read bits without consuming them from the stream */* f9 `$ `, E1 D# u
  60. static int view_bits(get_bits_context *gb, int count)" b, x3 t# L  F" L1 m
  61. {
    4 L9 x" C, g) {% u) k# v
  62.     if (count >= 24)# ~! A$ X1 B- X6 i' A; ]2 ~
  63.         return -1;
    . m( v* i, w/ H
  64.     if (gb->bits_in_buffer < count)
    ; Z7 _% `6 w; `) S( ^$ E
  65.         reload_bits(gb);
    2 \% E. v; ]: Q  _( C
  66.     return (gb->bits >> (32 - count));& c8 x; S, a) @5 K
  67. }7 f2 Q( ^$ B5 T- R6 b* l1 C* Y
  68. 1 H& z' }' c( ~5 t/ j
  69. /* read and consume bits from the stream */
    * R" L" N5 U8 C: u2 S. m2 H+ m1 h
  70. static int read_bits(get_bits_context *gb, int count)
    & Q. ^' @6 M. D* J' Y
  71. {7 @' E4 K) b5 F% O5 x* ~+ F( Z8 d
  72.     int value;
    9 C6 Q& _( L3 E5 g1 _$ q4 y
  73. , S; i$ i1 M8 G9 r2 p8 U) c
  74.     if (count >= 24): S' Y- g5 C- x5 W; G
  75.         return -1;
    8 ~6 t# M7 Q- S8 z! \

  76. ! X5 D4 [5 B0 K1 g. _, Y9 R
  77.     value = view_bits(gb, count);  E: V" V5 w- p& m1 u+ W, `
  78.     gb->bits <<= count;6 C9 f5 i) L) |7 G
  79.     gb->bits_in_buffer -= count;; y4 [; s  B  q; V" T, S, l

  80. $ G* S( `# E6 i
  81.     return value;
    & N4 }$ V' `+ V' D, I
  82. }, M& Z' J8 J' i& m; s
  83. 2 \5 o  T9 U* C  O& p
  84. static void delete_get_bits(get_bits_context *gb)
    2 K7 a0 j1 w# h$ |6 Z* K6 H
  85. {
    * _8 Y+ X: g' P% y! k
  86.     free(gb->bytestream);
    ' C9 L2 E- v7 p0 t. {/ {4 |
  87. }
    6 a  B' X1 R& @7 M. f: p; C9 }
  88. 2 a3 K0 W4 H/ e7 P) ?
  89. /*********************************************************************/
    . l# u" x! j) |$ ~; [; P6 s" J
  90. ; H5 t# L6 B/ I" N: |
  91. /* Bit writer stuff */
    " E+ E/ Q% W$ K* ^* x9 ~! T
  92. * }/ q$ V! G& R+ @
  93. #define MAX_PUT_BITS_BYTES 63000, B& M- v' a; ?3 W" F
  94. typedef struct, O# v+ h8 K$ U
  95. {
    : {. j7 |/ W* D
  96.     uint8_t bytes[MAX_PUT_BITS_BYTES];) c* k+ T- ?% a1 Y' ]# k
  97.     int byte_index;
    0 |& q% n$ r. {7 I7 V6 `, \
  98.     uint32_t bit_buffer;
    2 X* [7 I. }" Y& p% e: O
  99.     int bits_buffered;
    * D4 |  j" F! A4 j* e$ x
  100. } put_bits_context;  b' H) U2 @9 `/ b( [
  101. 2 E6 W  ^8 y" E6 f  U# I8 t( Y
  102. static void reset_put_bits(put_bits_context *pb)
    8 t3 b/ d1 Y. s2 P: r0 ?
  103. {+ d0 a3 Z* d/ z* u
  104.     memset(pb->bytes, 0, MAX_PUT_BITS_BYTES);2 [; N" D, T3 v- m+ s. x4 x
  105.     pb->byte_index = 0;! W. `) b7 D2 j5 t1 U
  106.     pb->bit_buffer = 0;6 D: H. Y% o7 s4 h
  107.     pb->bits_buffered = 0;
    # d7 @. n9 M9 |7 V' `2 {
  108. }
    ' b3 ^) [7 r1 M/ c: b- i
  109. ) n* ]2 A: }9 _# x8 I
  110. static put_bits_context *init_put_bits()
    4 l% R4 `* h/ P  _" ]; T6 x' S: t
  111. {% T& G7 }7 a! d; A
  112.     put_bits_context *pb;
    0 r& b" m8 j3 s* i  k
  113. 5 T+ y( N& |2 N/ g9 _
  114.     pb = malloc(sizeof(put_bits_context));
    , ^& `) Z) f; f, B; b7 ~. N
  115.     reset_put_bits(pb);( ?+ D! c: }* L) G
  116. # T4 {( b' u/ j' w
  117.     return pb;5 e1 W( o/ G" ]( e
  118. }8 _* {! U2 W7 i7 O/ w# M* ^
  119. $ c0 y" G6 e- k2 \# t/ ], h4 J
  120. static void put_bits(put_bits_context *pb, int bits, int count)8 J% }9 c+ I8 e- l; Z/ h9 k5 Q
  121. {' W2 F2 V4 {1 n+ [( z
  122.     pb->bit_buffer <<= count;
    , {: s1 w* G# y! {6 |
  123.     pb->bit_buffer |= (bits & (~(0xFFFFFFFF << count)));4 B8 K4 `7 C* r. e( a8 D
  124.     pb->bits_buffered += count;
    8 c: L, K3 M; r: ]/ V
  125. * o: K6 r( _4 l0 ?
  126.     while (pb->bits_buffered >= 8)
    0 L2 h) ^: p. j1 E5 Z
  127.     {
    , v+ H: o: t3 N& k
  128.         pb->bytes[pb->byte_index++] = pb->bit_buffer >> (pb->bits_buffered - 8);
    ' e7 i- R* i  \1 D
  129.         pb->bit_buffer &= (~(0xFFFFFFFF << (pb->bits_buffered - 8)));
    , _- ~  C4 G9 C, o; E
  130.         pb->bits_buffered -= 8;
    9 Y$ O8 y# X' A8 U
  131.     }( Y/ V4 W& w. F- x( ?7 L- u
  132. & A9 C7 ~2 d' D+ G# {" U5 f# O
  133.     if (pb->byte_index >= MAX_PUT_BITS_BYTES)1 y3 v8 k4 R) N6 P' N  ?  e
  134.     {5 E& m" n" A/ l; q# [  \
  135.         printf("HELP! Bit overflow\n");4 D+ z3 `& n% M) ]3 c/ G
  136.         exit(1);8 p, G: h& N& Z& {0 }6 C1 ^9 M
  137.     }  D0 ~2 ^9 f- p6 }( d" P
  138. }: G6 o( b% F; W. v

  139. 5 K3 L1 c" ]: O. U. a( L
  140. static void put_bits_flush(put_bits_context *pb), }0 L2 r+ k% X
  141. {4 Y( [; H, V8 V/ z7 l
  142.     if (pb->bits_buffered > 0)
    / ]9 i; k8 p- ^# C
  143.         pb->bytes[pb->byte_index++] = pb->bit_buffer << (8 - pb->bits_buffered);3 c' G/ S& q% T( q6 L" k& h  N
  144. }, p/ G- g+ {, Q: d4 e+ ]

  145. 2 j2 f5 e( v3 T6 U4 a
  146. static void delete_put_bits(put_bits_context *pb)
    : C9 Z0 {/ ?, \& ]5 l
  147. {
    2 I8 Z. }* O$ s
  148.     free(pb->bytes);
    * b4 L" }; y2 P0 i5 N8 W& q% V
  149. }
    2 |8 P2 N% A1 s$ Z( x" u0 d
  150. ; z- U( z( p+ L2 b3 n. s
  151. /*********************************************************************/
    ( C/ O7 o4 o  e& N) u, E# ~: s
  152. 0 p+ f- s, ]0 R) k; l+ n4 A
  153. /* RBT functions */7 c1 E2 O! ]# Y* z; x: J" x

  154.   n% E- B3 Z- S# k/ x4 [0 O* y& @
  155. #define PALETTE_COUNT 2566 A' c( J) p; \1 p: T: f
  156. #define RBT_HEADER_SIZE 60
    ) ]' K, {2 v9 Z/ l1 u2 {
  157. #define UNKNOWN_TABLE_SIZE (1024+512)( b, T; F( M3 ^/ N7 x- V0 c
  158. #define SUBTITLE_THRESHOLD 0x70
    & l, Q. L2 p0 w! ?3 k2 g% K0 o9 f
  159. #define MILLISECONDS_PER_FRAME 100
    ( l+ F+ G' k; m# J. _, F- u

  160. & w3 w7 c5 \: q4 G/ U
  161. /* VLC table */
    - C3 W* F5 F. w1 L7 O
  162. #define VLC_SIZE 4
    . E- U* W8 M9 [& |0 J
  163. static struct0 k( Q: g9 l' ~% @. d
  164. {
    ! \3 E" k  O' j& Z
  165.     int count;
    . o! p8 @# h$ U# _+ e
  166.     int value;) Z; W/ M: D, S/ G% a0 L
  167. } lzs_vlc_table[] =2 p5 W5 L9 Z; b4 o
  168. {: L" l0 v! l1 H8 p, q4 [
  169.     /* code length = 2 bits; value = 2 */
    # O* Q. e1 x5 p6 p
  170.     /* 0000 */ { 2, 2 },& G: S$ `4 n2 m
  171.     /* 0001 */ { 2, 2 },
    / q& j7 Q+ [$ n# `! h7 O" [
  172.     /* 0010 */ { 2, 2 },  `6 U( e$ B3 N0 G/ |6 [' c, x
  173.     /* 0011 */ { 2, 2 },
    . M# |/ y5 u; ?* B; ]
  174. 5 d, t" [5 b, z' h/ {
  175.     /* code length = 2 bits; value = 3 */
    3 x$ m6 Q$ Q2 \2 @/ z% i
  176.     /* 0100 */ { 2, 3 },! k; d7 M5 a3 r8 `0 @" O& _
  177.     /* 0101 */ { 2, 3 },
    ) u# s+ e$ V& {/ ?' G
  178.     /* 0110 */ { 2, 3 },8 J- b# B6 I: S. N8 T
  179.     /* 0111 */ { 2, 3 },
    ' q9 w' E& D4 ^  s* i* K9 n
  180. ) S, R  S- S# d2 A- E" M
  181.     /* code length = 2 bits; value = 4 */( |* t6 Q8 i4 m( H
  182.     /* 1000 */ { 2, 4 },0 ?  s* u9 H' ?9 U: T% Z& Q
  183.     /* 1001 */ { 2, 4 },; ^& }. C( H% w, p% C  u+ _
  184.     /* 1010 */ { 2, 4 },
    1 d9 ]- z% b8 I1 o7 W/ m
  185.     /* 1011 */ { 2, 4 },
    , a) h$ c+ d+ Z( d& s3 V

  186. 2 A) S6 x$ n0 O  s# K
  187.     /* code length = 4 bits; value = 5 */
    0 U0 ]7 p, o8 L( }8 R  h" a
  188.     /* 1100 */ { 4, 5 },
    0 q3 s- i6 {! f$ p7 m& z/ Z3 N

  189. 2 J# M- g/ ^  R* E* S
  190.     /* code length = 4 bits; value = 6 */
    $ @, s- s* @* `9 n2 z- t" A* ~
  191.     /* 1101 */ { 4, 6 },
    2 Z9 N5 B0 W# Q: \/ [! q* \4 t
  192. - [5 j0 q1 w6 ]  H* X% l
  193.     /* code length = 4 bits; value = 7 */
    0 y4 F8 k" f( J
  194.     /* 1110 */ { 4, 7 },
    6 o8 G9 e" k$ C
  195. 7 P" t! M. F0 e5 e* Z- h  f
  196.     /* special case */& N: y, g5 u+ c5 n' v6 M& X
  197.     /* 1111 */ { 4, 8 }- w: {0 [9 K- C; w2 _6 b5 V
  198. };& B- P' n+ D3 P

  199. : g3 T1 D/ ~6 P9 V' k
  200. typedef struct
    4 b7 }# U0 U4 s4 c8 W
  201. {) M3 ^$ W: Y- z5 ], Y: v' U2 [6 _5 O) p
  202.     int version;8 [" e2 U2 A# t6 P- N
  203.     int width;' \1 _$ B; ]  c$ g9 s$ D. ^
  204.     int height;% Y) O9 l1 O# Q+ {& D7 t
  205.     int frame_count;
    + k( Y) J6 c# }4 l
  206.     int audio_chunk_size;2 m2 H, B7 d! j1 `6 P
  207.     uint8_t palette[PALETTE_COUNT * 3];8 |: n! j- t1 r2 @
  208.     off_t video_frame_size_table_offset;
    9 d. W( ?1 x; D( t+ U2 Z: X
  209.     uint8_t *video_frame_size_table;/ G$ s" \% q$ k1 F0 R: F; y  t
  210.     off_t frame_size_table_offset;. S  O: C& S& P1 \( n+ w1 f
  211.     uint8_t *frame_size_table;/ B) c! J2 z+ w: w  B
  212.     uint8_t *frame_load_buffer;6 P% U: U/ s- g5 J8 f* ~5 w' |
  213.     int dump_frames;
    4 O& s' L% n( ~, R' n  D
  214. 0 y/ r" `# W! T; x) ?
  215.     /* subtitle library */
    " a; x5 V' r* }$ I* j: k; R- g
  216.     ASS_Library *ass_lib;8 k* C7 P' f2 ^% p: u
  217.     ASS_Renderer *ass_renderer;
    6 X- P' [( J+ G- A, f% }
  218.     ASS_Track *ass_track;# q3 c9 b; S% z, ?
  219. } rbt_dec_context;
    * o& y) r6 \: t  n! t$ Q
  220. 1 ^2 I1 C" ~, U' a
  221. static void dump_pnm_file(char *filename, rbt_dec_context *rbt,
    . C0 {& F# F  O9 \, p
  222.     uint8_t *image, int width, int height)+ o- e( _' N3 `/ u* Z; m  H
  223. {* B& @# l" W1 f+ m- @
  224.     FILE *outfile;
    0 r$ d5 p% g$ u) g
  225.     uint8_t bytes[3];
    % [7 m$ v1 \4 Z/ Y5 H* b
  226.     int p;
    " V) I, d$ p& a, v
  227.     uint8_t pixel;. W  Y6 L' N" `0 z$ H
  228. % W* P4 ?1 r+ s" q
  229.     outfile = fopen(filename, "wb");
    2 y2 T7 z* Y: R* V
  230.     fprintf(outfile, "P6\n%d %d\n255\n", width, height);
    ( o$ ]' A- j; t0 n2 z+ M% J) ~& A- ~
  231.     for (p = 0; p < width * height; p++)2 P6 o" i2 ^! A* t2 X- X! z: a
  232.     {- `% ]- |: S! U1 u
  233.         pixel = image[p];
    5 T! v8 O  T/ g
  234.         bytes[0] = rbt->palette[pixel*3+0];
    + u6 _: m+ {/ g! T3 P: \
  235.         bytes[1] = rbt->palette[pixel*3+1];
    6 ]+ A5 r/ }9 Y: o
  236.         bytes[2] = rbt->palette[pixel*3+2];
    * o( M7 L5 |  L7 @  s
  237.         fwrite(bytes, 3, 1, outfile);
    7 \$ G! S9 G3 f! {' K- l/ e$ {
  238.     }; `2 m5 h, A( A% ~0 {, u
  239.     fclose(outfile);
    4 {* p- \/ L$ @1 j  r' c
  240. }0 k' p7 `; q% l" B
  241. 1 K% a. \4 [1 _4 h0 o
  242. static int load_and_copy_rbt_header(rbt_dec_context *rbt, FILE *inrbt_file, FILE *outrbt_file)$ B  R: U: R. _" f, f! m. N
  243. {
    & [$ b4 Z# I8 h% N
  244.     uint8_t header[RBT_HEADER_SIZE];
    $ @' W  U- h1 c
  245.     int palette_data_size;' F6 Z9 h5 m0 b6 O% |/ E4 F" K7 e6 }
  246.     uint8_t *palette_chunk;5 i( d( M" E  b
  247.     int unknown_chunk_size;3 x: |4 [9 T5 s& }" C/ B# R
  248.     uint8_t *unknown_chunk;( r; T2 N& S$ u
  249.     uint8_t unknown_table[UNKNOWN_TABLE_SIZE];
    # X" E+ o3 `5 A: x# v
  250.     off_t padding_size;0 Y% P5 g0 y2 C% x
  251.     uint8_t *padding;
    7 h8 y# T% v1 X5 l% O+ L
  252.     int i;
    ( l/ x( c$ N: d/ b
  253.     int frame_size;
    ! ~$ Q, B4 X/ E, V) L2 L# v
  254.     int max_frame_size;
    1 O; F" R. @: k9 q9 y* `
  255.     int first_palette_index;
    $ C/ N  |5 k& a! r& C% l, C
  256.     int palette_count;* @3 Y9 q; t" K
  257.     int palette_type;3 b: }' q% J: q. H& n7 k
  258.     int palette_index;- m- b  H$ c, ]. c. O
  259. . }2 n7 W8 y+ e8 w0 h1 _
  260.     fseek(inrbt_file, 0, SEEK_SET);
    2 I! e8 d+ C" {( t$ _6 k
  261.     fseek(outrbt_file, 0, SEEK_SET);4 c; p5 Z2 ~5 b" J" @; k% I7 w8 f  C
  262. # g. u+ ]) k1 M4 o2 d9 @; g  W
  263.     /* load the header */
    " e# z) P$ c( A8 G- ^. m3 @7 f% O
  264.     if (fread(header, RBT_HEADER_SIZE, 1, inrbt_file) != 1)
    5 h2 r# F5 M3 F) V
  265.     {8 E0 o8 y3 U' Q$ i$ v7 S5 A
  266.         printf("problem reading initial RBT header\n");
    , b7 C2 X/ i0 b' {6 b
  267.         return 0;/ Q0 P; G9 `5 J, X- L! |3 g
  268.     }
    $ g% L+ p3 T1 f% Y4 B4 s* z
  269. / J9 R3 X# W7 C& Y6 @4 z
  270.     /* copy header to the output */
    - I, U+ g8 U* D) f3 N
  271.     if (fwrite(header, RBT_HEADER_SIZE, 1, outrbt_file) != 1)6 o: D  n4 o( E
  272.     {9 Z2 ]5 Q/ E( t+ N# L* Y
  273.         printf("problem writing initial RBT header\n");
    " e3 D1 \- Q' _- Y( V
  274.         return 0;
    ! f3 Q& b5 Q* U& g: S5 i  A
  275.     }
    $ D( Z3 P' M. M9 m& C: \& ^
  276. 6 l' [6 v& y) h8 u6 L2 A  r
  277.     rbt->version = LE_16(&header[6]);3 |3 E; z9 j/ h6 T4 g7 ]
  278.     rbt->audio_chunk_size = LE_16(&header[8]);
    * z1 K6 L/ d- p% F
  279.     rbt->frame_count = LE_16(&header[14]);
    6 g  t- d8 Y  E3 p# P/ H
  280. + G  F* q3 [; e' Y
  281.     /* transfer the unknown data, if it's there */
    " U7 l7 s5 T$ _6 V
  282.     unknown_chunk_size = LE_16(&header[18]);
      d: w5 j7 v( w& l# t4 H* F
  283.     if (unknown_chunk_size > 0)
    % @7 E9 z+ b) e! h- P1 Q* J, F1 o
  284.     {9 F) s# b3 e0 B
  285.         unknown_chunk = malloc(unknown_chunk_size);
    # L4 f( M- q. g" l" o: T; U/ Z
  286.         if (fread(unknown_chunk, unknown_chunk_size, 1, inrbt_file) != 1)4 g& g/ J3 n; K# i
  287.         {1 a" \, ^% x& j0 c
  288.             printf("problem reading unknown data\n");& A  |) m" v' _: M* K- h0 r9 f
  289.             return 0;
    / K. w3 l3 s1 n4 I& q
  290.         }* s' `+ o0 O+ D( V! {' A& o
  291.         if (fwrite(unknown_chunk, unknown_chunk_size, 1, outrbt_file) != 1)
    3 e  D6 u* y% v7 Y: f$ H6 p6 Y4 L
  292.         {+ X( P% ?) F9 `; i6 ^+ W
  293.             printf("problem writing unknown data\n");% p% b7 R# J; W# c3 w1 F, E- E$ Z) Y
  294.             return 0;
    ( ]3 m: Y# S: U! P
  295.         }
    0 z7 K. y: ]" f1 k" H
  296.         free(unknown_chunk);8 }4 V# v! E4 y
  297.     }& ^* F' l& m. y0 P" N+ g
  298. 6 t" `& I7 `6 b4 {6 [
  299.     /* transfer the palette chunk */$ |: `$ }8 V) M8 {( [6 U8 c
  300.     palette_data_size = LE_16(&header[16]);; E2 P8 D" \3 {6 M( ]6 K  k6 b
  301.     palette_chunk = malloc(palette_data_size);
    " m1 w2 F7 ?# s) k7 M' j
  302.     if (fread(palette_chunk, palette_data_size, 1, inrbt_file) != 1)
    ) B3 |& _0 N1 _4 e# r9 Y5 F' _
  303.     {
    - s4 E% j% N$ R- d
  304.         printf("problem reading palette\n");
    $ A1 ^3 [, N* A" Y, c. L
  305.         return 0;
    ' d4 E1 C1 M6 {: q
  306.     }' H' E* s$ C7 L0 d4 H
  307.     if (fwrite(palette_chunk, palette_data_size, 1, outrbt_file) != 1)& ]/ w2 _9 s8 }
  308.     {
    ( B+ C( Z5 V9 O- @
  309.         printf("problem writing palette\n");
    8 x* c) {! W3 U) s
  310.         return 0;. R4 a: P2 _. G) M1 L5 L, O: F0 b4 \
  311.     }
    # e( N* h' z* [' {' |9 o7 K
  312.     /* load the palette into the internal context */, x* l) D( E- @! P; F! D
  313.     memset(rbt->palette, 0, PALETTE_COUNT * 3);
    + z; \/ q+ W+ o3 J& ~/ K
  314.     first_palette_index = palette_chunk[25];2 x: l% ?' K' `1 M
  315.     palette_count = LE_16(&palette_chunk[29]);: {7 p* P1 C& y" m7 `
  316.     palette_type = palette_chunk[32];6 M4 ]4 C1 E) q1 t; ~0 j# ^7 Y
  317.     palette_index = (palette_type == 0) ? 38 : 37;
    2 |5 B9 ^6 ^: a2 A* ?: w- I& b7 i7 U
  318.     for (i = first_palette_index; i < first_palette_index + palette_count; i++)! Z& z+ B# {0 I* l
  319.     {7 D2 X- S) I6 z2 y) C5 o+ J
  320.         rbt->palette[i*3+0] = palette_chunk[palette_index++];
    $ z' P% Q7 n  [$ W# ~2 ^
  321.         rbt->palette[i*3+1] = palette_chunk[palette_index++];$ e" o+ C0 C) X: k
  322.         rbt->palette[i*3+2] = palette_chunk[palette_index++];6 q4 O$ @+ w. s; _7 y0 _8 ?! J
  323.     }* L/ A! G1 J- n/ P
  324.     free(palette_chunk);
    $ y1 h% }, j/ b" V+ o+ P  I5 ~6 U6 D
  325. ) O- h, p* Q& K: r
  326.     /* copy the video frame size table (2 bytes per frame), as a placeholder */  M7 i) H% G" U! d1 R& _
  327.     rbt->video_frame_size_table = malloc(rbt->frame_count * sizeof(uint16_t));
    ' c! r# [0 U9 J  S
  328.     if (fread(rbt->video_frame_size_table, rbt->frame_count * sizeof(uint16_t), 1, inrbt_file) != 1)2 j. l; U3 q' S7 m! v( K  w/ }, e
  329.     {/ Z( c( X7 L, `1 B# j9 ?) ~% @, l
  330.         printf("problem reading frame table\n");$ R1 _2 g8 z# V/ T& g* B
  331.         return 0;
    ' d4 r. g6 V" X& g
  332.     }
    4 k, b$ ]5 ~  F+ h. h
  333.     rbt->video_frame_size_table_offset = ftell(outrbt_file);
    ) D/ L+ V. ^5 g% F) w
  334.     if (fwrite(rbt->video_frame_size_table, rbt->frame_count * sizeof(uint16_t), 1, outrbt_file) != 1)" U& q* f5 g6 G4 J+ I1 y* q
  335.     {
    ! b$ b8 Z5 h7 q+ [
  336.         printf("problem writing frame table\n");; H0 t4 h& J2 J. l% w, x# T
  337.         return 0;' G' F! a8 H8 B3 d0 w- b
  338.     }
    7 u  I' h! `, t! _6 k2 F5 W  ~' M

  339. 0 s; l, n8 v9 S- b$ Q- l3 z
  340.     /* copy the frame size table (2 bytes per frame), as a placeholder */! z4 G; }9 w3 o! e7 d
  341.     rbt->frame_size_table = malloc(rbt->frame_count * sizeof(uint16_t));2 M' y- B2 J2 V; Z) `/ ^. w
  342.     if (fread(rbt->frame_size_table, rbt->frame_count * sizeof(uint16_t), 1, inrbt_file) != 1). U+ d# q- T. }7 b7 J
  343.     {
    , @/ |- j) Y, y' H0 H
  344.         printf("problem reading frame table\n");& `7 b' T# x4 x" U/ H: W5 [0 `
  345.         return 0;
    0 O* _8 @4 _4 q$ u' H6 Q, p
  346.     }- s3 b$ A7 c" I/ W8 P
  347.     rbt->frame_size_table_offset = ftell(outrbt_file);
    8 r  p8 C* K" L1 s1 z
  348.     if (fwrite(rbt->frame_size_table, rbt->frame_count * sizeof(uint16_t), 1, outrbt_file) != 1)6 u. n4 A8 O* N3 W) L/ |
  349.     {
    3 \1 i" T  Y& q. u
  350.         printf("problem writing frame table\n");5 M7 c& |2 H+ _& u- G( C3 v' _
  351.         return 0;
    8 S, m2 u! v5 \
  352.     }
    + K' x0 Q+ F! l5 |' x- S7 \

  353. " ?- i. p9 R) W1 B, B
  354.     /* find the max frame size */
    & v4 `0 ?0 I8 c9 w) v
  355.     max_frame_size = 0;
    8 `0 W0 ^, @* e3 D8 H
  356.     for (i = 0; i < rbt->frame_count; i++)
    6 w/ L+ Y" r1 X; ~; p
  357.     {
    8 r" W1 O( Y1 E7 v3 x: g
  358.         frame_size = LE_16(&rbt->frame_size_table[i*2]);
    + x' |* d0 s' W
  359.         if (frame_size > max_frame_size)4 ]- q2 `# ]! s1 h
  360.             max_frame_size = frame_size;
    8 D- e5 [/ o2 R& s! [( c
  361.     }
    ; j! Q' C3 u) Y0 }+ z+ E
  362.     rbt->frame_load_buffer = malloc(max_frame_size);: b- a4 Q3 {' O' i

  363. - v' a6 E' t' ]- l7 T
  364.     /* transfer the unknown table(s) */
    + {) z" {8 g/ y4 O. K# N( t- y
  365.     if (fread(unknown_table, UNKNOWN_TABLE_SIZE, 1, inrbt_file) != 1)
    ( f# S( }. W5 n: D1 q
  366.     {9 g9 b+ I: {3 B% {+ o
  367.         printf("problem reading unknown table\n");; x5 n$ Z$ E1 e2 i: m2 V* k
  368.         return 0;9 p. `* E$ s8 t, C
  369.     }/ b) Y; X6 |5 v4 V
  370.     if (fwrite(unknown_table, UNKNOWN_TABLE_SIZE, 1, outrbt_file) != 1)
    # i  Z6 r( t/ m+ G1 Y  {! _2 `, B- d# |
  371.     {
    - S/ ~9 r. [2 |. R+ x  k
  372.         printf("problem writing unknown table\n");) j0 n% p. f/ M+ ~/ F7 `
  373.         return 0;
    ! \: K2 z+ ^1 d8 p% K3 F
  374.     }
    - X# r; |; Q; q0 {9 b

  375. . e7 ]! z& j% ?  I. T% J
  376.     /* copy over padding */3 n. @7 ^$ V% P* ^
  377.     padding_size = 0x800 - (ftell(inrbt_file) & 0x7FF);. s9 Q, l: x' j' G
  378.     if (padding_size)
    , v& |5 z- L; d* N* N7 I! w
  379.     {
    9 J3 l, }/ ]9 [! B: @% G  @
  380.         padding = malloc(padding_size);
    2 D( \9 \, m$ P; z7 Q8 i
  381.         if (fread(padding, padding_size, 1, inrbt_file) != 1)1 e# P$ @! I  u- ]9 |* y
  382.         {& j; G& i+ E1 n' P' F2 n2 O
  383.             printf("problem reading padding\n");
    5 W  K3 ]4 J5 ?' Z1 G
  384.             return 0;$ J" c* z! k+ d
  385.         }
    8 |9 i: @7 y/ {3 ]
  386.         if (fwrite(padding, padding_size, 1, outrbt_file) != 1)
    3 H# S/ q* \. s$ J0 l- G. B0 f
  387.         {8 f0 u9 {' \7 t: U
  388.             printf("problem writing padding\n");) L( d! V7 C0 l* o7 S; s
  389.             return 0;2 o6 V. u" U' m
  390.         }
    $ x5 z6 J) ^4 C( P# p
  391.         free(padding);: Y* ~! d9 G# z! R
  392.     }
    0 _  T/ M$ [2 Y3 Z4 }% [3 ~4 a
  393. ; ]8 L# _( `  v6 c6 H7 J
  394.     return 1;; b% I, E0 d# N! Y! D
  395. }
    : V! i* l; a2 C. U" z

  396. ; f( ~1 p5 e" a1 @
  397. static int get_lzs_back_ref_length(get_bits_context *gb)
    3 b; ~) o1 [. P) s6 z9 d6 l! ]
  398. {: Y4 f& J2 n4 `0 b) m" J3 W
  399.     int vlc;  e3 _" U+ y. f6 N
  400.     int count;
    / r- N4 b( l4 _7 _$ _
  401.     int value;
    0 W1 |6 S/ w0 w1 q, B( ]
  402. + X: t& n5 _* ^
  403.     vlc = view_bits(gb, VLC_SIZE);
    & q3 J2 A( y! x5 t) G
  404.     count = lzs_vlc_table[vlc].count;
    2 n% a7 o* A& a8 a! Z& q, c7 l
  405.     value = lzs_vlc_table[vlc].value;
    ) ^& _. O8 K* C, s- m
  406. * \+ j& ]) W6 H9 ^* w
  407.     read_bits(gb, count);
    7 U8 t6 b9 |0 W$ Y
  408.     if (value == 8)
    9 w% U$ X9 I) K4 F& v5 Y) g5 K2 {
  409.     {+ W' G1 r$ O/ @, U3 r
  410.         do
    7 t  C2 w+ M# E& P) ^. ]6 M; Q
  411.         {
    . m0 R+ ]* N  c" k  u. ?& k& g
  412.             vlc = read_bits(gb, VLC_SIZE);
    3 w6 B7 ~. t  N$ z
  413.             value += vlc;
    3 p2 E4 B6 W9 G% B  P' s
  414.         }5 Z& p. E+ S, Y  |3 q( r8 e5 U
  415.         while (vlc == 0xF);
    0 c) i  @1 s" Y. v
  416.     }
    ! N% @7 m5 ]8 n5 @9 Y2 ]" y7 u

  417.   M% F' H6 a0 p/ J
  418.     return value;) h* m+ ^+ y2 @
  419. }9 ]! d7 H: j3 X( a1 K  l
  420. 3 E4 `4 O/ N7 [( }1 B
  421. static void compress_window(put_bits_context *pb, uint8_t *full_window,
    9 M; J( T) i+ K0 s5 r; z; ?8 I. S" N
  422.     int full_window_stride,  c7 Z# |3 |" r9 {$ O
  423.     int window_top, int window_bottom, int window_left, int window_right)
    - R: t1 P3 U5 _' O4 {# T7 s1 ]
  424. {
    5 E2 M# A0 S& D- R
  425.     int last_pixel;2 D5 o9 K7 \# A% ]' V  s
  426.     int run_size;
    $ v9 Y( v2 m, h4 M
  427.     int x;
    1 S$ m* c' A# a
  428.     int y;6 G: H  M- i% o+ x
  429.     int start_index;
    7 }+ e4 q7 Z5 T( k1 J; C
  430.     int end_index;9 V+ l* h) H& I0 r! b2 f
  431.     int encode_last_run;( Y  Y& y2 O+ u! ~: i7 i9 z
  432. . Y5 q& H9 j) ?* S4 m6 ]: c1 i
  433.     last_pixel = full_window[0];
    - k' g/ C% S" n
  434.     run_size = 1;
    0 i+ Y$ Y, g. ?: G3 k) Z; G
  435.     for (y = window_top; y <= window_bottom; y++)/ F9 T. |7 ?- e& J# W0 Z
  436.     {( F0 T% U$ h; O7 Q
  437.         start_index = y * full_window_stride + window_left;
    ; k$ h% X' v7 m& p5 ^) m6 U
  438.         if (y == window_top)
    $ Z9 f) Z- \  W+ e: V: w" q' N
  439.             start_index += 1;) A& E0 ]) H" {- }2 f+ u+ {
  440.         end_index = y * full_window_stride + window_right;
    $ z! J/ C5 ]# M8 i
  441.         if (y == window_bottom)
    2 x  h9 l& i3 e5 [+ K, g$ e! ~
  442.             encode_last_run = 1;2 D5 L* a( \& j5 A# z3 j
  443.         else+ \7 Y1 c6 H5 }! z/ l
  444.             encode_last_run = 0;
    % N3 |$ T. Q$ J4 P' b. K
  445.         for (x = start_index; x < end_index; x++)  K* ~3 W8 B  S1 V. T
  446.         {, F* b( z1 _' N, F2 H
  447.             if (!encode_last_run && full_window[x] == last_pixel)
    ; ^( b" N2 U3 B4 w* A# [
  448.                 run_size++;
    , K  g* a/ i% `4 j0 V) _' ]5 @
  449.             else$ \. Y# @5 p5 o
  450.             {
    : K7 u) B  p# J8 R8 S9 m" F( B: G, R
  451.                 if (run_size == 1)
      O0 D9 G% s, K9 r
  452.                 {4 E* _4 {; c* b4 I" R! l9 b+ B5 |
  453.                     /* encode a 0 bit followed by raw pixel byte */
    ! z  P3 d- w3 d) Z1 x
  454.                     put_bits(pb, 0, 1);
    5 ?, k% k/ H' {( @' k' a
  455.                     put_bits(pb, last_pixel, 8);
    & X0 {' ^: Z, S2 J
  456.                 }
    " W2 y: I$ f  q: F, K
  457.                 else if (run_size == 2)  _, F7 t. J7 T) l
  458.                 {: f' P( J$ R. M# F* F- G; ~- l
  459.                     /* encode a 0 bit followed by raw pixel byte */0 h/ I, b5 P0 y" [5 t& |
  460.                     put_bits(pb, 0, 1);' k" R0 e: u% b# L; v
  461.                     put_bits(pb, last_pixel, 8);
      m7 o: o1 `. W' R1 g  o! n
  462.                     put_bits(pb, 0, 1);
      [6 l0 I1 L/ l( e0 x! ~3 t, M3 W
  463.                     put_bits(pb, last_pixel, 8);! ?: N# G8 N) H+ [# I  ^$ d8 u
  464.                 }, k- k4 s# T; v% x6 i" d
  465.                 else
    5 [! |" _& Q3 T0 J% k
  466.                 {8 w$ B8 Q6 Q* O. U9 O* J
  467.                     /* encode a 0 bit followed by raw pixel byte */
    . E  q. z, x& V" _; Z% @' ]9 E+ G! Q
  468.                     put_bits(pb, 0, 1);
    2 q, G& O& X( Q6 Z3 {- [! W
  469.                     put_bits(pb, last_pixel, 8);# T7 S8 _+ ?$ ?  b
  470.                     run_size--;! T2 G8 _: ~! d: i9 ^! O, y, C; K
  471.                     /* encode a run: a 1 bit, followed by a back reference& {3 n% w5 n3 r1 g: Q( F
  472.                      * offset (-1), followed by a length */; m. x* I: [  f. e! c4 |- I* P
  473.                     put_bits(pb, 1, 1);
    * r( T+ Y3 ~2 R: ~
  474.                     put_bits(pb, 1, 1);  /* 1 = 7-bit offset */
    * P2 }- N8 B% T0 n
  475.                     put_bits(pb, 1, 7);
    * Y" k& [' i' I7 d" ^8 ^
  476.                     if (run_size <= 4)$ b& |& }9 }: V1 R) C3 w
  477.                     {
    & x2 O3 E) j) C" t. K/ ?" G: {
  478.                         /* lengths 2, 3, and 4 are 2 bits */6 O0 |6 }9 n7 z, F
  479.                         put_bits(pb, run_size - 2, 2);* A& @  A: @0 E
  480.                     }0 s! Z% [# P1 M# L, O
  481.                     else if (run_size <= 7), w1 z) A! F( s+ C
  482.                     {# |$ G( v  ]  z& A" s$ L
  483.                         /* lengths 5, 6, and 7 are 4 bits */; M4 }, h. f7 r( d/ z
  484.                         put_bits(pb, run_size + 7, 4);
    & w) ]8 i4 y2 `  ^4 f' K  y2 }
  485.                     }3 u' T4 ]% t7 ?5 m
  486.                     else
    % D: T/ G- C5 [" B
  487.                     {
    7 n6 S2 A6 F( X$ k' t
  488.                         /* arbitrary length; start by encoding 0xF which) Y, x; H2 v) r
  489.                          * stands in for an initial version of 8 */6 C* l) H1 U( q0 ~: X
  490.                         put_bits(pb, 0xF, 4);+ j3 i5 m9 X1 x+ ]+ b  g
  491.                         run_size -= 8;
    - C3 s- v. B- g* d$ Z4 C
  492. $ V- K1 F: D: _
  493.                         /* encode blocks of 4 bits until run_size is 0 */
    9 {: N* }$ p5 q! g
  494.                         while (run_size >= 0)% W$ `) |3 y( ^& t) u
  495.                         {
    , M6 n' i- ^8 G: z
  496.                             if (run_size >= 15)8 O" X4 K$ C7 S$ P7 O
  497.                             {2 K$ @, y2 D' l2 b' D
  498.                                 put_bits(pb, 0xF, 4);
    9 l0 U; ~- f! M: W' n. Z
  499.                                 run_size -= 0xF;6 {- ~4 ^" L1 C5 w9 F
  500.                             }
    * l- N. _4 y6 p2 X( U7 \
  501.                             else
    5 m9 x6 b* s1 i! p% y
  502.                             {
    6 T$ f9 Q9 e/ W: k6 d
  503.                                 put_bits(pb, run_size, 4);
    7 }8 E! _+ p. A
  504.                                 run_size = -1;  Y3 J+ P9 a+ m# C
  505.                             }
      l! N. |. A3 H3 Q
  506.                         }
    2 S7 `) E0 |0 u
  507.                     }! s( D6 ]8 b: |9 E- c
  508.                 }" A7 _% ~* f: |. Q
  509. 2 H+ b2 n1 _; t2 A# i) r. K  m
  510.                 last_pixel = full_window[x];1 C0 `( g4 ~8 j, E
  511.                 run_size = 1;
    + \/ d3 Q1 M3 C. k8 ~7 m/ Q+ R

  512. . g2 F' _6 G4 U& v7 S$ X9 ?0 d  Z
  513.                 /* this single x iteration was only here to close the final run */& J9 L# t# C9 s& E
  514.                 if (y == window_bottom)
    8 Q/ x3 H# s0 n! G
  515.                     break;
    7 q- D' `$ z+ w+ g5 d
  516.             }
    : o. L1 X8 R5 k' S
  517.         }
    , k' E. O0 ]. H9 t1 [, ~
  518.     }( ^% C0 B+ w3 Z- @+ ~- r- i
  519. ; W! ~; x. q4 o' k0 D8 F
  520.     /* close the bitstream by encoding a back reference with length 0 */
    6 ^+ _% V2 p9 m& J
  521.     put_bits(pb, 1, 1);  /* back reference run */! x: |1 A( T) `( c/ ^
  522.     put_bits(pb, 1, 1);  /* 1 = 7-bit offset */& ]: k" s" q2 {0 y* c9 A
  523.     put_bits(pb, 0, 7);  /* length 0 */
    ' |! m9 q" W0 }/ A1 v5 _- d

  524. 4 o  {0 ?8 h/ i7 {" O
  525.     put_bits_flush(pb);
    3 `1 N; H3 T+ g! M6 l5 y8 B+ l* ~
  526. }, \# M: r) x/ r. I% Y
  527. / m  ]$ p; M& V6 B$ f9 ^
  528. /* compute Euclidean distance between an RGB color and the desired target */
    & F+ H/ B4 v) r9 e( m
  529. static int compute_rgb_distance(int r1, int r2, int g1, int g2, int b1, int b2)
    ; J+ y( ^  e7 b4 V' M! D) {1 }
  530. {* R0 x- Y5 q$ l3 k, }: a. B4 p
  531.     return sqrt((r1 - r2) * (r1 - r2) +1 c! R$ w2 M% x( [$ ~/ k/ {" B
  532.                 (g1 - g2) * (g1 - g2) +
    7 F/ k8 Y) G& d
  533.                 (b1 - b2) * (b1 - b2));% f$ K0 M/ V6 \& \6 K- ]& Y/ u
  534. }
    9 c* U: [. l$ J

  535.   R: q' H" P# z2 d: {% d3 W
  536. static uint8_t find_nearest_color(rbt_dec_context *rbt, int r, int g, int b)
      k$ T. j* r# H: _% s' s& M# @
  537. {
    ( i: M6 I0 m# ?/ g
  538.     int i;
    5 z3 J& j7 s+ ]# Y, ^: A
  539.     int nearest_distance;
    1 N/ j  r5 O8 z- e, u8 b# Y
  540.     int distance;
    " |) F# O) Q; l8 y/ w% u
  541.     int rp;. N* g6 z2 {! ^0 k( ?2 _+ i* r
  542.     int gp;
    % d/ @- F/ [4 X4 \1 X& a+ z, |6 s
  543.     int bp;# ~8 y- A/ F& X$ E3 h
  544.     uint8_t palette_index;- w9 {( M. U& P" p* D

  545. 2 _: y+ h7 C* ~/ G5 V
  546.     nearest_distance = 999999999;
    % w9 x, o; ?* @3 w
  547.     palette_index = 0;+ E, F+ g  |0 D) ^7 D3 n! R
  548.     for (i = 0; i < 256; i++)
    + h, n/ }3 L2 ?; L! G$ p, Q: w! f
  549.     {
    0 ?: V" ^, e1 E* }, f6 o5 Z9 _
  550.         rp = rbt->palette[i * 3 + 0];5 i  \, k5 ~4 W
  551.         gp = rbt->palette[i * 3 + 1];/ u& r1 k1 E/ T0 A+ X3 F6 [; Y
  552.         bp = rbt->palette[i * 3 + 2];
      A" ~# k8 }5 [- R) H' R; K% a
  553.         distance = compute_rgb_distance(r, rp, g, gp, b, bp);
    0 W; \% p) J6 x2 j
  554.         if (distance < nearest_distance)
    : H4 p! J6 f3 R
  555.         {
    ( J9 H) f6 a6 q7 n" P
  556.             nearest_distance = distance;
    / I- f( \; g( A* T
  557.             palette_index = i;% H: y; [1 Y3 z7 w* ~: H
  558.         }$ U5 O3 }' [! r
  559.         /* can't get closer than 0; break early */
    & l4 ]3 E0 d8 U  d: p& y- A
  560.         if (distance == 0)$ H: a4 ?0 N4 h* r% ?
  561.             break;
    6 @4 f, ^  j% p( l) k, e
  562.     }+ W) g( q4 D+ A+ n" i: ^9 T

  563. 2 h2 n) @# }' n* s6 R- _% C- A
  564.     return palette_index;. |% ~1 u! N1 g! s+ f9 B" G* @% p" r
  565. }7 T: [# E- |: Q) m$ E; j+ ^

  566. ; J; i1 O( f2 z! c/ A9 v
  567. static void subtitle_frame(rbt_dec_context *rbt, uint8_t *frame,0 y& ~( T/ m) T8 I9 i
  568.     int width, int height, int timestamp)
    9 l* ^5 G3 j( V2 l$ i4 V* v' u5 N
  569. {
    + O/ j, c. Y$ b5 R: d, l( x
  570.     ASS_Image *subtitles;- ]* _  G6 B5 i2 k. Q3 A9 o
  571.     int detect_change;# K2 P5 j( }+ l3 G
  572.     uint8_t subtitle_pixel;2 }+ `( k3 D0 q; \" M5 \% D
  573.     int x, y;9 E7 B# r$ x1 o( _% }' e! T8 f
  574.     uint8_t *frame_ptr;
    2 D4 ?# P  G6 Q# }1 O' j+ j+ k
  575.     uint8_t *subtitle_ptr;
    " z9 E5 z5 ?3 y, S3 X5 P( X/ M

  576. ( p/ R3 M0 T. Z* a  |% `2 f
  577.     /* ask library for the subtitle for this timestamp */
    6 V& p+ y; h* }* D9 L
  578.     subtitles = ass_render_frame(rbt->ass_renderer, rbt->ass_track,
    * n: p, Y" C* B. B1 ?7 n
  579.         timestamp, &detect_change);
    ' p6 `; c9 ^. r! _' T# N( t2 ^
  580. 7 i& J+ G' `4 {) s% v/ ?4 c
  581.     /* render the list of subtitles onto the decoded frame */
    : r& A+ l9 b# q
  582.     while (subtitles)) ~2 v8 d. ]" L, [6 {
  583.     {" O; h! g/ r7 w7 c2 m7 w2 O
  584.         /* palette components are only 6 bits, so shift an extra 2* k1 x' Y9 _! [. k1 V0 z
  585.          * bits off each component */
    ' V2 n. z% s0 Z, N! m1 ?
  586.         subtitle_pixel = find_nearest_color(rbt,
    # }; U4 B3 d$ v1 J
  587.             (subtitles->color >> 10) & 0xFF,& {. f! `# q. a
  588.             (subtitles->color >> 18) & 0xFF,$ `5 x2 U/ E! b% B, B
  589.             (subtitles->color >> 26) & 0xFF);
    $ P3 q( a$ w' a) l: _4 s
  590.         for (y = 0; y < subtitles->h; y++)
    % r8 m' ^% [! d5 n4 N6 e( x/ T
  591.         {7 a1 ^0 r7 |: k$ ^
  592.             subtitle_ptr = &subtitles->bitmap[y * subtitles->stride];
    ( ?- I1 ^/ S7 e
  593.             frame_ptr = &frame[(subtitles->dst_y + y) * width + subtitles->dst_x];
    - Q* |, d7 h4 C6 ?; A
  594.             for (x = 0; x < subtitles->w; x++, frame_ptr++, subtitle_ptr++)
    % {5 g, w7 a* \  a! j
  595.             {
    $ o0 R4 ~& ?. u4 w0 ]
  596.                 if (*subtitle_ptr >= SUBTITLE_THRESHOLD), ~7 b' p* b* F5 i+ z+ K2 Y
  597.                     *frame_ptr = subtitle_pixel;: ]) `4 m. ]5 `3 z  v" i
  598.             }2 }# j9 w. f. H
  599.         }
    ; Y" Z* l7 ?% E0 l- X: W, p8 H9 T
  600.         subtitles = subtitles->next;
    # x' v. V! R- f! D9 N
  601.     }0 }( L0 w% g# T5 ^  a; ~
  602. }
    2 C& c/ v- _( a# U5 @5 m
  603. 2 Y: D, D6 }* w7 Z& j6 v  G
  604. static int copy_frames(rbt_dec_context *rbt, FILE *inrbt_file, FILE *outrbt_file,
    ; U: R5 c* @" x9 B9 Y0 Z/ l: r& r
  605.     int origin_x, int origin_y, int window_width, int window_height)/ \1 ~8 H* T# h) o
  606. {, w0 W5 h9 x$ n8 a
  607.     int i;
    0 L$ i: Q0 x7 t& N# x3 n
  608.     int j;
    2 g+ T6 L3 ^1 x9 Q+ Q8 A  V/ y/ g
  609.     int scale;
    ! |# E9 `& [8 |& G
  610.     int width;
    % h  X# z' d4 Z- i) _( f  T
  611.     int height;. K6 x- w  M1 v% ~+ b- v
  612.     int max_width;5 _: ~" u& t# t0 b% O% I# c
  613.     int max_height;
      J8 ?# M1 L2 e9 G" S
  614.     int frame_x;0 N" ^' a0 F4 \7 J3 e; o( j
  615.     int frame_y;$ E) P7 Z- ~; Q4 f* ^
  616.     int fragment_count;
    2 l1 v; O1 k+ c' ]
  617.     int decoded_size;. ?: S* v8 q( {4 H! V( s2 P. `
  618.     uint8_t *decoded_frame;
    ! P1 Y2 G  H  h3 m" {. e
  619.     int fragment;  z% W& s+ Q5 L: i% m+ m9 y
  620.     int fragment_compressed_size;2 t  j9 v0 B6 h# g" H( `* |7 i8 r
  621.     int fragment_decompressed_size;4 _8 U' N0 }# @& N4 w- G3 g
  622.     int compression_type;
    ' D4 J6 F; Z/ U) f% n
  623.     int index;
    3 F% L* G, C0 B* b# w8 t
  624.     int out_index;: V& b/ v2 j# X# x
  625.     get_bits_context gb;% e- d% l( o2 @- @- g+ f
  626.     int frame_size;: Y% [& F  U" x+ j  ^
  627.     int video_frame_size;9 n" B+ D3 w3 a" h. p1 x
  628.     int audio_frame_size;
    1 r; T- G/ I! S& l
  629. $ a3 l$ W4 \; T  B+ [8 m
  630.     int back_ref_offset_type;: q; U3 u  x4 ^' c
  631.     int back_ref_offset;0 K% Q  i' R( O8 Z
  632.     int back_ref_length;
    + J" v! c3 F% c( l0 `
  633.     int back_ref_start;, u2 s7 t+ Q1 h3 ?' ~* r
  634.     int back_ref_end;/ ?4 [4 d* R$ e$ b

  635. ; l, Y2 U  h# y3 h2 H; o4 X4 P5 a) c$ X
  636.     uint8_t *full_window;
    ! Y3 Y. S1 y( R3 r5 C9 C
  637.     int full_window_size;3 x. k4 W8 }/ o& N
  638.     int y;/ B: i8 L8 K  E( ]! D) D* v7 L
  639.     int window_top;6 n( L+ q, G1 S$ E
  640.     int window_bottom;, `) I- R% j9 ?' i* q3 F9 z9 p
  641.     int window_left;
    8 _! D3 M. q+ }  J) i
  642.     int window_right;
    - l9 o0 Q6 Y  r' r9 s
  643.     int window_size;
    # [6 d1 H8 E9 G
  644. 9 E$ d# j) q* g- x* ]( B
  645.     char filename[30];$ {2 l: ]0 T! H/ N' Y/ e' [, N

  646. ; U; w, G, J' T' {
  647.     put_bits_context *pb;7 d9 R* e8 v/ Z2 }

  648. 0 h6 O( e. M' {! C0 F
  649.     full_window_size = window_width * window_height;
    . {7 D! d8 Q* l) b1 |: j
  650.     full_window = malloc(full_window_size);) F# y* ^" T7 W; T0 a# |4 h8 N
  651.     pb = init_put_bits();
    2 a9 ^5 z2 B' B3 t( l. J
  652. 7 V" H" L0 h+ y( M) I# \8 T
  653.     max_width = 0;$ q8 W- t6 ?; h) ]- x0 u! A
  654.     max_height = 0;
    : u" S; m8 ^* }1 a  E

  655. ) ^) Z/ e: x+ M' h/ B  l
  656.     for (i = 0; i < rbt->frame_count; i++)( k' Z, W/ W3 t& v! U& D
  657.     {
    4 O2 m# T8 m7 q1 p
  658.         /* read the entire frame (includes audio and video) */
    ; X* }! t6 P3 \- H
  659.         frame_size = LE_16(&rbt->frame_size_table[i*2]);) ~. K) J! a% Y. ?7 t) e
  660.         video_frame_size = LE_16(&rbt->video_frame_size_table[i*2]);
    ! p! Y% r, ~. N
  661.         audio_frame_size = frame_size - video_frame_size;
    . q. F( t. \: f% U: X
  662.         if (fread(rbt->frame_load_buffer, frame_size, 1, inrbt_file) != 1)
    3 A4 B* e9 b; J* a
  663.         {
    8 z. X8 n- [8 T. i0 N
  664.             printf("problem reading frame %d\n", i);: i7 ]# K6 \3 w5 w% m
  665.             return 0;& w6 ~$ W# e$ [& r# |" g
  666.         }- e& e. i- v+ ~# u0 Z

  667. . ]  m/ {" L8 b! _: A- ~! s
  668.         scale = rbt->frame_load_buffer[3];% e. d4 Q: k& m% \. T0 B; o
  669.         width = LE_16(&rbt->frame_load_buffer[4]);3 Q: G! j6 [/ i" B  a
  670.         if (max_width < width)
    2 V% j" q* S7 a; I% }
  671.             max_width = width;8 W2 q% y, y* _  C( q- f0 s* d
  672.         if (max_height < height)# P8 A/ g5 J' s
  673.             max_height = height;; W. r1 b' P/ h% |# K3 @
  674.         height = LE_16(&rbt->frame_load_buffer[6]);" P: n  A6 I1 L* c+ P
  675.         frame_x = LE_16(&rbt->frame_load_buffer[12]);
    # s; j  K; z# x/ c2 ]! U' ]3 h9 |8 o
  676.         frame_y = LE_16(&rbt->frame_load_buffer[14]);  D% {: H5 v) Q4 B, |7 k
  677.         fragment_count = LE_16(&rbt->frame_load_buffer[18]);
    # f1 Z5 }- Z# C/ S
  678.         decoded_size = width * height;
    6 x. s. e. H0 N  s" E8 `0 ?

  679. 4 W; {5 l+ ]1 ?9 q
  680.         printf("processing frame %d: %d%%, %dx%d, origin @ (%d, %d), %d fragments\n", i, scale, width, height, frame_x, frame_y, fragment_count);7 ]7 B8 F. t" k" z; e; U
  681. 4 \" ]2 z0 ?' D2 }" [
  682.         /* decode the frame */
    ! g: H2 k' T9 f4 m8 d. _6 K# v$ q/ n
  683.         decoded_frame = malloc(decoded_size);' x: W1 ?1 u% f/ U$ D
  684.         index = 24;
    - _0 I5 m7 @9 U4 n1 X# c
  685.         out_index = 0;
    4 u% X' i2 u1 G8 O0 U; e
  686.         for (fragment = 0; fragment < fragment_count; fragment++)1 y0 L9 L5 C$ @9 M
  687.         {% v+ V& `9 k! K2 i/ I" C9 }2 I7 f
  688.             fragment_compressed_size = LE_32(&rbt->frame_load_buffer[index]);9 l  ?9 D" {+ `' i4 B& f1 d& W
  689.             index += 4;! h: u: w; i+ t1 B
  690.             fragment_decompressed_size = LE_32(&rbt->frame_load_buffer[index]);
    8 W' G/ @/ c/ H/ V" U( o- M) w( T9 z# J
  691.             index += 4;# ]( a- F! g* L# b0 F$ {( a4 v
  692.             compression_type = LE_16(&rbt->frame_load_buffer[index]);
    5 W" `' `7 `3 Z3 D& m- H4 M
  693.             index += 2;5 m/ R: n; c+ ]! C* X

  694. ( x4 {, @; F5 O! ?8 ^0 q0 P# }' W1 w+ }9 u
  695.             if (compression_type == 0)( Q$ s/ g3 ?$ l; {/ `& t
  696.             {
    6 \; l' Q, b7 E2 s  q4 s: _) {8 X$ U$ r
  697.                 init_get_bits(&gb, &rbt->frame_load_buffer[index],% h. Y( ^$ D& ^8 C/ U8 e- w/ W
  698.                     fragment_compressed_size);/ [1 Q/ w) {( t: H$ ^
  699. 9 u. g$ u3 g4 B
  700.                 while (out_index < fragment_decompressed_size)  e& q0 Z# _3 g% f; B% q3 g8 `
  701.                 {6 i5 G# h0 T! ?
  702.                     if (read_bits(&gb, 1))' ]5 Q' I8 F  t+ R; U
  703.                     {
    0 z  e8 L/ c  ?" d
  704.                         /* decode back reference offset type */
    , J7 _# N" y' ?; M" y6 V: V- W
  705.                         back_ref_offset_type = read_bits(&gb, 1);! A3 N9 O6 U, \( a. I: n4 h, M+ H

  706. * f, m& ^: t8 P5 G% D' S8 u
  707.                         /* back reference offset is 7 or 11 bits */5 o7 b* c" v6 ~! _" L+ T8 H0 l9 {
  708.                         back_ref_offset = read_bits(&gb,
    / ]. m3 C0 o: m' \
  709.                             (back_ref_offset_type) ? 7 : 11);+ ^3 H& b$ h- v# G- @5 W
  710. 2 B3 q+ C! N5 q* A6 o
  711.                         /* get the length of the back reference */
    & H1 k; w; D# {  t- D  x5 E- H; t
  712.                         back_ref_length = get_lzs_back_ref_length(&gb);
    ' Y, E7 u( L$ b9 {3 G- R
  713.                         back_ref_start = out_index - back_ref_offset;
    6 o0 ~% S& v" \8 A
  714.                         back_ref_end = back_ref_start + back_ref_length;
    . E$ a4 g3 j0 E/ E8 }3 u

  715. ! z8 A: Y+ X/ l5 Z
  716.                         /* copy the back reference, byte by byte */" i; X" z; `( y# o
  717.                         for (j = back_ref_start; j < back_ref_end; j++)1 d; z) |/ s' K$ O" i: _. B, {
  718.                             decoded_frame[out_index++] = decoded_frame[j];7 s$ h* D1 E4 A  g) j
  719.                     }
    ; Y% f, S: ^1 d. |8 e' i. Z7 T
  720.                     else
    - S* x8 P( a0 p1 r
  721.                     {' D) Z: {  u& @: h: ?3 `
  722.                         /* read raw pixel byte */
    * r! V& M' o7 u
  723.                         decoded_frame[out_index++] = read_bits(&gb, 8) & 0xFF;
    " a* l$ w9 M" K' i8 i/ `1 {
  724.                     }
    ; x9 ?- y( ?/ J
  725.                 }  }9 a' I4 l- ?: p

  726. & ?; I0 n2 @$ X) ?, ~
  727.                 delete_get_bits(&gb);
      j: u( R: h# B; |- t1 p2 O- X
  728.             }, P; Q3 K0 `6 \9 T! O
  729. & J  E" B! d# x5 `0 }1 a. Q) C
  730.             /* next fragment */
    * J+ V' m  l) ]  m; A
  731.             index += fragment_compressed_size;
    2 d0 P& o9 }; b
  732.         }  r+ e6 O/ |: k7 q# S4 m

  733. / J4 x8 q( v- N
  734.         if (rbt->dump_frames)- c2 R1 J% f+ Q; m
  735.         {$ W6 B0 `4 x" ?
  736.             /* dump the original frame */
    4 h) I" V3 u) |1 m- O
  737.             sprintf(filename, "original-frame-%03d.pnm", i);9 I+ h) M8 P5 k0 ^$ x' G# D( S
  738.             dump_pnm_file(filename, rbt, decoded_frame, width, height);$ a$ k5 v) G2 n' k% E! z6 P# T
  739.         }
    0 m. ^- h4 _- f1 N3 O4 W, K' g1 d

  740. ! ~- I$ T- f/ f2 u' U2 J0 Q
  741.         /* transfer the image onto the frame window */$ ?5 H8 \2 d  }5 J
  742.         memset(full_window, 0xFF, full_window_size);! s4 i* D) K+ a. w3 X$ z$ g
  743.         index = 0;
    * r  I3 d/ v* `9 k7 K; X
  744.         for (y = 0; y < height; y++)* h" s! D; Y/ G9 x
  745.         {6 D# \7 p* L, {2 L# f2 G
  746.             out_index = window_width * (frame_y + y) + frame_x;
    * t  G2 @1 h7 a1 R
  747.             memcpy(&full_window[out_index], &decoded_frame[index], width);$ Y' V7 d- R( B4 ^
  748.             index += width;/ M1 }/ S: A  t- R+ B
  749.         }
    ) n1 @" W/ {  S0 ?- H# [

  750. ' h8 J. j0 ^% p9 P8 J5 P- s4 m
  751.         /* write the subtitle */
    & T1 c7 y" C9 Z
  752.         subtitle_frame(rbt, full_window, window_width, window_height,+ {; t2 v2 E& Q3 P
  753.             i * MILLISECONDS_PER_FRAME);1 O, J2 U* L& S8 J

  754. ! l* |: k+ N0 B+ [
  755.         /* figure out the smallest change window */
    . y  u$ \. {+ B& G" q# B
  756.         window_top = frame_y;4 \/ q. v2 i# Y' P
  757.         window_bottom = window_height;  f9 Z* @. b' E3 c" `
  758.         window_left = 0;$ [7 d4 C/ D9 e' p. a
  759.         window_right = window_width;9 l" t9 ~/ v4 g- Y
  760.         window_size = (window_right - window_left) * (window_bottom - window_top);6 O1 S$ u' S" q/ m$ A6 R1 z

  761. " T! @$ w4 ]0 J$ R2 s7 _
  762.         /* compress the frame */, H; l6 R2 r* @' ~' B1 e5 d
  763.         reset_put_bits(pb);
    ! o6 e- D. f  t0 U* {2 k
  764.         compress_window(pb, full_window, window_width, window_top,) c& f( T+ J0 `2 A  T
  765.             window_bottom, window_left, window_right);
    3 S% v" j/ B/ B5 h' `+ N, Z2 f
  766. , B  s* ~% O4 R( j+ B% ?
  767.         if (rbt->dump_frames)
    % r# Q* @1 O6 P' Q2 G( t
  768.         {) T2 q. G5 z  M1 V  n  \& j+ E  k
  769.             /* dump the frame plotted onto the full window prior to encoding,; L( R9 D9 I3 r" I
  770.              * with subtitle */
    2 w5 i& }' n2 p8 q* y  @9 Z7 H
  771.             sprintf(filename, "pre-encoding-frame-%03d.pnm", i);9 Z3 I! j( O- N4 D0 {
  772.             dump_pnm_file(filename, rbt, full_window, window_width, window_height);
    7 y+ @5 X- O' ^# Y2 ^) L
  773.         }
    $ Z0 r, O9 p7 h' q

  774. ) H, `7 |# i+ q- u* c" }( ?: K- o
  775.         free(decoded_frame);
    ( V" v! j! S: ^& p

  776. 3 I6 @6 U3 @; @) d
  777.         /* update the frame header */. A. Q9 E0 L0 n
  778.         /* width */
    % F1 u( E" ?, v  Q) ?+ J3 u0 P
  779.         rbt->frame_load_buffer[4] = (window_right - window_left) & 0xFF;
    & P6 B* z3 |9 F
  780.         rbt->frame_load_buffer[5] = (window_right - window_left) >> 8;
    5 O& t0 L/ n8 ~, l9 e  I: N, D
  781.         /* height */
    7 H$ E4 N7 e, U3 ?* F0 s9 X# j
  782.         rbt->frame_load_buffer[6] = (window_bottom - window_top) & 0xFF;
    6 J8 O, {; D) P
  783.         rbt->frame_load_buffer[7] = (window_bottom - window_top) >> 8;& V" p3 x. ^/ C  y
  784.         /* origin X */
    / R  D4 a8 e/ @8 g6 [
  785.         rbt->frame_load_buffer[12] = window_left & 0xFF;# s* M5 U& {! e5 D* N5 X
  786.         rbt->frame_load_buffer[13] = window_left >> 8;8 q& r+ \1 p% Q/ q5 G" N2 E
  787.         /* origin Y */
    0 G  m- R! `# y7 B" R
  788.         rbt->frame_load_buffer[14] = window_top & 0xFF;
    * N) b; J4 y" u+ `. D4 P8 r
  789.         rbt->frame_load_buffer[15] = window_top >> 8;
    3 y# L/ c$ @" Y% d5 B- w% B
  790.         /* fragment payload size */; X% f- @: Q! y, G
  791.         rbt->frame_load_buffer[16] = (pb->byte_index + 10) & 0xFF;/ v2 P1 D- U. R- Q& l+ A9 U
  792.         rbt->frame_load_buffer[17] = (pb->byte_index + 10) >> 8;. |- r2 B5 O+ Y! k: b* H- {# h
  793.         /* fragment count (1) */% ?+ B* y- O! B) t( j; m
  794.         rbt->frame_load_buffer[18] = 1;6 T, L1 i/ m9 S( g1 U% o
  795.         rbt->frame_load_buffer[19] = 0;9 j5 t) L/ W% o8 o$ R2 A/ v

  796. 9 v% H' m9 \* s3 _! C9 L
  797.         /* update the fragment header */6 D6 A3 q' @% i" q* N% d
  798.         /* compressed size */! W& v9 z8 R8 V
  799.         rbt->frame_load_buffer[24 + 0] = (pb->byte_index >>  0) & 0xFF;- K2 l5 J/ n! X' u2 f1 J
  800.         rbt->frame_load_buffer[24 + 1] = (pb->byte_index >>  8) & 0xFF;
    ' \8 \/ F! w8 c$ a1 X5 W2 ]
  801.         rbt->frame_load_buffer[24 + 2] = (pb->byte_index >> 16) & 0xFF;
    ' C$ f" [% \  w- A& E! @& }# |
  802.         rbt->frame_load_buffer[24 + 3] = (pb->byte_index >> 24) & 0xFF;
    9 m- h5 k2 Q* }& W8 [( y
  803.         /* decompressed size */3 \" M; T& o: K
  804.         rbt->frame_load_buffer[24 + 4] = (window_size >>  0) & 0xFF;' J2 a" z/ x; Z9 j
  805.         rbt->frame_load_buffer[24 + 5] = (window_size >>  8) & 0xFF;
    0 c5 `; |; J' {' n1 i
  806.         rbt->frame_load_buffer[24 + 6] = (window_size >> 16) & 0xFF;
    ' T+ m: o  `- n" l8 `
  807.         rbt->frame_load_buffer[24 + 7] = (window_size >> 24) & 0xFF;
    " v' `/ d7 E" e3 ~
  808.         /* compression format 0 */
    ! c5 n' Y4 ?  e
  809.         rbt->frame_load_buffer[24 + 8] = 0;
    + \) R+ P4 ~0 Z, Y
  810.         rbt->frame_load_buffer[24 + 9] = 0;
    8 O7 Y9 X8 ^' D# M" a, c( C$ z
  811. ) f5 k; F1 ?2 x' |$ C/ D
  812.         /* write the 24-byte frame header and the 10-byte fragment header */
    4 U. Z4 f# f0 o6 [/ p
  813.         if (fwrite(rbt->frame_load_buffer, 24 + 10, 1, outrbt_file) != 1)
    # b  N. I$ d& _; j, G
  814.         {
    6 Z: f- \8 f  s. t+ y8 z$ X4 q" Y
  815.             printf("problem writing frame %d\n", i);
    ' A- K' Z! I7 C: ]5 O- S
  816.             return 0;! @" n6 D1 [' V, @; K" a* `
  817.         }
    / f  J; p; S% s8 r/ M

  818. * D" u, w' l8 O6 }
  819.         /* write the new compressed frame data */
    ! {; G+ s. S  w& `' e
  820.         if (fwrite(pb->bytes, pb->byte_index, 1, outrbt_file) != 1)) t. X9 Y+ R: ^  v
  821.         {
    . w; l3 h2 H  |& D/ R: X6 L" j% y
  822.             printf("problem writing frame %d\n", i);
    , r) \7 p4 S6 ~. X) p7 e
  823.             return 0;! B1 H7 E9 w% g! U" D( {  J
  824.         }
    5 e8 w8 _# u! u& m
  825. - U5 s* j) A/ ?  T
  826.         /* write the audio data */# Q, ?2 f* T8 e0 G& v5 _
  827.         if (fwrite(&rbt->frame_load_buffer[video_frame_size], frame_size - video_frame_size, 1, outrbt_file) != 1)2 |: s" n# H$ W/ u& R
  828.         {' E  x, V+ ?5 D' o
  829.             printf("problem writing frame %d\n", i);
    $ B! i- M# j/ C2 N/ N
  830.             return 0;+ i- v8 q3 X: P/ H
  831.         }
    / K8 E0 j3 h2 D; l
  832. 9 w. x: z3 f& P) t9 T6 d) R2 U
  833.         /* update the table entries */2 X/ b- G; R- }# |* k% }
  834.         video_frame_size = pb->byte_index + 24 + 10;. j2 I; Q2 W/ S+ @
  835.         frame_size = video_frame_size + audio_frame_size;
    6 G9 h4 Y" \, b& e( l; p
  836.         rbt->frame_size_table[i*2+0] = frame_size & 0xFF;
    . z, r& Q" b; \3 r( l" S2 Y) ~
  837.         rbt->frame_size_table[i*2+1] = frame_size >> 8;
    3 `& [; {5 {4 r% L) X  Y
  838.         rbt->video_frame_size_table[i*2+0] = video_frame_size & 0xFF;! L0 a: Y/ |& h: f9 ]
  839.         rbt->video_frame_size_table[i*2+1] = video_frame_size >> 8;0 `+ K2 c( C  T$ A" a& ~
  840.     }  r6 u! I" D  N& R

  841. . ]  ?, P: e  V$ `$ d
  842.     printf("maximum dimensions seen are %dx%d\n", max_width, max_height);
    2 q& Z& y" u3 k) p) k& A! w
  843. " V5 j4 N0 w0 K# _
  844.     delete_put_bits(pb);
    1 f) i5 D; X% }" W8 L( y: m
  845.     free(full_window);
    & m8 H1 {  Q5 @# }5 [

  846. 0 k/ d7 R6 }: ^
  847.     return 1;
    ; f" N9 K( v/ m" _, H" y, l
  848. }6 ], Y+ I1 b8 L- |! G7 Y# N9 v9 V' L

  849. - Y, A: w! ]4 r
  850. int main(int argc, char *argv[])
    4 c7 Z; H+ M& M' j: ~9 K! J
  851. {
    % s. }$ u# m! e+ m7 ^
  852.     char *subtitle_filename;/ f# a# M9 _/ S3 \, {# p2 @
  853.     FILE *subtitle_file;$ a2 c4 l2 \! @0 [% Y
  854.     char *inrbt_filename;
    : u( u8 |, @+ t$ x2 Q2 x) i
  855.     FILE *inrbt_file;. s7 m% \+ }7 J) B
  856.     char *outrbt_filename;
    ( a, [0 A5 P, V. R# V7 j  I- W
  857.     FILE *outrbt_file;
    6 w% a  b+ G- `; E7 Y) r; h
  858.     rbt_dec_context rbt;0 N& x7 a' [* s
  859.     int origin_x;' F* u9 E; a$ h) ~" C* ^
  860.     int origin_y;8 L7 i" [1 E5 b, y  C6 }3 n
  861.     int window_width;/ Z7 W8 ]" t$ \) ^
  862.     int window_height;) f+ \) N4 b- z3 C
  863. 2 x  U4 z4 K* g4 e! b* v
  864.     /* testing the bit functions */; x+ v2 V4 T2 d: p: F( W
  865. #if 0' J* \) ~" N" P/ w+ S/ y
  866.     int i;
    ' `4 s% O5 ~! P8 N8 A* c
  867.     uint8_t bytestream[] = { 0x55, 0xAA, 0x00, 0xAA, 0x55, 0x77, 0xFF, 0x1B, 0x70, 0x8F };+ A2 T5 _2 j+ Q9 ^& h& ?6 f3 R
  868.     int bytestream_size = 10;0 s# K2 }7 @; i+ k5 U' s
  869.     get_bits_context gb;
    , }, M! N5 w) W7 I4 Q8 g( r! B( t3 A
  870.     put_bits_context *pb;6 o5 k9 `* ~+ n( Y8 r
  871.     int bits;
    % H& H" G3 K+ {! |# C
  872. 3 E' [- ~! L3 o1 T' y6 r
  873.     init_get_bits(&gb, bytestream, bytestream_size);! F; [$ C8 W& R) ~' X3 U6 S& v. }
  874.     pb = init_put_bits();0 k7 ^% \5 \7 v/ ^
  875. : i  ~: B1 g1 h& P
  876.     for (i = 1; i <= 12; i++). G2 B: V& v9 Y! J9 W* D1 ~( N
  877.     {% q+ W( A: x& k  ?9 y7 x$ N7 _
  878.         bits = view_bits(&gb, i);; U* h. {# \* ^! _/ b, B: L
  879.         printf("view %d bits: %d\n", i, bits);
    1 M5 F- N$ _* e( X  N
  880.         printf("read %d bits: %d\n", i, read_bits(&gb, i));* C1 g; d5 Q: K5 Y1 T# d- f
  881.         put_bits(pb, bits, i);4 I9 W! R  C1 Z+ o( K8 O0 k
  882.     }
    ; `, Z6 Z- J. F* r( T9 ]
  883.     put_bits_flush(pb);3 ?$ V. L6 ^" }! D9 L6 G

  884.   a0 w8 L8 b$ d, R' S6 X5 e+ C
  885.     printf("original bytestream:\n");5 H1 {+ p! _7 N, c/ K1 `3 n  x
  886.     for (i = 0; i < bytestream_size; i++)6 z$ h& S* |! o" V
  887.         printf(" %02X", bytestream[i]);2 S% n; s/ s: f: L3 {# m- @; T
  888.     printf("\nnewbytestream:\n");: U6 B$ X! h& C7 ~* ?* a
  889.     for (i = 0; i < pb->byte_index; i++)
    5 Y( r0 |/ S& _) J$ j9 D
  890.         printf(" %02X", pb->bytes[i]);1 {  Q1 x; N2 T% @" {9 C7 x
  891.     printf("\n");
    ' H4 S8 S: C6 h8 a7 i) a/ Z) I

  892. 6 f5 }, j: x" C. M
  893.     delete_get_bits(&gb);8 A) q  w! Y9 r4 ~3 W; r
  894.     free(pb);6 }% c2 O8 e$ [
  895. #endif
      ]' f% L0 R* b( S  I6 ~+ s9 A- |

  896. " F+ b/ y& B& ~
  897.     /* validate the number of arguments */  J: l4 y& k/ P  D
  898.     if (argc != 8 && argc != 9)
    ( Z0 F& U( z1 E  h/ U) i0 o' ^
  899.     {
    ' h, D% t0 M7 ?7 t( e
  900.         printf("USAGE: subtitle-rbt <subtitles.ass> <in.rbt> <out.rbt> <origin X> <origin Y> <width> <height> [dump_frames]\n");
    $ ~! n+ M( ~* c1 h0 U) k
  901.         return 1;
    ; _5 P1 L6 S# d/ r
  902.     }$ q! K, d% V- s
  903.     subtitle_filename = argv[1];( Z1 F% c8 W) c" `2 g. r7 Z
  904.     inrbt_filename = argv[2];
    % g) Z4 G, M1 V8 e+ N0 g& y6 Y
  905.     outrbt_filename = argv[3];
    + a% v) Y) Q" g; }6 ^8 L. n! E
  906.     origin_x = atoi(argv[4]);1 t! d; E! A+ n/ V5 }4 n
  907.     origin_y = atoi(argv[5]);- ]2 ^! y, {* i. H% c+ b
  908.     window_width = atoi(argv[6]);1 s: K( V5 ~4 E2 ]$ c* h
  909.     window_height = atoi(argv[7]);7 ]0 p( C' _/ y+ y' U" f( h  V
  910.     rbt.dump_frames = 0;% Q5 t2 |. m: J% ^* _3 w* c+ v
  911.     if (argc == 9)2 X. U% ?* E4 w1 `# ]6 U; b+ ~
  912.         rbt.dump_frames = 1;1 p. t" C8 P  c& W% z

  913. % k6 L! _: P" T
  914.     /* verify that the specified input files are valid */& p6 g$ |/ V& c6 g( S4 A
  915.     subtitle_file = fopen(subtitle_filename, "r");
    : R  k% V! K' b3 ~% N; M8 E0 L
  916.     if (!subtitle_file)
    + U: z6 L) O+ J+ p! P
  917.     {
    - \  b- H2 w, k
  918.         perror(subtitle_filename);
    : l5 r! e2 R6 o& N! q
  919.         return 1;9 Z8 t3 x- Q, W
  920.     }2 U) k+ \3 E- V4 S
  921.     fclose(subtitle_file);1 J. S. B/ j9 j/ d
  922.     inrbt_file = fopen(inrbt_filename, "rb");" l% C2 V* p# y7 B9 S+ W
  923.     if (!inrbt_file)
    7 {3 a2 [2 d$ s, E9 o5 o
  924.     {
    / a4 H3 X3 U7 @
  925.         perror(inrbt_filename);$ v/ ^% U; u& O: q2 u: _
  926.         return 1;8 p* }4 m7 J0 G' }& v
  927.     }
    ' V$ ]1 {" c4 ~( H. M7 A8 o
  928. ' k* v) q1 Z1 B# n' P) f
  929.     /* initialize the subtitle support */
    % {: R: m. G* H% G
  930.     rbt.ass_lib = ass_library_init();) l* j( i9 |  y6 j8 y
  931.     rbt.ass_renderer = ass_renderer_init(rbt.ass_lib);9 B8 G* D/ x& e% Y
  932.     rbt.ass_track = ass_read_file(rbt.ass_lib, subtitle_filename, "UTF-8");+ Q$ Q0 k+ o9 j! |$ {1 l. L
  933.     ass_set_frame_size(rbt.ass_renderer, window_width, window_height);
    # t5 m; n  o' K
  934.     ass_set_fonts(rbt.ass_renderer, NULL, NULL, 1, NULL, 1);
    ; m! l5 s2 U* e4 w6 @' D
  935. / [1 z+ e/ N; h; D7 ?
  936.     /* open the output file */
    8 _9 S; f/ n. g$ L' g& C, `- A
  937.     outrbt_file = fopen(outrbt_filename, "wb");
    ; x, B7 X6 {6 i9 l# K6 z  V. R
  938.     if (!outrbt_file)  N* h( C* I+ E6 e8 t
  939.     {
    ) @' ^* p- k* U
  940.         perror(outrbt_filename);
    4 A# }$ E, ], r# ~
  941.         return 1;  b5 T: Z# Z6 O! H: }
  942.     }
    7 i7 @, a' T2 `) Y% v% Y; s

  943. ( ]" r0 u3 X* a( n  K' v4 b
  944.     /* transfer header from input to output */
    3 Y9 i7 y: V& ?  a5 `# {
  945.     if (!load_and_copy_rbt_header(&rbt, inrbt_file, outrbt_file)). U3 i" ~: d) E" E
  946.         return 1;" V* A# `& h0 x& g& D$ K% F

  947. : i' v% c  n  d
  948.     /* rewrite the frames */
    8 E! {2 W, _; r7 l
  949.     if (!copy_frames(&rbt, inrbt_file, outrbt_file, origin_x, origin_y,
    1 \6 r( P) `! b. ]
  950.         window_width, window_height))# }" E% v9 m- M6 V% ]0 R* n
  951.         return 1;/ J& p: ~7 {  Y$ H4 m

  952. 5 Z# n7 C9 U* s3 D
  953.     /* write the modified frame size tables back to the file */4 \4 G) r& |4 U. ^& a1 l
  954.     fseek(outrbt_file, rbt.video_frame_size_table_offset, SEEK_SET);' s* F5 q9 v( U+ v
  955.     fwrite(rbt.video_frame_size_table, rbt.frame_count * sizeof(uint16_t), 1, outrbt_file);4 O3 t6 H+ q. H/ U) O% q! T) C
  956.     fseek(outrbt_file, rbt.frame_size_table_offset, SEEK_SET);' g% l, f% s: ]
  957.     fwrite(rbt.frame_size_table, rbt.frame_count * sizeof(uint16_t), 1, outrbt_file);
    6 e. p* T7 k7 m" r9 M& ^* ~& x: Y
  958. ( S  ?8 o9 v* N
  959.     /* finished with files */9 v+ s) C% [" O& {) Y
  960.     fclose(inrbt_file);# P) q: z- s( t/ M; Z# C- W
  961.     fclose(outrbt_file);  a1 {0 t( t$ t5 `

  962. 1 i) R  O& H6 `6 Z& y
  963.     /* clean up subtitle library */* c% @8 Q2 k  W% T. K5 y! F2 `, G# p
  964.     ass_free_track(rbt.ass_track);* i1 Z$ _2 z, j9 W( R1 t
  965.     ass_renderer_done(rbt.ass_renderer);( o% h7 z; E4 w8 i
  966.     ass_library_done(rbt.ass_lib);
    7 t# E: N: G, P; O) F
  967. ' z0 v& Q" k7 i! g" _
  968.     /* clean up */3 B" Y& K0 a/ }7 _  X, P$ z
  969.     free(rbt.frame_load_buffer);
    ! P" P7 Z0 E( ^3 ]
  970.     free(rbt.video_frame_size_table);3 s2 t/ t, `9 E1 F- u8 ~( N
  971.     free(rbt.frame_size_table);/ q, |/ e& ?3 _1 W8 w: K
  972. $ e# P8 \; b4 a1 G* l* q* `
  973.     return 0;
    % i7 P5 J: ~4 R2 C5 p
  974. }
复制代码
6 f& u% R- ]) J  F: H( S5 ]. m& ^" v

; J* M6 p( {- z3 ~: X1 G3 c- W8 ]: L8 }/ b

8 N/ G+ L9 r1 {7 {$ d
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 很美好很美好 很差劲很差劲
回复

使用道具 举报

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

使用道具 举报

板凳
 楼主| 发表于 2009-11-19 11:38 | 只看该作者
引用第1楼soring123于2009-11-19 11:09发表的  :! f6 \# c: N' o/ q) O3 P9 x5 t1 j
这游戏有字幕吗?
! p3 E8 M0 a, |2 ?2 m
好像没有字幕,我说的是给视频外挂字幕方式的汉化。  @1 F* i8 ?0 F& l* P/ q+ F
就像syberia2汉化版下面那行字一样。
回复 支持 反对

使用道具 举报

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

使用道具 举报

5#
 楼主| 发表于 2009-11-19 17:39 | 只看该作者
引用第3楼soring123于2009-11-19 17:07发表的  :
  Z, t* u4 D& n- @8 u( Y9 |  T我记得是没字幕的 比较麻烦 都是视频的

+ T: G+ @% i# O, T给视频外挂字幕方式汉化也许能行。# |$ L9 w( R* ?6 R
要结合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日,是全球华人共同的冒险解谜类游戏家园。我们致力于提供各类冒险游戏资讯供大家学习交流。本站所有资源均不用于商业用途。

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