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

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

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

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

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

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

本帖最后由 shane007 于 2021-1-2 13:56 编辑
8 V8 k7 c/ z7 g9 u6 f8 @: c7 W& j7 v" X& Z; i! y/ W- T
最近找到了一些和幽魂系列Phantasmagoria 有关的资料,
6 o1 A: O& V3 V% ?$ B- E  m  b% M也许将来可以用于汉化。
8 f& b8 ?* S* d7 a, w
+ v) Y9 X1 S$ h. L, Y和日文版有关的信息
7 q. G$ R: @& R9 M# ]; r! `http://anthonylarme.tripod.com/phantas/phintgtp.html" n. m, d" C% ]; @7 k0 P
/ c1 ^% F$ `0 q# ], g- Y& v
相关工具
) L( Y" m% e8 V" V9 Nhttp://anthonylarme.tripod.com/phantas/phcheats.html
* G. y, \! h, l: F0 P% V-----------------------------------------------------------------------8 l( p* `  I8 ]0 o6 B: J* W9 x
2012/1/2  更新/ k4 a1 C; U! Q
关于幽魂游戏的字幕
/ w# Y. u2 X/ s5 R# w3 w" p7 V7 YPhantasmagoria subtitles function discovered - ScummVM :: Forums9 p: [* ^* p$ F1 z

% K( [; N% Z- ~  p& @! K, AVMD文件! h$ _- r8 ?9 s
Subtitling Sierra VMD Files | Breaking Eggs And Making Omelettes (multimedia.cx)VMD - MultimediaWiki: ]2 B0 Y3 _4 p, ~

: r4 X9 ]; ?" o% F" f8 O字幕* e% B! V; J. _" `
Subtitling Sierra RBT Files | Breaking Eggs And Making Omelettes (multimedia.cx)
( x$ V5 ?) b: V: h% f$ V' _% o0 d
, J" E) u6 F9 |& e1 y# G0 XFFmpeg/subtitle-rbt.c at feature/VMD_encoder · multimediamike/FFmpeg · GitHub
+ O4 ?4 W/ \, w, o5 d" Y
  1. /*
    ; @1 c$ O+ ~+ e5 T% M' o
  2. * subtitle-rbt.c
    & C9 K1 I. E  H4 F, U) ~. L
  3. *  by Mike Melanson (mike -at- multimedia.cx)
    5 [0 H7 c' h% y1 Q
  4. *
    6 n- L+ l; Q8 [
  5. * build with this command:1 t7 p' [3 ]) j% F+ R
  6. *   gcc -g -Wall subtitle-rbt.c -o subtitle-rbt -lm -lass6 B) W8 N* Y% i9 v" W+ |
  7. */
    " k- D8 q4 U4 U; f# i3 C

  8. . C" D2 x5 f4 O
  9. #include <inttypes.h>8 A. c7 B5 d3 s* B
  10. #include <math.h>  U, D8 b0 ]1 I- G$ Q; _- T
  11. #include <stdio.h>  H* J: C7 {- Z6 I# D  C
  12. #include <stdlib.h>% }, A+ y8 E2 u
  13. #include <string.h>
    ; H- d6 M' }! `6 H
  14. 1 f4 t. ^, v) j4 o0 y
  15. #include <ass/ass.h>* S; z  q& B4 T9 f

  16. 1 I+ n: q$ e9 L
  17. #define LE_16(x) ((((uint8_t*)(x))[1] <<  8) | ((uint8_t*)(x))[0])
    / p" c  P- T& u8 W7 i

  18. . l$ U) H0 C4 H: ^, D: N
  19. #define LE_32(x) (((uint32_t)(((uint8_t*)(x))[3]) << 24) |  \) s/ P) M1 T8 D  j( e+ W
  20.                              (((uint8_t*)(x))[2]  << 16) |  \  V$ P4 C" c) P3 u+ b0 g! o
  21.                              (((uint8_t*)(x))[1]  <<  8) |  \$ r0 k. Z$ t! _* m6 N( g+ n( m
  22.                               ((uint8_t*)(x))[0])7 }) V0 {+ [( y9 B; m

  23. , u9 d+ h' X, z  P# D
  24. /*********************************************************************/
    - M. M& o( {) I5 o* s6 ~- V
  25. ' k! q* U0 p4 p$ f% ~. q4 D
  26. /* Bit reader stuff */- M7 N; F8 t8 [% r  N
  27. / F8 U/ B# n; ~0 w3 H5 j
  28. typedef struct
    0 h3 j! B  w: V9 Q3 v
  29. {
    1 Q5 [4 Q9 r4 e/ ~
  30.     uint8_t *bytestream;
    + _" M. d" m; o) c9 u5 ]
  31.     int bytestream_size;. e' z$ I* }4 G. f% O9 j; L9 Q
  32.     int index;
    4 L, g! O; L- I1 R: @0 g
  33.     uint32_t bits;6 a/ Z+ n/ O  N  c% r  A
  34.     int bits_in_buffer;( G$ x6 n' D( i: r6 G% e6 L
  35. } get_bits_context;. _5 M+ R' A% @9 x% U
  36.   [. v5 q3 M3 J: d+ d: A
  37. static inline void reload_bits(get_bits_context *gb)2 C( v# n( \- o! z9 F  K6 x) g. n$ K3 k4 U
  38. {: E1 P. F* v7 e( b! [$ W
  39.     while (gb->bits_in_buffer <= 24)
    " }' t& c7 ]( C% ^4 `' ?, _
  40.     {
    ! J, `% q( u1 V. b! O# P) t
  41.         if (gb->index < gb->bytestream_size)$ H2 U6 T9 P  O2 ^3 ~+ w. p6 r" s' @
  42.             gb->bits |= (gb->bytestream[gb->index++] << (24 - gb->bits_in_buffer));
    0 G" U# i% c# Y8 Y2 X. r' z' H" Q7 r
  43.         gb->bits_in_buffer += 8;
    0 t* w0 A5 B* r  S* m- x+ r
  44.     }8 F' D4 c1 T9 O& Q# z& x! v! `6 P
  45. }
    ; A, c& G) }3 V- X$ L! X2 m

  46. 5 t4 G; R- h* g1 X
  47. static void init_get_bits(get_bits_context *gb, uint8_t *bytestream, int size)
    5 @. K* O/ I8 m  P7 ]6 H
  48. {
    4 Q/ D0 q( b* m" `. w6 V, q
  49.     gb->bytestream = malloc(size);& i; y1 s- z5 \" U: |
  50.     memcpy(gb->bytestream, bytestream, size);+ |/ f& c3 X& z8 `4 t1 |
  51.     gb->bytestream_size = size;
    , n5 I1 v8 x$ l; l0 d5 x# }3 L/ i
  52.     gb->index = 0;7 d4 x1 c/ u0 C6 h! U- f
  53.     gb->bits = 0;# S' f/ D2 q4 I8 \
  54.     gb->bits_in_buffer = 0;0 b4 y( x8 m- Z5 t  s! D

  55. 2 ?; o& d, @+ N$ K, J5 k
  56.     reload_bits(gb);" d2 _$ F- F5 k3 `
  57. }
    . f7 a1 B/ A1 v% g: `$ ]
  58. 1 w: x# t/ G4 C& s! s: j
  59. /* read bits without consuming them from the stream */
    * l% |9 l3 ?' h
  60. static int view_bits(get_bits_context *gb, int count)/ y# r) ?3 K. o  ~
  61. {
    / g# R/ G6 T8 z8 Q. t0 |6 g
  62.     if (count >= 24)- d. W7 E# _! F. ]! l* o& Q
  63.         return -1;
    & F; @2 t3 D5 {, T6 i+ n" }& w
  64.     if (gb->bits_in_buffer < count)
    . D# W1 \/ [+ d* D2 |
  65.         reload_bits(gb);" D; ~$ `8 a' F  r, R
  66.     return (gb->bits >> (32 - count));
    6 G! u5 P% \/ Z5 ~5 S" a: G
  67. }
    $ {4 B. r7 l6 L
  68. 6 L4 l$ z. U6 M: D; S  S
  69. /* read and consume bits from the stream */
    " r% H# ?0 x2 ^- T
  70. static int read_bits(get_bits_context *gb, int count)7 c2 N9 k- E: v3 J3 z
  71. {4 p6 q$ T7 U7 G4 |; i$ `
  72.     int value;9 f7 G8 `. j, _; N
  73. 6 ]6 V( I- E2 r% |0 G7 D
  74.     if (count >= 24)
    $ ?. T& c% T+ N% D
  75.         return -1;0 ~! n* ]6 m; Y* c# Z

  76. 9 L( i- L/ `+ h
  77.     value = view_bits(gb, count);6 V8 ~) v# @7 ]2 ^8 E
  78.     gb->bits <<= count;
    5 C' X+ w0 q1 t+ @2 ^& a$ P7 S
  79.     gb->bits_in_buffer -= count;8 }3 @# X4 c6 Z! `3 x/ ]

  80. 7 f7 |. r2 e5 r; ?6 C
  81.     return value;  ~1 g8 ~9 m2 U8 f/ e, E9 x6 P2 n
  82. }
    ( ^# P. ]* ?+ g" a* [
  83. ; `- A$ l+ ~" t+ X9 d
  84. static void delete_get_bits(get_bits_context *gb)8 r% a7 h( t- B
  85. {
    3 ?) C  v' E" |
  86.     free(gb->bytestream);8 v" |4 _5 Z: g* x" j) D4 ~% q1 F
  87. }2 t! V" @7 u7 x6 G- o

  88. , z3 w1 A7 N0 E( a( Y
  89. /*********************************************************************/
    ' H# r2 P4 @# I8 k4 U6 g$ X

  90. 8 n" }8 R# G+ X8 |
  91. /* Bit writer stuff */3 X# V/ }4 y3 i' N- a0 k
  92. 8 Q8 N. x7 ~3 ~1 s& H* V
  93. #define MAX_PUT_BITS_BYTES 630002 K) ^) G. C0 G& G# `
  94. typedef struct% [- T1 c* J- u0 i8 N
  95. {
    ) r6 h' {9 [; A6 Q# [5 A7 h; `
  96.     uint8_t bytes[MAX_PUT_BITS_BYTES];5 O  f% ?1 F0 G3 ]  ?$ }* k
  97.     int byte_index;
    . A5 G0 C* {' N5 s2 a( X- L
  98.     uint32_t bit_buffer;7 H! K7 i6 s2 b, ^/ y+ c# O: Z
  99.     int bits_buffered;
    ( J" l. P5 c* S6 [
  100. } put_bits_context;3 s0 c1 C. E5 T0 e, o+ `, q
  101. 0 W! R1 y; [& H% D8 r4 X' Y
  102. static void reset_put_bits(put_bits_context *pb)5 @6 c  D2 e; V  ~( n5 j: i
  103. {
    % i5 h$ K* g$ t, H6 G7 O; O
  104.     memset(pb->bytes, 0, MAX_PUT_BITS_BYTES);2 N# n* S6 ?' N: f% K5 ~' c
  105.     pb->byte_index = 0;
    3 s* o  @$ F$ d, P
  106.     pb->bit_buffer = 0;. ^/ d( k9 o# z$ c9 L  L
  107.     pb->bits_buffered = 0;1 l& t( ]6 f5 s! J
  108. }( G$ f8 H: p/ y/ K# B4 L. Y; v! J: s9 `
  109. 0 o' E) ?. Z' J1 _; a# d* X6 F
  110. static put_bits_context *init_put_bits()
    2 D- L: P! A. q
  111. {2 s8 e& \2 p  E) s$ o
  112.     put_bits_context *pb;
    7 h& v; @# q% ~* d. A
  113. ) a0 |) g% U, Y; ~, P# o9 {2 w
  114.     pb = malloc(sizeof(put_bits_context));1 X* T' \! P* S" w. g& ^
  115.     reset_put_bits(pb);
    + W& T) [& ?: }
  116. 9 q  a, Z$ ^& R9 S: J  K4 o
  117.     return pb;( Y7 W& F$ F- l9 P" M8 S
  118. }
    - s) {, `9 A1 z" a
  119. - v4 |: w% ~  c  p( {, S6 a
  120. static void put_bits(put_bits_context *pb, int bits, int count), |& s' P& w; y8 d
  121. {
    # M/ b* _& ]/ u. H8 c
  122.     pb->bit_buffer <<= count;: z) G3 }2 T  G6 S! p: ?/ B5 N
  123.     pb->bit_buffer |= (bits & (~(0xFFFFFFFF << count)));
    / v$ K1 K4 t$ z" k- j* v
  124.     pb->bits_buffered += count;. `! u3 H! ~8 v8 S) q
  125. ' D5 k3 b0 b# z
  126.     while (pb->bits_buffered >= 8)
    ! m. T4 N, ^% ]4 [6 x9 w" m
  127.     {
    % R8 f) H; x6 i. e
  128.         pb->bytes[pb->byte_index++] = pb->bit_buffer >> (pb->bits_buffered - 8);9 `  J8 Q, l; q2 J0 P& N; H) S) `
  129.         pb->bit_buffer &= (~(0xFFFFFFFF << (pb->bits_buffered - 8)));; o( H$ ^1 g9 c! L
  130.         pb->bits_buffered -= 8;
      m) p9 @8 l7 e! y9 R( w  L# p
  131.     }5 V( F1 Z5 I8 i, _; y) ]8 K
  132. & v" c# T1 ~6 l$ Q
  133.     if (pb->byte_index >= MAX_PUT_BITS_BYTES)1 _! m3 }0 [+ O2 _: J# n
  134.     {7 \0 e6 y. f4 J) F. {8 O
  135.         printf("HELP! Bit overflow\n");+ r& e3 F3 E( ]. X: n
  136.         exit(1);
    ; M! ?: J5 y2 |% \0 Q2 O2 d
  137.     }
    5 C; W2 ^0 K* L( p2 P( a9 E6 `, X
  138. }! \# [  u1 Q/ J# O2 ~
  139. & A% I  B% t+ q8 p9 d
  140. static void put_bits_flush(put_bits_context *pb)
    6 E: a9 n5 d% I2 X' W+ q
  141. {" G& p8 _. L# \  I4 E% Z6 }
  142.     if (pb->bits_buffered > 0)
    6 Y) ~7 C  B% [* y8 }1 N
  143.         pb->bytes[pb->byte_index++] = pb->bit_buffer << (8 - pb->bits_buffered);$ r+ z" R/ ~6 {' a: N$ g) U+ {, @
  144. }
    4 I! p9 W% e7 G$ n$ z! @
  145. ; l: |" q) M4 q3 @1 ?7 v
  146. static void delete_put_bits(put_bits_context *pb)
      @8 J6 q2 Q% M1 r
  147. {
    8 J& _% O0 D( X: u
  148.     free(pb->bytes);6 V6 O* {, g4 x2 r! A5 G
  149. }
    8 ^/ n  C/ U2 W- p* m/ ~1 a% A

  150. # O- B2 p! ~( c$ {, V5 d, Q, D
  151. /*********************************************************************/, ?! V0 d# M) j) W
  152. 8 w0 Q0 q8 ]) `; m2 `
  153. /* RBT functions */
    & N1 S4 }# U& c) S
  154. " W; {( _( R* g" o# O
  155. #define PALETTE_COUNT 256
    ) D: m# t9 [" ^" z
  156. #define RBT_HEADER_SIZE 60
    + G" \0 ~; C1 @2 E
  157. #define UNKNOWN_TABLE_SIZE (1024+512)3 q6 I5 i$ J" v! D) ~* _! H
  158. #define SUBTITLE_THRESHOLD 0x70# n- q/ f+ e7 B. a: k
  159. #define MILLISECONDS_PER_FRAME 100
    1 [( _" X0 `1 @# j' |% T0 W2 a
  160. : [! ?, i0 }7 T+ e8 b: Z
  161. /* VLC table */
    , |! u: U9 q& G
  162. #define VLC_SIZE 47 T2 `1 @( D) {
  163. static struct
    / M( _3 b0 v2 I
  164. {
    ; u2 z7 m* b' N, l; B- L
  165.     int count;, D- V. n+ V- D3 R
  166.     int value;2 c2 O' [  J9 u+ B6 y
  167. } lzs_vlc_table[] =- U* `# B! l( x( s# c: Y( |
  168. {
    ' i  H$ M! p/ ^6 g& f
  169.     /* code length = 2 bits; value = 2 */
    ; `9 o5 @  x: d( {6 _! D
  170.     /* 0000 */ { 2, 2 },
    7 D6 {* K* j- W8 l9 L! e
  171.     /* 0001 */ { 2, 2 },
    1 R' G& _  d  E' X* b
  172.     /* 0010 */ { 2, 2 },3 ]9 Z: E, }% z1 S0 P0 _4 @
  173.     /* 0011 */ { 2, 2 }," C, b& I( N$ G5 J  \8 I
  174. 7 v2 Z  R1 |7 r- L5 l% u" d
  175.     /* code length = 2 bits; value = 3 */
    # ]$ ~+ }* D3 v0 ?9 a8 D
  176.     /* 0100 */ { 2, 3 },
    % x- P& E" g0 U1 ~; z8 B
  177.     /* 0101 */ { 2, 3 },% A+ q9 o+ s% U8 n/ ~; r3 q3 b
  178.     /* 0110 */ { 2, 3 },
    # L' }: ~: _4 R) C4 I. T
  179.     /* 0111 */ { 2, 3 },
    $ z( l2 N. j' K0 k0 c

  180.   J) ^3 P3 _3 l& X6 D2 z
  181.     /* code length = 2 bits; value = 4 */! E- F1 u  O$ ]0 e! a/ S, X
  182.     /* 1000 */ { 2, 4 },# Q. l2 P7 C$ C
  183.     /* 1001 */ { 2, 4 },
    ; R; m' U, z3 @* Q( H' I
  184.     /* 1010 */ { 2, 4 },8 g& Z* F/ k- t, n# h
  185.     /* 1011 */ { 2, 4 },
    $ Z/ Z+ J0 q/ j: r! q5 |( x

  186. 6 i5 Y( n1 g; D7 Z% ~
  187.     /* code length = 4 bits; value = 5 */
    7 L0 s% i+ h5 S+ c
  188.     /* 1100 */ { 4, 5 },& ~' Z! W1 w& l; A5 {9 v

  189. - k9 c1 [$ k7 m2 d& g0 j/ L4 z
  190.     /* code length = 4 bits; value = 6 */
    - J3 D! r0 G5 ^  w2 A% H
  191.     /* 1101 */ { 4, 6 },' D+ `  p8 u/ B% q4 _% m6 p
  192. ) h; \, B$ s! V+ ?7 A' z
  193.     /* code length = 4 bits; value = 7 */4 q: N* ~. a# Z
  194.     /* 1110 */ { 4, 7 },# L- H" @' k* k

  195.   ?2 |( ]/ Z8 o# x1 F  Z3 [7 t
  196.     /* special case */' y/ s9 p8 M( }8 X+ o0 K, ~
  197.     /* 1111 */ { 4, 8 }' a( e+ Q! k4 V/ @& U6 c
  198. };
    " R3 D. h1 \6 M# X
  199. + T' z6 E9 Q6 m2 I* V4 I
  200. typedef struct( ]/ V' H" c0 l2 i
  201. {
    / T9 ^- K6 u; i/ S6 t8 V
  202.     int version;: p. B1 T0 w1 b+ @3 j+ g, o# a4 |. I1 Z
  203.     int width;
    / e7 N. u9 q, I2 o% q
  204.     int height;
    , a& |# H# i' O1 x2 |, [
  205.     int frame_count;
    4 t8 ~" \" }' N6 e* Q
  206.     int audio_chunk_size;
    9 w  f# W! b6 Z8 A, {4 n8 y
  207.     uint8_t palette[PALETTE_COUNT * 3];! _  \4 I, C0 G8 x6 F6 ~" q
  208.     off_t video_frame_size_table_offset;
    8 L/ t3 |/ V! j* T) K! L# ]2 n
  209.     uint8_t *video_frame_size_table;2 U; F* ]3 n9 K
  210.     off_t frame_size_table_offset;. D# ^1 c* d) a) u+ ?' C8 M
  211.     uint8_t *frame_size_table;9 |4 P$ v! R  z* X% e. a' @
  212.     uint8_t *frame_load_buffer;
    + M5 ]" ^& y7 m/ I
  213.     int dump_frames;" M. ]+ N9 B5 k% }
  214. / m% z7 `* Q! z% J$ ^9 l' k
  215.     /* subtitle library */; l! V. _" f4 n7 J  @
  216.     ASS_Library *ass_lib;# q: B" E% w5 r$ [3 v
  217.     ASS_Renderer *ass_renderer;4 D1 r8 `7 I5 t- o; C3 X
  218.     ASS_Track *ass_track;
    # a% m  Q2 M5 Q) i; R+ n/ c7 {2 |
  219. } rbt_dec_context;
    ; A5 Q' r& v$ P$ y

  220. 8 B: S' _& G6 [  E7 A; n
  221. static void dump_pnm_file(char *filename, rbt_dec_context *rbt,
    3 h- X9 {3 T) }- t% N5 `
  222.     uint8_t *image, int width, int height)
    8 C1 E9 [; k) Z2 ]
  223. {( \* {8 L) ^+ @
  224.     FILE *outfile;
      u+ i& c' O& O% n5 j$ F- ?/ ~- S
  225.     uint8_t bytes[3];2 R5 \2 W6 j! A- H
  226.     int p;+ u" T2 w- I$ H  F
  227.     uint8_t pixel;, n) |! b# ?$ H; y
  228. / m4 {2 v( W1 ~6 a# p. r4 j1 i
  229.     outfile = fopen(filename, "wb");7 z: |$ X- z. M  S$ Z
  230.     fprintf(outfile, "P6\n%d %d\n255\n", width, height);
    . R6 B  A+ B. U# d+ c5 I% F2 D% F& v
  231.     for (p = 0; p < width * height; p++)/ A, X/ l" N3 c# ?
  232.     {" ~# X0 m( z! W
  233.         pixel = image[p];
    9 q! I' W, s: |* Q% U% g
  234.         bytes[0] = rbt->palette[pixel*3+0];1 F# \, w9 [& y- z$ R( H$ X& E
  235.         bytes[1] = rbt->palette[pixel*3+1];' Z$ [% W0 O* H
  236.         bytes[2] = rbt->palette[pixel*3+2];
    $ h% _2 S5 m& F  s9 F' F
  237.         fwrite(bytes, 3, 1, outfile);% d. J8 Y8 g6 o, _7 ?
  238.     }
    2 w4 F$ y$ R' P% x
  239.     fclose(outfile);
    ; ]4 k3 c5 W& Z% X4 y! j
  240. }/ F+ o- w0 H' h; M
  241. 6 h$ T4 F9 \: |9 z
  242. static int load_and_copy_rbt_header(rbt_dec_context *rbt, FILE *inrbt_file, FILE *outrbt_file)7 u4 h  a6 S& j! b: b% T, i( k) ]4 I
  243. {
    9 p2 `4 ?  y* E5 F2 A8 {# |! F% P
  244.     uint8_t header[RBT_HEADER_SIZE];
    $ u5 ~8 V: h! ^* M) M
  245.     int palette_data_size;
    : Z/ n- ~) j2 {1 Y
  246.     uint8_t *palette_chunk;
    7 U- s4 g, E1 N9 j; o
  247.     int unknown_chunk_size;
    # ^3 v9 q1 w) p
  248.     uint8_t *unknown_chunk;
    0 Q* E" w( h7 I6 U
  249.     uint8_t unknown_table[UNKNOWN_TABLE_SIZE];; ~; g# m- [) W
  250.     off_t padding_size;3 a  L% D  |* a8 {
  251.     uint8_t *padding;1 {5 u/ ?: ~! _) w& R1 W# K
  252.     int i;7 [$ [- @7 Y  e
  253.     int frame_size;! {2 q. @+ |% {. O9 B1 p
  254.     int max_frame_size;
    1 [; K$ }; k3 O* t
  255.     int first_palette_index;
    7 K. A1 ^! c7 d: x/ Y0 K: D  j
  256.     int palette_count;; l5 k+ p. t1 Q* @4 r* l0 T, p8 h
  257.     int palette_type;  P2 f2 A2 k: A; `& p; F
  258.     int palette_index;
    ( `3 n, B  Y$ k, m9 J* Z6 c3 `0 w

  259. : }1 o( Y3 b$ d8 l
  260.     fseek(inrbt_file, 0, SEEK_SET);# s* u+ ^& q% A- F( x+ d
  261.     fseek(outrbt_file, 0, SEEK_SET);
    5 ~* v. z% n3 I* h3 @4 U

  262. 0 {7 I5 H- C" M# K, b3 D
  263.     /* load the header */( u* ]% d; [/ Q7 B2 _" M# z
  264.     if (fread(header, RBT_HEADER_SIZE, 1, inrbt_file) != 1)
    : v' r/ ^' [7 k% N: l$ ^" w
  265.     {8 ]$ k# N# M+ f! f, D0 H4 y1 i
  266.         printf("problem reading initial RBT header\n");
    ! S- n' Z! B/ O: @, E( d
  267.         return 0;
    0 c/ S3 U: H$ N4 P; q) p$ v: q
  268.     }9 r- N5 s  a) N+ m3 p

  269. 0 W3 h& l2 V. V: v$ i0 T+ E
  270.     /* copy header to the output */0 f: s) ]7 s: F# f  E' S
  271.     if (fwrite(header, RBT_HEADER_SIZE, 1, outrbt_file) != 1)' Z+ V/ Y3 _, Y; E3 \" W! A& X; J
  272.     {
    , I% R0 N, c8 E, a  D  P1 }
  273.         printf("problem writing initial RBT header\n");( f& q" y* V2 p/ r$ m. c
  274.         return 0;
    7 _% A; }7 F9 L. G2 y2 U
  275.     }: n! y% B0 |& H3 F9 }3 Q, h

  276. 6 @$ L4 @1 `/ X* F
  277.     rbt->version = LE_16(&header[6]);
    ( U* o" _' q. N) ?  Y% U5 q; a% |, m
  278.     rbt->audio_chunk_size = LE_16(&header[8]);
    6 l) E' p8 c  Y0 h
  279.     rbt->frame_count = LE_16(&header[14]);! S2 z7 h2 a4 _) ~0 q# \4 p* R
  280. ( Z: w7 J" Y5 D6 L1 k
  281.     /* transfer the unknown data, if it's there */% z' x# F3 |" O9 [* S) F8 I7 L- |
  282.     unknown_chunk_size = LE_16(&header[18]);
    1 u  ?: }% u+ W4 S0 R0 f* ]! H, V" C
  283.     if (unknown_chunk_size > 0)
    & u- J, M0 Z$ J  Y$ f
  284.     {
    : a; W% E. _; A3 H. e: O
  285.         unknown_chunk = malloc(unknown_chunk_size);( n- z% p! x* R( G( Q
  286.         if (fread(unknown_chunk, unknown_chunk_size, 1, inrbt_file) != 1)
    % U$ N/ R  E% ~9 T5 T! {
  287.         {
    $ U2 A! N+ V6 S  {
  288.             printf("problem reading unknown data\n");
    : @, g1 G% \8 I/ d  G
  289.             return 0;# x) ?& z3 L9 J2 W# Y
  290.         }
    ( y0 s8 S* X+ O" `, w
  291.         if (fwrite(unknown_chunk, unknown_chunk_size, 1, outrbt_file) != 1)  Z6 q$ p( p. U" S8 h
  292.         {/ s! ^/ E4 @- c* t7 R( h
  293.             printf("problem writing unknown data\n");
    ' r2 H1 S6 z8 f. ]3 r( K/ c
  294.             return 0;
    6 k" n8 ?5 w8 y0 f  w7 ]
  295.         }5 _2 S6 [9 r4 p7 V5 p
  296.         free(unknown_chunk);
    ' z4 X* }# _6 _" A; l9 J
  297.     }
    2 C! o) N$ N1 d9 }

  298. % W2 v* a! U, _0 V( A1 m" S
  299.     /* transfer the palette chunk */' y$ ?; f9 N$ y3 l6 _# H, U
  300.     palette_data_size = LE_16(&header[16]);8 D* j# r/ p9 p2 b4 c
  301.     palette_chunk = malloc(palette_data_size);5 w9 K; {+ G) k
  302.     if (fread(palette_chunk, palette_data_size, 1, inrbt_file) != 1)
    ! l/ P+ I- X1 C1 M1 r2 J# t
  303.     {) s+ H; f0 q) Y: q
  304.         printf("problem reading palette\n");3 |: `8 o/ @% K; K' X# }- S
  305.         return 0;
    5 N) u5 [( F* P) I* _# \2 K
  306.     }
    1 f: q4 ^/ `, j9 @/ x( w
  307.     if (fwrite(palette_chunk, palette_data_size, 1, outrbt_file) != 1)
    6 S9 ?) G: x7 J# z' i0 J0 Q
  308.     {6 `; K% l/ P" `3 e. G/ n
  309.         printf("problem writing palette\n");7 Y- v5 C" F7 u: G. k, ~
  310.         return 0;2 J& S8 f2 k$ a) w, x
  311.     }
    # \% p; J; z# M0 j* {. g- [! K
  312.     /* load the palette into the internal context */% H/ I: ]' l& Z
  313.     memset(rbt->palette, 0, PALETTE_COUNT * 3);, @) w$ Y: S! w3 T8 a& n; O: [' a
  314.     first_palette_index = palette_chunk[25];
    ! X  m7 B0 l* x) ]
  315.     palette_count = LE_16(&palette_chunk[29]);
    ! E2 L$ N; f4 y1 A" z# _  _
  316.     palette_type = palette_chunk[32];7 W2 L" Y3 I8 ?6 o
  317.     palette_index = (palette_type == 0) ? 38 : 37;
    1 `; }. W+ n4 U5 p# f
  318.     for (i = first_palette_index; i < first_palette_index + palette_count; i++)
    3 C: g0 s' ^" C0 R8 C# z
  319.     {
    9 d3 G# R: C& k* G. n, C/ H
  320.         rbt->palette[i*3+0] = palette_chunk[palette_index++];$ b3 T& Y2 r" l: e5 u' ~
  321.         rbt->palette[i*3+1] = palette_chunk[palette_index++];: q: Q4 }9 C' I* `7 N' a6 l+ W
  322.         rbt->palette[i*3+2] = palette_chunk[palette_index++];
    - I& Z8 q0 f( l
  323.     }) Z, D( `5 \$ [5 z& U2 P5 o
  324.     free(palette_chunk);0 s7 V- {+ D& \

  325. ( h- z& F2 o; T) ]. F9 V6 `
  326.     /* copy the video frame size table (2 bytes per frame), as a placeholder */, l) {3 p$ x$ }8 X7 p+ ~( o
  327.     rbt->video_frame_size_table = malloc(rbt->frame_count * sizeof(uint16_t));
    & [( H9 J0 f1 w$ w+ J
  328.     if (fread(rbt->video_frame_size_table, rbt->frame_count * sizeof(uint16_t), 1, inrbt_file) != 1)
    # I8 X$ k5 v: m8 f# P5 y
  329.     {
    8 M- c% B4 ?9 ?: X" g/ `
  330.         printf("problem reading frame table\n");
    , f% `8 m9 G3 v& M8 n! B$ X9 r
  331.         return 0;5 h% N5 Z& O9 i7 ?" W
  332.     }4 \* Z# M0 A% f. _. c1 s  y: v5 C
  333.     rbt->video_frame_size_table_offset = ftell(outrbt_file);! {% w, \) G1 T: G! B% B+ O
  334.     if (fwrite(rbt->video_frame_size_table, rbt->frame_count * sizeof(uint16_t), 1, outrbt_file) != 1)( f* C$ n- e# p, U) Q4 r. L
  335.     {
    2 x& {" p  u! g' a
  336.         printf("problem writing frame table\n");' S) _! o, Z' s# `
  337.         return 0;! Y. ~  A! l7 D9 E- z; g
  338.     }
    , i1 I: s( l2 W. A/ L
  339. 8 n- Y8 q* Q, ^) o1 T% |, [  N5 [
  340.     /* copy the frame size table (2 bytes per frame), as a placeholder */2 _. r- L) T$ _, O
  341.     rbt->frame_size_table = malloc(rbt->frame_count * sizeof(uint16_t));
    * c# R6 ?. A$ h4 m3 R  E
  342.     if (fread(rbt->frame_size_table, rbt->frame_count * sizeof(uint16_t), 1, inrbt_file) != 1)
    % w$ _. b1 a2 s& t& q: N; b, _- T
  343.     {
    ! ^# Y4 \9 |9 s% L" J
  344.         printf("problem reading frame table\n");
    : g7 O; w3 M+ ^  B
  345.         return 0;
    0 N! U1 ~% x8 ~* ~  Z
  346.     }2 T# {5 H- D! F8 u7 q
  347.     rbt->frame_size_table_offset = ftell(outrbt_file);; c2 u4 {, y" }8 T6 q
  348.     if (fwrite(rbt->frame_size_table, rbt->frame_count * sizeof(uint16_t), 1, outrbt_file) != 1): E6 n8 b0 z' H/ x+ C
  349.     {4 _6 M3 }) |. t4 H) U
  350.         printf("problem writing frame table\n");) ^- t6 x$ ?( z2 z! n& T7 H4 d
  351.         return 0;
    ( L% [# _. I6 H1 M( W4 x" ?
  352.     }& I) [7 `; n2 ^$ `% a( W' Z8 m( J
  353. 0 e/ P2 g: H0 h$ v- M" ?: a1 p
  354.     /* find the max frame size */
    * U, ?2 C) E' y/ s4 S3 Q- c8 c
  355.     max_frame_size = 0;
    9 W8 W% H' I$ d9 y. w3 H+ t
  356.     for (i = 0; i < rbt->frame_count; i++)
    1 i7 D+ r; g3 j; s% t2 W
  357.     {
    . H% Y6 Q8 r1 N( R# v* \: T& D' x
  358.         frame_size = LE_16(&rbt->frame_size_table[i*2]);( ^' b* h2 j0 D  C0 b
  359.         if (frame_size > max_frame_size)
    - Y3 X4 {# O4 m
  360.             max_frame_size = frame_size;
    9 I0 K# g  ~2 H; B9 g$ @/ A4 K3 v
  361.     }2 d- E4 K7 y0 i8 d- S
  362.     rbt->frame_load_buffer = malloc(max_frame_size);
    ' b& t. l2 ]# L& o" |
  363. 7 }& p) \/ I7 Q, Z9 `* C
  364.     /* transfer the unknown table(s) */
    6 N5 r/ [% h1 B! [- o8 t
  365.     if (fread(unknown_table, UNKNOWN_TABLE_SIZE, 1, inrbt_file) != 1)
    ' D6 H; M; Z( F  y
  366.     {; n' S5 |, |$ _% ~/ H* T
  367.         printf("problem reading unknown table\n");
    % Y1 Z. H. ^5 x9 w. [0 ~" e
  368.         return 0;
    3 d4 z# F/ u7 |# L7 }/ O5 |
  369.     }+ p' ?+ G! K5 C& T
  370.     if (fwrite(unknown_table, UNKNOWN_TABLE_SIZE, 1, outrbt_file) != 1)
    ) C0 R  n" O: B9 p+ O0 W, D+ t
  371.     {
    1 R: E6 L% k3 f7 F
  372.         printf("problem writing unknown table\n");
    6 ~1 U( z* Y6 s5 M% w
  373.         return 0;% N; t4 h4 K: h# ]& h( U
  374.     }
    $ @' b. [; Q3 A1 }1 h, C! L
  375. 9 N( J- }- v6 v& O) G( e
  376.     /* copy over padding */  d( [/ H- x# W) c+ L/ o
  377.     padding_size = 0x800 - (ftell(inrbt_file) & 0x7FF);
    5 C3 A# P" ^) K1 ?5 X. a7 W
  378.     if (padding_size): ^# Q  T/ ^* D7 O
  379.     {/ Y1 q* y. B% Q& O2 ?3 y2 r0 N7 C
  380.         padding = malloc(padding_size);6 t1 {! u* V; m: F$ j7 k: c
  381.         if (fread(padding, padding_size, 1, inrbt_file) != 1)
    ; ?8 M. F. J. P8 z) ~
  382.         {
    ! ?/ V+ J8 T* C! O& @
  383.             printf("problem reading padding\n");
    * |/ u* O: l0 ~: N
  384.             return 0;
    : e; ^+ \- t& l
  385.         }6 |3 f' Y1 g& }( l' B
  386.         if (fwrite(padding, padding_size, 1, outrbt_file) != 1)
    4 h# R3 u0 Z5 B0 q/ ^* z
  387.         {4 w4 F0 O  c8 N/ O; n
  388.             printf("problem writing padding\n");  Y: H- f: x0 B9 U
  389.             return 0;; O3 g/ M: k) N$ x, ~: q: M
  390.         }2 W! C% k2 n2 [9 a% F$ t) W' R) N
  391.         free(padding);8 A' H4 f' c8 C3 b$ ]( s$ D% d
  392.     }# `; h; L1 N' J3 r1 Y! J
  393. ! U. C; e- y  J) A
  394.     return 1;# n3 k; g0 N2 i/ J# W
  395. }: v! `& }/ z9 Y9 T
  396. - F& B$ k/ n& h* h; I+ M. M
  397. static int get_lzs_back_ref_length(get_bits_context *gb)  e) ~8 X, f$ W/ ]0 ?, z( G
  398. {
    # h. e9 u- ^" ~; k$ u) l; `
  399.     int vlc;
    2 |3 ?+ }8 y# Q
  400.     int count;
    ' z2 M8 o( s, v, L/ t% [% G* ~
  401.     int value;
    9 |& P6 H! w; c) R$ A9 S
  402. . e- f5 F4 }! W! O+ ?6 ~
  403.     vlc = view_bits(gb, VLC_SIZE);
      L& ~9 r5 a' a! q( g( u
  404.     count = lzs_vlc_table[vlc].count;
    - V9 r/ s( F1 O% M; J6 {( E
  405.     value = lzs_vlc_table[vlc].value;
    , n) t0 p9 |3 Z: S1 p
  406. - ~6 g# R: J3 l- y' ^
  407.     read_bits(gb, count);
    7 }8 P+ R7 W6 I8 A9 G
  408.     if (value == 8)3 u6 ?  w8 G# t
  409.     {# ]* L; }* d* N9 j' J1 T' ?# B: p
  410.         do
    4 {" Z$ F8 R# z: Q0 J; G- i
  411.         {
    ( |9 v0 J  j- e2 X. o) m
  412.             vlc = read_bits(gb, VLC_SIZE);
    + ]) ~4 v& S4 q$ ^# e: i7 g
  413.             value += vlc;
    4 h; ~2 H) {6 n9 c. {* o/ }1 _" Y
  414.         }' j5 g0 Q8 I% O: o% [
  415.         while (vlc == 0xF);
    7 x2 ^& v& ?$ |* q
  416.     }, |; G0 u3 t- \
  417. ! g3 X: Z  \9 f7 S% A: ~
  418.     return value;0 [' P/ Z; |1 o  F) y7 Z
  419. }
    : a) y9 e0 U) L* @+ ^2 A! m
  420. - _" c! _4 A' @& ?# h1 j9 Z
  421. static void compress_window(put_bits_context *pb, uint8_t *full_window,3 A3 Z  S1 I. v! e# U$ @6 b, S
  422.     int full_window_stride,
    , g5 U, l& X6 R" i! E
  423.     int window_top, int window_bottom, int window_left, int window_right)+ A. |0 M6 Q. R0 S/ Z0 @
  424. {
    , F) J; ?/ G' r& J9 W
  425.     int last_pixel;
    ( j. k* c# q8 [4 f+ a
  426.     int run_size;
    ; {! d# L, y& l5 k3 Y; Z7 E
  427.     int x;
    1 z7 C( ]9 Z( ~
  428.     int y;
    8 u8 O3 J/ U& ~$ L
  429.     int start_index;
      m- A" y' R) H7 P6 N% L" |
  430.     int end_index;$ u2 t/ L$ k1 K8 Q
  431.     int encode_last_run;$ E0 x( s0 ~3 Y( I. P& f4 C
  432. ! U4 O9 o( f4 N
  433.     last_pixel = full_window[0];
    4 Z7 ~9 M; z# ]/ |
  434.     run_size = 1;5 S* v% X. u1 a9 @. Y6 L& ]# L8 h
  435.     for (y = window_top; y <= window_bottom; y++)
    # |. \8 v. n) B" f* v7 R- W
  436.     {
    : V, [7 ~: G/ a( E
  437.         start_index = y * full_window_stride + window_left;
    1 x  U' U' [7 t4 \. {# E
  438.         if (y == window_top)" o# b: ~; y! N( u* g
  439.             start_index += 1;! R$ U  y" L/ J
  440.         end_index = y * full_window_stride + window_right;9 m' k% W$ C/ }+ y  t1 h. g# q
  441.         if (y == window_bottom)
    - `0 Q0 y- u" O) L2 F' X7 C
  442.             encode_last_run = 1;
    0 u3 r  b# Q0 k7 C
  443.         else1 F8 ~& C* I3 d; ^
  444.             encode_last_run = 0;
    ; V6 j( b$ l* w& A7 H5 c- D
  445.         for (x = start_index; x < end_index; x++)8 X. Z+ ]4 U. U
  446.         {) m3 N$ `& Y! X$ ]6 s
  447.             if (!encode_last_run && full_window[x] == last_pixel)
    ' N: z2 u2 x8 A" d) k1 k5 A6 r
  448.                 run_size++;
    ! u/ ]% w2 J& C9 F  X+ v' ^
  449.             else
    9 z: N  \, b: w" S
  450.             {
    5 [; e1 ~3 f! g. M3 \# i3 F3 Z, P" d
  451.                 if (run_size == 1)) C: B7 a3 D( [% u& c
  452.                 {8 ^6 I9 L" j2 E0 }
  453.                     /* encode a 0 bit followed by raw pixel byte */1 p  i. z- Q- E) o0 B! ?9 ~
  454.                     put_bits(pb, 0, 1);
    4 q7 @! x$ j: G! A8 K
  455.                     put_bits(pb, last_pixel, 8);
    2 \. j, N+ I# d8 M6 z( W
  456.                 }( |* g" W6 S3 T6 X5 [+ j2 h/ g0 }: {9 Q
  457.                 else if (run_size == 2)+ e" w9 h  e- {# @+ i
  458.                 {
    ; P$ u. J( Z6 B
  459.                     /* encode a 0 bit followed by raw pixel byte */! t% ~* _. T1 T3 X+ L9 K& x
  460.                     put_bits(pb, 0, 1);$ p' `/ s- B4 ]
  461.                     put_bits(pb, last_pixel, 8);
      N$ K+ o- g) @: _6 Z3 c
  462.                     put_bits(pb, 0, 1);" ?2 O* h/ o* ?+ Z1 e: w) l4 i
  463.                     put_bits(pb, last_pixel, 8);
    ; D& s0 F; l- Y# D# b
  464.                 }
    7 F- E3 @. e$ P% r5 [1 S! x
  465.                 else
    + U$ e3 Y0 ?  X
  466.                 {
    2 x5 a) G1 ~" Q6 Q0 U
  467.                     /* encode a 0 bit followed by raw pixel byte */
    ; }) p7 o& M0 I! L
  468.                     put_bits(pb, 0, 1);
    0 {. D( h1 F" K7 n
  469.                     put_bits(pb, last_pixel, 8);
    # y: B: ]* X0 u: j: Z
  470.                     run_size--;& h1 w% U1 ~6 D4 [1 e
  471.                     /* encode a run: a 1 bit, followed by a back reference
    2 e1 p$ g( i; [0 d
  472.                      * offset (-1), followed by a length */4 d" r7 F4 L' y1 [  Y" ?, c
  473.                     put_bits(pb, 1, 1);( R$ V2 h/ A) \; E! E( V3 b
  474.                     put_bits(pb, 1, 1);  /* 1 = 7-bit offset */" m; e9 y/ @* g  R& H1 X
  475.                     put_bits(pb, 1, 7);
    ) ]. ~3 V& l& I8 y& ]) Z' }
  476.                     if (run_size <= 4)) B* y' J+ x+ d. c  N
  477.                     {6 o- {, j1 q: E/ s/ Q: P
  478.                         /* lengths 2, 3, and 4 are 2 bits */
    " e/ I8 H+ u. T! i" Y: N, g
  479.                         put_bits(pb, run_size - 2, 2);5 R- O% Q3 E3 D
  480.                     }% I# {' \: l( w  t
  481.                     else if (run_size <= 7)* A0 U! z+ m1 t3 \
  482.                     {7 |. f0 ]: I8 L
  483.                         /* lengths 5, 6, and 7 are 4 bits */
    $ c& ?+ T: \, _: O  n7 l
  484.                         put_bits(pb, run_size + 7, 4);( X+ X, R5 x6 h
  485.                     }" P/ x& d& ]" u7 a) t; `
  486.                     else9 J$ y8 M) p) P# c8 W* D7 y# o
  487.                     {* ^+ i7 b* S* C' y
  488.                         /* arbitrary length; start by encoding 0xF which7 i1 r& h- ?' t" [6 E
  489.                          * stands in for an initial version of 8 */. ]8 q2 T* A" {3 G) C% N
  490.                         put_bits(pb, 0xF, 4);
      z8 T! U0 Q$ a$ ~; I- ~( C( m
  491.                         run_size -= 8;
    ' A! J1 q: v4 s% e

  492. * x% N6 q5 w4 t; |
  493.                         /* encode blocks of 4 bits until run_size is 0 */
    ) r* F0 W, X1 @3 g$ P1 B: Q
  494.                         while (run_size >= 0)4 M2 a+ k$ E# i: Q( |  Q
  495.                         {
    1 ]  p4 a3 P0 |7 j
  496.                             if (run_size >= 15)0 T6 A. }4 D- x0 r
  497.                             {
    ' K, A8 m/ H/ L$ d& \
  498.                                 put_bits(pb, 0xF, 4);
    / g& s2 r) b2 ?" H6 r
  499.                                 run_size -= 0xF;9 d* A- r; H: k4 S1 M
  500.                             }, {# e; c5 y9 _4 F% u% m' Z
  501.                             else! ]4 X+ B4 N# l$ i5 w4 p
  502.                             {# i3 r/ y1 ~1 o- m! k5 H
  503.                                 put_bits(pb, run_size, 4);& F% ^5 H8 c" u6 p$ ?$ t
  504.                                 run_size = -1;+ \7 D& y2 O. F. M5 i+ u; O9 k. \3 q
  505.                             }
    & `% ?- A  V1 a' Q
  506.                         }6 m5 M5 m- s+ r  @4 J9 o* r; j0 V
  507.                     }
    + d2 I' ]0 [" Z
  508.                 }
    # W3 @$ S! k5 t0 D" D8 _

  509. 8 U" d& Y: c( v0 _, J9 `5 D
  510.                 last_pixel = full_window[x];
    , U: i4 P7 x3 ^7 x
  511.                 run_size = 1;
    4 a8 u5 ?# ^( {/ [

  512. # F+ Z9 `) N9 m3 P# z9 ]0 Q/ C7 U8 q
  513.                 /* this single x iteration was only here to close the final run */% Y! H7 C' N. v' I6 i
  514.                 if (y == window_bottom); t- w; J8 V, N# Q- H: R! A
  515.                     break;: C2 e) l* |& A5 a! @. _4 A
  516.             }4 g4 M0 `+ |5 E1 P. F
  517.         }
    # ?$ p4 g. y" }1 ^, k8 @
  518.     }0 E) A7 M$ S3 X: l3 O4 }

  519. & j$ i  `/ b1 p0 K* V
  520.     /* close the bitstream by encoding a back reference with length 0 */$ R, _5 e* M5 @) K7 }0 L) j
  521.     put_bits(pb, 1, 1);  /* back reference run */
    $ j* o, z3 C8 I: Z' y
  522.     put_bits(pb, 1, 1);  /* 1 = 7-bit offset */
    6 U/ {+ }' |$ `- F+ [
  523.     put_bits(pb, 0, 7);  /* length 0 */: T0 o8 M/ l3 v& l* K

  524. & q0 o- r7 d! A( N5 n* Q2 \7 D0 a8 [
  525.     put_bits_flush(pb);' h9 I* P  r, ^) y8 ?; N9 Y3 }( Z4 [
  526. }
      \6 h* p7 p1 X: ~' V
  527. 3 Q5 j3 Q8 a! y* M! m/ u2 P' N
  528. /* compute Euclidean distance between an RGB color and the desired target */4 K5 Y7 C' h' F/ N, ~) K- `
  529. static int compute_rgb_distance(int r1, int r2, int g1, int g2, int b1, int b2)
    " D  \8 P$ l4 c$ L' w8 N/ {# W
  530. {
    6 h0 P& ~- x- y  R3 m. C
  531.     return sqrt((r1 - r2) * (r1 - r2) +& u) c1 ]! i1 U, U$ i
  532.                 (g1 - g2) * (g1 - g2) +* I+ X' E6 E) s% K3 C
  533.                 (b1 - b2) * (b1 - b2));' v6 T, U1 k% `5 e/ a
  534. }; G' V9 ?3 K8 t) a. [0 p# H

  535. ) C  D7 t' {3 o7 Q
  536. static uint8_t find_nearest_color(rbt_dec_context *rbt, int r, int g, int b): H' w' ^$ l/ q0 t* {
  537. {3 N. _4 N  ~7 ]5 B5 y2 j* P8 x
  538.     int i;
    ' G5 g$ f$ ~; U# |
  539.     int nearest_distance;  M+ ]/ R1 U1 `5 ~) W. N6 P
  540.     int distance;
    " f) N: c4 c6 d1 B# l
  541.     int rp;
      p9 N- ^9 m; n" _" W6 D
  542.     int gp;
    - M, L4 i' i) S& l
  543.     int bp;1 F& o. ^, ?$ }& R4 P# P
  544.     uint8_t palette_index;
    4 y5 N1 m4 U; Q2 x$ h! V( m" Y
  545. 1 G; k% K7 Y8 R( t- V
  546.     nearest_distance = 999999999;
    % Z! X" ?# @# @5 K; }( P6 O/ d
  547.     palette_index = 0;
    % r- \; H: W8 @. x0 }- Q( y& H
  548.     for (i = 0; i < 256; i++): S2 c) H- K8 \8 f3 x2 H: j
  549.     {1 R" x% u6 \2 u# K5 s
  550.         rp = rbt->palette[i * 3 + 0];4 l- g9 p1 K' Q3 B  l6 |+ b
  551.         gp = rbt->palette[i * 3 + 1];
    - n( V  F  t# i  d" O% r2 T
  552.         bp = rbt->palette[i * 3 + 2];( r' @# b+ `$ K2 P$ M( ?5 I
  553.         distance = compute_rgb_distance(r, rp, g, gp, b, bp);0 ?+ R  O. L5 S1 \* t7 P% [% g5 z
  554.         if (distance < nearest_distance)- ?  k0 P( j& `4 E8 P  h" k
  555.         {
    : ~* x& n' v% w1 M$ P5 V
  556.             nearest_distance = distance;
    5 D& C6 {# x0 s: A5 R0 a" s9 x# R
  557.             palette_index = i;. H4 ~! ~; ~5 P1 I1 X
  558.         }
    2 c4 c( W+ g7 U/ T) b1 y! ]5 n
  559.         /* can't get closer than 0; break early */
    " f' F4 j. W! _% e
  560.         if (distance == 0)
    % o' ?8 T2 S$ o1 C% P
  561.             break;
    ' e3 b% }$ @3 C
  562.     }! e8 ]1 c) ?, m! {
  563. & b$ ]6 I6 ~/ p
  564.     return palette_index;6 x3 @. Z& O1 c: d0 N
  565. }3 }6 P  ?8 b& ~6 I* ?
  566. 4 ^, @5 i8 ]: R: k- l
  567. static void subtitle_frame(rbt_dec_context *rbt, uint8_t *frame,
    5 \3 P+ l( W. K: A
  568.     int width, int height, int timestamp)
    # F  \# j) L3 t% I! L1 T
  569. {% B* j% \0 ^  O% v" n
  570.     ASS_Image *subtitles;# w6 f9 i. \7 D# ?2 T4 Z( I  I
  571.     int detect_change;7 G3 ^3 ]) C- o3 j& d# K" y
  572.     uint8_t subtitle_pixel;
    . _6 ]! p) W2 r/ G8 [; r9 z
  573.     int x, y;
    , N6 y9 r% W# i! A* \* T  ^) j6 [* H  ~
  574.     uint8_t *frame_ptr;
    2 ~+ c( }7 q& [. b
  575.     uint8_t *subtitle_ptr;% ^3 U+ ^( O- Z8 J, h. F0 H
  576. 5 z* b8 S2 v6 B+ a* m, w
  577.     /* ask library for the subtitle for this timestamp */
    ' @, _$ n2 T2 p' X# P
  578.     subtitles = ass_render_frame(rbt->ass_renderer, rbt->ass_track,
    ! v) h! d3 l1 |+ n
  579.         timestamp, &detect_change);
    - X$ I+ r  ?. v' e& y( g2 r

  580. ; O, i9 [+ B" s! E
  581.     /* render the list of subtitles onto the decoded frame */6 M* H% ~0 f$ D' X& W
  582.     while (subtitles)' c1 A, X# P) e% Q- ?, w- |
  583.     {
    : a& w9 L! O2 U2 {2 L, W
  584.         /* palette components are only 6 bits, so shift an extra 2
    - V" R% O7 w' T7 E4 \! [5 R. O+ K
  585.          * bits off each component */4 M1 M2 t" O& X& T- M
  586.         subtitle_pixel = find_nearest_color(rbt,. `# p3 \6 Z0 t9 E
  587.             (subtitles->color >> 10) & 0xFF,0 O* v# W  n1 }* g) g5 h1 g
  588.             (subtitles->color >> 18) & 0xFF,
    & c9 {* X7 s9 H; r7 l. P: v8 {4 {
  589.             (subtitles->color >> 26) & 0xFF);
    . v9 K$ a- ]+ C1 @1 n
  590.         for (y = 0; y < subtitles->h; y++)
    6 l6 S5 z. q4 t7 ]. z) @! }
  591.         {1 b. X1 j. P0 }4 U. ?
  592.             subtitle_ptr = &subtitles->bitmap[y * subtitles->stride];
    * D( |5 A& z6 _# j. v
  593.             frame_ptr = &frame[(subtitles->dst_y + y) * width + subtitles->dst_x];9 H* v' Y( x! O" S" e
  594.             for (x = 0; x < subtitles->w; x++, frame_ptr++, subtitle_ptr++)
    % s  H3 ^, i  T# S) |3 _# n$ P+ m
  595.             {
    / U# _$ u2 O6 U8 m# @1 l  c
  596.                 if (*subtitle_ptr >= SUBTITLE_THRESHOLD)
    6 |- a3 ?5 |5 d2 ^6 g. o
  597.                     *frame_ptr = subtitle_pixel;
    ( g4 X* U  Y# a2 b: F$ w! W
  598.             }" ^5 b* q% x/ p8 {8 c
  599.         }2 d. C: @8 R4 M9 D2 u; J
  600.         subtitles = subtitles->next;
    - e2 d4 G& l$ |: t
  601.     }
    9 Z" ?* q7 H% c  o
  602. }
    # ~. C- M) S  e  l. j. O2 q0 Q
  603. 5 a1 o" W+ R+ t" d6 K
  604. static int copy_frames(rbt_dec_context *rbt, FILE *inrbt_file, FILE *outrbt_file,6 o6 n4 r1 I. M3 h
  605.     int origin_x, int origin_y, int window_width, int window_height)# y5 f( b- ]2 C: V0 N. n
  606. {
    4 g+ C4 e0 T% b& I
  607.     int i;
    8 Q+ ?2 h9 |0 X
  608.     int j;5 M) V" p3 q2 }! h  Z% z
  609.     int scale;
    * J( T) Z& I$ O! o/ s1 E0 K7 Y& n
  610.     int width;
    : \6 w- T. d4 Y$ A7 R  G
  611.     int height;
    ' J; f* t( Z; q
  612.     int max_width;/ e- j! [$ L, v  d! @8 a: J4 F, W
  613.     int max_height;
    # n  b$ n: c/ m$ W( a1 |3 h0 V+ z" n
  614.     int frame_x;4 Z% g$ b9 O& x/ S% a, P
  615.     int frame_y;( B4 n! u( R* o7 i3 m
  616.     int fragment_count;# p  q! L7 d/ S) N4 Z  ^
  617.     int decoded_size;
    & b3 q  P1 n/ ~$ m8 K$ G/ Z4 M: T0 c
  618.     uint8_t *decoded_frame;6 ]' R* L# x* Y4 E& n
  619.     int fragment;5 [! [5 T3 e/ H# h3 f2 f$ q
  620.     int fragment_compressed_size;9 W! z  A2 I: p3 w0 b8 g
  621.     int fragment_decompressed_size;5 g: w" L; z1 _( @( [) ~+ _
  622.     int compression_type;6 R9 s1 z) }) E
  623.     int index;0 ^4 i5 x0 [3 _5 A3 L; d2 N, M
  624.     int out_index;
    4 ]5 u+ T1 w  F: z, y
  625.     get_bits_context gb;
    , H# z( `3 B# w+ g5 k) [
  626.     int frame_size;2 D6 [6 h) g1 i( r! R' t
  627.     int video_frame_size;
    * n) |2 s( t* E3 @: z+ Z. W
  628.     int audio_frame_size;$ `- a6 Z: }2 o

  629. 7 a. i; j7 \) X9 u
  630.     int back_ref_offset_type;
    . o$ I9 b/ I% T
  631.     int back_ref_offset;; h1 ]* `- H2 T  k: \) T/ n3 x
  632.     int back_ref_length;
    ) w. O, X# m# C1 t$ h! ^" k' V* m
  633.     int back_ref_start;
    ' `* c- r  d! Z9 n7 {
  634.     int back_ref_end;* Y! L5 R1 V# x
  635. / g: `) v4 R7 y" I+ \1 @( n
  636.     uint8_t *full_window;
    - P# x) s7 H9 ]5 v3 E
  637.     int full_window_size;
    7 s2 E6 b! U8 S# ]4 `
  638.     int y;
    3 a& g: D1 K* |8 u, o2 b% c
  639.     int window_top;
    & f5 R6 D; [4 i' Q+ ~1 c2 x6 E; a
  640.     int window_bottom;
    9 i- `6 [, s7 L% ]: p  l, @
  641.     int window_left;
    6 K$ `- s* c; q8 n
  642.     int window_right;
    # e$ X; _; P9 v: Y! o, {  D1 w. u
  643.     int window_size;$ d" f; y7 E( A8 N

  644. 8 {) W8 g. s! j! U- d
  645.     char filename[30];# S) R8 f) R* _- O1 E2 N
  646.   u# e5 w5 V! ~2 w; p2 L
  647.     put_bits_context *pb;- W$ G2 o+ A+ n$ C6 |: W

  648. 0 [% M5 o4 s/ x* w5 r0 I
  649.     full_window_size = window_width * window_height;
    - |" r! B5 [; {) |
  650.     full_window = malloc(full_window_size);6 G/ R) _( P0 R! j
  651.     pb = init_put_bits();
    8 A1 I- X$ m' g% g3 i4 u

  652. : ]- Z# l  `4 }2 a5 h- W
  653.     max_width = 0;8 ]+ c# k: v1 Q7 w5 w% h1 F
  654.     max_height = 0;
    1 O% v/ z( I+ W

  655. # e! h  v7 b0 D- T
  656.     for (i = 0; i < rbt->frame_count; i++)
    1 r( ?5 q; C( D& b$ Q: \
  657.     {7 u# K: S" x  C' Z$ R- R8 B( v6 Q
  658.         /* read the entire frame (includes audio and video) */
    & L& f. I, e& _/ [
  659.         frame_size = LE_16(&rbt->frame_size_table[i*2]);9 \5 a0 n4 l4 Y* l; `$ x% r
  660.         video_frame_size = LE_16(&rbt->video_frame_size_table[i*2]);
    ) [9 p7 d: ]; a8 \
  661.         audio_frame_size = frame_size - video_frame_size;# p* ]7 n9 w+ h0 I
  662.         if (fread(rbt->frame_load_buffer, frame_size, 1, inrbt_file) != 1)
    0 V% _: k1 r1 S* A( L9 U
  663.         {' i0 P5 i" a* x' r, X) e
  664.             printf("problem reading frame %d\n", i);
    / ?* x7 ~2 O' E; [
  665.             return 0;& c9 {# A& [4 \9 _
  666.         }! E% T+ C+ J0 w' T) D% {% k9 z
  667. : H  d7 l' q$ i# M7 P
  668.         scale = rbt->frame_load_buffer[3];
    ' }& Y4 Q/ R: e
  669.         width = LE_16(&rbt->frame_load_buffer[4]);2 T2 X. U3 e. ]9 Q8 L
  670.         if (max_width < width); X. @7 I" P% K, ?) M% G9 E
  671.             max_width = width;
    # W2 d5 r0 ~* d. D0 w! g" S
  672.         if (max_height < height)% T, K2 s* Y' I3 w5 X, M, X2 x( J! Y, B
  673.             max_height = height;
    / U) G7 y. z8 ?' n! J  n$ M
  674.         height = LE_16(&rbt->frame_load_buffer[6]);
    ( k% T0 B: z, H, j
  675.         frame_x = LE_16(&rbt->frame_load_buffer[12]);6 i8 J1 g7 o4 t) Q  _. B% O
  676.         frame_y = LE_16(&rbt->frame_load_buffer[14]);5 U3 N. L/ S6 {  J/ a; `7 B3 a
  677.         fragment_count = LE_16(&rbt->frame_load_buffer[18]);& @1 C" ~4 ~3 E
  678.         decoded_size = width * height;9 A/ T8 a4 S% C6 Z
  679. ! f/ `' y' n) _: u3 `3 Q* p2 _
  680.         printf("processing frame %d: %d%%, %dx%d, origin @ (%d, %d), %d fragments\n", i, scale, width, height, frame_x, frame_y, fragment_count);+ {' ]8 l& T8 b3 [6 z

  681. , S7 z' }7 `* v1 \) z  r
  682.         /* decode the frame */
    + z6 w  f+ n3 R- _9 W6 P
  683.         decoded_frame = malloc(decoded_size);/ [- Y8 d$ r; O  C& W0 ^
  684.         index = 24;
    0 u9 O7 u' {7 y  g
  685.         out_index = 0;! a4 \- g1 {2 F
  686.         for (fragment = 0; fragment < fragment_count; fragment++)) p. I5 o" V  R) S2 ]
  687.         {
    , B) m* ~( m. S4 z2 n) y
  688.             fragment_compressed_size = LE_32(&rbt->frame_load_buffer[index]);
    4 _0 V4 T6 @1 a+ ]
  689.             index += 4;
    6 s8 h3 g* F9 t) l2 [  i7 ^
  690.             fragment_decompressed_size = LE_32(&rbt->frame_load_buffer[index]);, T; ~2 a6 B1 s& ~0 x
  691.             index += 4;! i4 H8 b% a" P: K* l" n
  692.             compression_type = LE_16(&rbt->frame_load_buffer[index]);
    ! R* C2 D3 H' M. z# o" N" G
  693.             index += 2;9 P  p( Y/ O& Q/ z

  694. : t% O- {& x+ J! x
  695.             if (compression_type == 0)! m3 _$ f$ y2 V! ]8 e5 ?- M3 m' |
  696.             {9 n1 Y6 I9 h$ Q* p9 p
  697.                 init_get_bits(&gb, &rbt->frame_load_buffer[index],
    8 ^2 @$ K# ~/ w& R/ c/ s% |& W
  698.                     fragment_compressed_size);, z9 n- }* F' t6 g' c1 |5 G  P

  699. 3 z4 B, R" T* L9 _# H* G' p( I7 L
  700.                 while (out_index < fragment_decompressed_size)
    6 A& f2 Z: C* ^  T+ \
  701.                 {
    & M- y9 q# |% V+ l- n, d
  702.                     if (read_bits(&gb, 1))" L, \: P* _0 ]: w5 i: `
  703.                     {# m! E. u' @* i9 p( z
  704.                         /* decode back reference offset type */
    & v& \& C  V. b( x0 `/ I$ p' J
  705.                         back_ref_offset_type = read_bits(&gb, 1);$ j# ^% a- s$ u7 I7 P+ J, H( g' B
  706. " m2 T/ z6 ~6 w8 p
  707.                         /* back reference offset is 7 or 11 bits */4 E" W7 V6 B# g' s! R! a
  708.                         back_ref_offset = read_bits(&gb,
    + J+ N. d6 L1 C
  709.                             (back_ref_offset_type) ? 7 : 11);6 J; J5 G& x# O: U1 o6 W/ V
  710. + t  n- {4 W8 V* ^% O6 Y
  711.                         /* get the length of the back reference */1 G' v7 {: y7 G! z) Z/ A& E1 C
  712.                         back_ref_length = get_lzs_back_ref_length(&gb);7 m9 z8 j+ @2 p" X
  713.                         back_ref_start = out_index - back_ref_offset;1 B! Q9 ~$ {1 d, G: J
  714.                         back_ref_end = back_ref_start + back_ref_length;: M: n7 `2 H- D$ C; [2 s+ r
  715. 8 Z" Z$ q+ a  `8 Y$ q1 M+ u
  716.                         /* copy the back reference, byte by byte */
    : e, k2 m. q) R. H" ]- `6 h  ]2 j
  717.                         for (j = back_ref_start; j < back_ref_end; j++)3 u, Z$ C  R# {9 a! s, i
  718.                             decoded_frame[out_index++] = decoded_frame[j];+ y4 Y! P9 w* `! ^3 i
  719.                     }% ^' L- }2 K  l3 m4 `8 i/ q8 k
  720.                     else
    1 c% z7 k: F0 b
  721.                     {. m  H. b& ?1 t% H6 G: h9 t5 O' k
  722.                         /* read raw pixel byte */+ {( W$ r( @' h  h, O7 |
  723.                         decoded_frame[out_index++] = read_bits(&gb, 8) & 0xFF;
    $ z, q2 q, Y0 ?8 R9 j- g4 R
  724.                     }
    6 N/ h. Y0 `/ C8 E( q( E
  725.                 }
    1 o5 m, X. o7 K6 T- v

  726. 5 x% p0 P3 O! v( g7 x6 C9 c9 d
  727.                 delete_get_bits(&gb);
    2 c& p1 D' Z1 j: o0 ^8 ?% A
  728.             }1 Y- }, w) n- N- b$ E% \

  729. : ]5 j3 b* z4 r% N
  730.             /* next fragment */( W( p! k, F+ f( u% U# V! n% d  W
  731.             index += fragment_compressed_size;& F5 i; M- Y. N( t) ]5 f+ |
  732.         }
    0 d. b- X/ Y0 i/ r7 Q& B4 B: X

  733. ! Z3 {" c* n& P4 c& o$ X6 a
  734.         if (rbt->dump_frames)- @9 Q. f1 L, _3 A, g% Z
  735.         {2 V% t' m7 p$ z/ K9 ?& h
  736.             /* dump the original frame */( ?) r! x8 g- S. {) D; A' C
  737.             sprintf(filename, "original-frame-%03d.pnm", i);
    . G& [$ C% q; H+ H0 n1 \6 O
  738.             dump_pnm_file(filename, rbt, decoded_frame, width, height);+ E) L( \/ z- i1 R, L% I
  739.         }
    ; K. ?: X- I& f& \' I% d$ Q1 \  D

  740.   k3 R% e4 X& L, Y' `# F9 m
  741.         /* transfer the image onto the frame window */
    & w" ?$ [4 l, b8 Z
  742.         memset(full_window, 0xFF, full_window_size);
    " q, U' @6 L+ P3 Y# V3 }
  743.         index = 0;
    / q/ U* e) j5 C/ ?+ E" L
  744.         for (y = 0; y < height; y++)
    , U6 g! ^' Q- w& y# `* W
  745.         {
    , R0 s( v1 [7 A# C, z
  746.             out_index = window_width * (frame_y + y) + frame_x;5 l( X3 Q7 Z- b& K
  747.             memcpy(&full_window[out_index], &decoded_frame[index], width);1 J+ O* ]7 `# W" E  p" @* y
  748.             index += width;
    + d# ^0 c/ e& M3 K6 V
  749.         }  h  s- |  W% J! N
  750. - [& T- j, `8 ?) J/ \
  751.         /* write the subtitle */6 S% X3 S! f% l4 r0 F: \
  752.         subtitle_frame(rbt, full_window, window_width, window_height,
    5 A3 l/ N! d$ s; H; x
  753.             i * MILLISECONDS_PER_FRAME);
    ! `, `: I6 ^6 K1 m+ M5 K6 B

  754. : J) J' W8 O0 p  P9 o* Q
  755.         /* figure out the smallest change window */( v# m1 v+ M& ]5 ~/ m. c: \8 M
  756.         window_top = frame_y;0 A, d/ H1 q7 O- o) I
  757.         window_bottom = window_height;9 K" O4 K5 g2 y2 m$ P8 [# ?
  758.         window_left = 0;
    5 ]0 G3 O* D& Z0 h
  759.         window_right = window_width;
    $ d2 Y. n& W: m
  760.         window_size = (window_right - window_left) * (window_bottom - window_top);
    : C+ b- j# X: `- \2 t& D
  761. 8 d0 N8 o$ f: z5 m
  762.         /* compress the frame */
    3 B5 B% ~/ L# B5 d1 v/ t
  763.         reset_put_bits(pb);+ x4 ~6 S1 a- O- `6 B
  764.         compress_window(pb, full_window, window_width, window_top,
    4 \! [) ]. o6 a/ J9 R) O/ A
  765.             window_bottom, window_left, window_right);
    : c- P5 F  h6 w5 g* j/ N
  766. " m) O/ T% Y6 P. z$ r  J
  767.         if (rbt->dump_frames)
    + F; U  \3 L% v3 r. Q- G
  768.         {
    : w; i( {8 s" K3 m3 d2 H3 J  Q
  769.             /* dump the frame plotted onto the full window prior to encoding,2 `& V2 m3 @4 w* z& h4 O& j
  770.              * with subtitle */! K. S: U1 v+ ]$ x2 `
  771.             sprintf(filename, "pre-encoding-frame-%03d.pnm", i);& `- C( m- x: ?' g* f$ s
  772.             dump_pnm_file(filename, rbt, full_window, window_width, window_height);" u# ^9 y( w; N$ V
  773.         }" t' f* b" [( B/ x) f! N# U: j/ q
  774. / b( F0 W: ], C! ^
  775.         free(decoded_frame);' M( u" E# Z+ ^( a& S
  776. 9 \8 {9 b$ ^- R$ c0 `( V
  777.         /* update the frame header */5 p, b: F  O3 h% {
  778.         /* width */
    7 j3 D/ N- |  a3 J( S
  779.         rbt->frame_load_buffer[4] = (window_right - window_left) & 0xFF;
    + H6 Z! E: u8 [% L' _6 g
  780.         rbt->frame_load_buffer[5] = (window_right - window_left) >> 8;
    % T2 A# D) c& B  S) V
  781.         /* height */
    4 d2 v: R, Z- r# z" h5 D
  782.         rbt->frame_load_buffer[6] = (window_bottom - window_top) & 0xFF;
    . b$ y5 |! w- O! {, n$ p
  783.         rbt->frame_load_buffer[7] = (window_bottom - window_top) >> 8;
    - u! @6 y# t  F0 V" R0 o
  784.         /* origin X */
    7 U7 i9 z3 ]& P% y$ j# k4 y
  785.         rbt->frame_load_buffer[12] = window_left & 0xFF;( v- j9 j. f  Y% U" i
  786.         rbt->frame_load_buffer[13] = window_left >> 8;1 X# G) i+ U  `1 O; _+ o& ~
  787.         /* origin Y */' h; K: Y& @4 w5 V: j' j! |
  788.         rbt->frame_load_buffer[14] = window_top & 0xFF;
    ; e5 A) K) B4 K" y% {6 \1 @  i
  789.         rbt->frame_load_buffer[15] = window_top >> 8;
    2 r/ e; r5 v: I" D% S7 C
  790.         /* fragment payload size */
    : _7 R( S) y% A/ T6 A" [
  791.         rbt->frame_load_buffer[16] = (pb->byte_index + 10) & 0xFF;
    & n2 r/ a- s  W
  792.         rbt->frame_load_buffer[17] = (pb->byte_index + 10) >> 8;' o+ [  \' U! F7 Y
  793.         /* fragment count (1) */' N2 `+ k9 Y! X& _; Q+ L! j
  794.         rbt->frame_load_buffer[18] = 1;5 t. D. Z# J* p, O5 m4 K0 P
  795.         rbt->frame_load_buffer[19] = 0;
    4 ~. U- c, Y) Y' h( [/ W

  796. / q" f2 G: Y# ?' P
  797.         /* update the fragment header */
    " q/ o5 w! b9 J& x0 c' D
  798.         /* compressed size */- p# l& b$ E% _3 I* b. Z
  799.         rbt->frame_load_buffer[24 + 0] = (pb->byte_index >>  0) & 0xFF;3 f9 \& f' e$ g5 ?" A, V0 D, f
  800.         rbt->frame_load_buffer[24 + 1] = (pb->byte_index >>  8) & 0xFF;( u) n) ]0 S2 q3 p, t, h
  801.         rbt->frame_load_buffer[24 + 2] = (pb->byte_index >> 16) & 0xFF;) W, L) ?2 F, O" P% T
  802.         rbt->frame_load_buffer[24 + 3] = (pb->byte_index >> 24) & 0xFF;
    7 g& ~$ a( @0 l- k5 ^
  803.         /* decompressed size */
    ; I7 F4 X# e) K# d/ g+ J9 |; j
  804.         rbt->frame_load_buffer[24 + 4] = (window_size >>  0) & 0xFF;
    5 t, A; M# \# t' k3 [) y
  805.         rbt->frame_load_buffer[24 + 5] = (window_size >>  8) & 0xFF;8 g, C4 R7 \7 C" ~) r0 G
  806.         rbt->frame_load_buffer[24 + 6] = (window_size >> 16) & 0xFF;
    . g/ Q. G8 l1 I2 `- _
  807.         rbt->frame_load_buffer[24 + 7] = (window_size >> 24) & 0xFF;; v, U5 v5 a8 }/ H8 O
  808.         /* compression format 0 */
    ' T  B6 h# w0 d3 z0 H
  809.         rbt->frame_load_buffer[24 + 8] = 0;% P! y* c" u+ N! y
  810.         rbt->frame_load_buffer[24 + 9] = 0;
    5 Y# i/ p6 r+ D& p3 u
  811. 3 E& i6 \; M& ?! O- T! Q& k
  812.         /* write the 24-byte frame header and the 10-byte fragment header */
    7 b9 l( Y9 I6 e, [
  813.         if (fwrite(rbt->frame_load_buffer, 24 + 10, 1, outrbt_file) != 1)+ F! D: e, P( o, V, H
  814.         {9 U- E) U6 u/ J2 `: q& t2 x
  815.             printf("problem writing frame %d\n", i);5 z2 r8 V* {/ O  f
  816.             return 0;/ y. a# q7 g' B' a- J
  817.         }( a9 h$ H* q7 e& h0 g2 S$ w& n" F( Z6 s

  818. % _1 H) B1 I+ x4 B. ^
  819.         /* write the new compressed frame data */: W  G/ s3 i$ {5 Z# n8 a9 s: r
  820.         if (fwrite(pb->bytes, pb->byte_index, 1, outrbt_file) != 1)
    ; r" G3 Q0 ~: @3 ]$ N8 Q9 V
  821.         {
    + t( |  W& y) Q' P+ }5 T6 o! X" E
  822.             printf("problem writing frame %d\n", i);
    3 h& M6 @* D/ n
  823.             return 0;3 C. {, H+ r" Q# {3 d- Y7 R
  824.         }$ g9 m) {9 ^. _/ b" g, Z2 x
  825. , O2 }  x! ?' x7 b
  826.         /* write the audio data */
    , t# W2 ]' F: V* H7 K. M# P
  827.         if (fwrite(&rbt->frame_load_buffer[video_frame_size], frame_size - video_frame_size, 1, outrbt_file) != 1)% S( ]! [. ?; L1 |% o+ Y  W, }
  828.         {
    6 ?" K- o7 z7 s9 t, a5 q6 h
  829.             printf("problem writing frame %d\n", i);
    , W. w+ j, C/ l' b  ~
  830.             return 0;
    / L: W0 \- u- T6 C5 e6 l
  831.         }6 z; Q/ v. q  l
  832. - p% Q& h9 r) Y% W
  833.         /* update the table entries */* d$ v% w; ?/ a3 K* X3 w
  834.         video_frame_size = pb->byte_index + 24 + 10;
    1 G9 E' M$ X+ O& V  b
  835.         frame_size = video_frame_size + audio_frame_size;
    9 ~9 M* E5 P; _/ x# ^% u4 k7 q
  836.         rbt->frame_size_table[i*2+0] = frame_size & 0xFF;# }2 ~/ L5 o- h
  837.         rbt->frame_size_table[i*2+1] = frame_size >> 8;
    ( n: X/ ~* I- O" s1 |
  838.         rbt->video_frame_size_table[i*2+0] = video_frame_size & 0xFF;( S$ Z! ?; p. G* A- Y3 q9 R
  839.         rbt->video_frame_size_table[i*2+1] = video_frame_size >> 8;
    0 b3 N( G# Y+ z& \2 A5 X
  840.     }
    ; {, Y5 ~" P2 \- q: ]/ m' F0 |
  841. - [1 f6 y( e/ Q9 N; i
  842.     printf("maximum dimensions seen are %dx%d\n", max_width, max_height);3 H+ z2 e: J: ~9 T( o" v) }
  843. , A& Z5 ]9 A5 E7 ]5 e
  844.     delete_put_bits(pb);
    . P* u1 K$ Z8 L7 A! A, Q/ U& A
  845.     free(full_window);
    * D! Y5 U6 E+ u: Z+ x

  846. 9 Q) A9 v4 A3 I3 D
  847.     return 1;
    ; P/ D$ a' I0 |  c+ S& f* C
  848. }; U( w3 b& J0 n/ H/ g

  849.   f- g/ i; C' `  |% ~1 k
  850. int main(int argc, char *argv[])
    7 }. r# N, A, P4 E" I
  851. {3 V0 h+ x+ G8 i% T1 G
  852.     char *subtitle_filename;
    * p6 T1 `, B& n. U# D
  853.     FILE *subtitle_file;& j0 X& _( V" P
  854.     char *inrbt_filename;
    4 V3 Y+ z3 r; F# T0 J
  855.     FILE *inrbt_file;9 J4 n7 Z( ]% Q$ u( f7 [) `( v9 i
  856.     char *outrbt_filename;
    8 i( V# L7 c% C* a; }0 J; T
  857.     FILE *outrbt_file;
    ( `- M% Q1 U3 ]" r$ b5 Q
  858.     rbt_dec_context rbt;9 W4 E& F+ r$ a& j6 e' C
  859.     int origin_x;6 x0 _9 U8 J/ O+ b0 s
  860.     int origin_y;
      f+ x2 ^" J  m+ j0 i
  861.     int window_width;
    ' w+ r! d6 q$ L  _. s; S# ?, Z
  862.     int window_height;
    + {3 _9 Y* E. K) f- t7 O

  863. . g7 b, E: L. E2 `/ ^2 t  J/ U4 a
  864.     /* testing the bit functions */
    * }& E- K- Z: Q* q; x6 I, X
  865. #if 04 j& o, T1 u' J+ v1 p
  866.     int i;
    & s& J# W8 D; c
  867.     uint8_t bytestream[] = { 0x55, 0xAA, 0x00, 0xAA, 0x55, 0x77, 0xFF, 0x1B, 0x70, 0x8F };( D- ~' @& ~1 T
  868.     int bytestream_size = 10;
    ) D  f5 Y$ d+ K' ]& Q/ \
  869.     get_bits_context gb;
    . P, B& e9 a1 T+ D/ X% K6 @
  870.     put_bits_context *pb;8 K6 r: R4 F! L* ?" g; A9 ^9 U
  871.     int bits;& a" i1 x' ?. r8 k
  872. : ?( y5 L; M& I
  873.     init_get_bits(&gb, bytestream, bytestream_size);* ]) }, |7 Q5 O
  874.     pb = init_put_bits();
    / c# H; V! k6 V* r
  875. , A7 S: G: {( l9 h" u5 N+ I( C. p
  876.     for (i = 1; i <= 12; i++)
    4 Q& Y& M7 ]* N9 i
  877.     {  z' o! ]( J5 p4 y
  878.         bits = view_bits(&gb, i);! J0 w; i  x/ `$ \7 t. K8 B
  879.         printf("view %d bits: %d\n", i, bits);) g; F4 L3 U- U+ G, s  c
  880.         printf("read %d bits: %d\n", i, read_bits(&gb, i));& V% l  V( F8 r
  881.         put_bits(pb, bits, i);0 L5 q" S& l( M4 h: B2 O9 w
  882.     }( i0 U0 }; ?& b  Z( Q% j
  883.     put_bits_flush(pb);
    * N7 g( A) Y8 T

  884. / V" t6 x/ g- h* z
  885.     printf("original bytestream:\n");
    3 f" x5 ~% }1 ]6 p. |* d: [
  886.     for (i = 0; i < bytestream_size; i++)) C+ z8 O: O5 g- c
  887.         printf(" %02X", bytestream[i]);
    & p% y9 b4 t7 S& z0 S7 j: L
  888.     printf("\nnewbytestream:\n");
    0 S8 A* X! ?) v
  889.     for (i = 0; i < pb->byte_index; i++)+ ~! Q. T7 r: T$ O+ I( b( `& f& W! v
  890.         printf(" %02X", pb->bytes[i]);
    % X* x1 [) z2 B
  891.     printf("\n");( |6 [( w) a+ p

  892. " d$ n3 g8 o( `' e0 n$ _/ o! k' a. R
  893.     delete_get_bits(&gb);0 A( |* C  G$ f' y- `+ Z7 X
  894.     free(pb);2 t& O4 y6 u5 Y( m
  895. #endif, N) R2 M" Y% E( ]
  896. , `6 U9 ^$ H5 l/ ^
  897.     /* validate the number of arguments */& I( e1 @# O& n3 K' ~
  898.     if (argc != 8 && argc != 9); K& L( q9 n5 R# S" P6 v
  899.     {" |5 |: r! n. {. D' {
  900.         printf("USAGE: subtitle-rbt <subtitles.ass> <in.rbt> <out.rbt> <origin X> <origin Y> <width> <height> [dump_frames]\n");
    ! `. ?; ?5 U' G
  901.         return 1;
    3 H# P& M; ~  y* w" ^& W' i
  902.     }& `9 l) e: c  C" u
  903.     subtitle_filename = argv[1];9 |7 ?) K  U9 \( R
  904.     inrbt_filename = argv[2];
    7 e4 X9 a2 ~* D- i  k
  905.     outrbt_filename = argv[3];
    & p! v1 Y. `3 @0 W, C$ c7 o
  906.     origin_x = atoi(argv[4]);
      {; Z$ N% v, l% g) C
  907.     origin_y = atoi(argv[5]);
    6 z2 P7 i- [- F8 p9 [2 e
  908.     window_width = atoi(argv[6]);( e, e4 R) E2 j1 w
  909.     window_height = atoi(argv[7]);  f9 L  U5 v0 ?* k. `
  910.     rbt.dump_frames = 0;
    / e& ~3 {2 v4 F) O- X% Q6 @  h! a
  911.     if (argc == 9)7 N  [; }6 s* d" E2 I9 m
  912.         rbt.dump_frames = 1;
    9 R+ d% \( ~2 }3 w# ]

  913. + r, J4 R$ i4 @8 k! s+ ]% D; s
  914.     /* verify that the specified input files are valid */& i$ {' l3 S5 ^. T2 ^
  915.     subtitle_file = fopen(subtitle_filename, "r");
    # @) }9 I4 M4 {
  916.     if (!subtitle_file)
    . D" E0 A2 {2 C9 T( k
  917.     {
    1 x- p9 u0 ~  t# t# L
  918.         perror(subtitle_filename);- _/ }4 W3 \% S/ |5 E
  919.         return 1;
    1 q/ u! y: ^9 T4 X
  920.     }2 q! y6 w. g- x. \2 o. q$ ~4 Z
  921.     fclose(subtitle_file);1 k8 n7 c2 }" J8 |0 T" C9 \0 s/ D
  922.     inrbt_file = fopen(inrbt_filename, "rb");
    1 _4 H( W3 R' w6 ~: n
  923.     if (!inrbt_file)* d1 m- ?& o5 ?- L! H# E% O
  924.     {2 G: I: D4 `, L3 b9 p$ a; R
  925.         perror(inrbt_filename);6 y! X! D2 T* P9 V( E( @5 p8 @7 P
  926.         return 1;, y; D6 ?- j& B, _
  927.     }+ i5 ]7 `6 }( j# G( f8 j
  928. 7 B% u# P0 n# t8 }7 b% j6 @
  929.     /* initialize the subtitle support */  b1 Z+ R% T8 d7 b) K& k/ O
  930.     rbt.ass_lib = ass_library_init();
    5 Z4 b6 G* |! k  S7 Y0 g' _
  931.     rbt.ass_renderer = ass_renderer_init(rbt.ass_lib);
    ' {! E& T, ?% q7 I! B9 I  V" c
  932.     rbt.ass_track = ass_read_file(rbt.ass_lib, subtitle_filename, "UTF-8");
    , r; P. q. J5 z" z$ q
  933.     ass_set_frame_size(rbt.ass_renderer, window_width, window_height);
    4 }8 r% q' s9 P2 G% L+ b5 n+ j
  934.     ass_set_fonts(rbt.ass_renderer, NULL, NULL, 1, NULL, 1);
    ( ]) J5 ?2 `/ W& @0 N0 h# g. q0 S
  935. 2 ~. B, t! a( C8 Q3 u$ u2 B
  936.     /* open the output file */
    3 B! p3 D5 Z+ N% `  K- \
  937.     outrbt_file = fopen(outrbt_filename, "wb");
    " E& O4 j5 f0 G$ y+ }
  938.     if (!outrbt_file)
    + E4 ^- D- k+ e' R/ w1 A
  939.     {
    . @$ x$ m0 a  N# j
  940.         perror(outrbt_filename);* X  H. d# Q( @# q' a6 I
  941.         return 1;
    ' r; z0 P/ ?4 a. j1 F$ w. V
  942.     }
      p& `5 g4 t* E; r% R) r
  943. ; h6 i4 Y* E2 k3 L
  944.     /* transfer header from input to output */& q4 R; `5 e. A; v
  945.     if (!load_and_copy_rbt_header(&rbt, inrbt_file, outrbt_file))
    , L8 N* C* }$ r9 l9 R
  946.         return 1;/ ]$ J6 E9 R" e2 ^1 D

  947. ' G  S- Q% k9 G( ]9 N
  948.     /* rewrite the frames */
    * w' k3 ]  T. a; Q& t
  949.     if (!copy_frames(&rbt, inrbt_file, outrbt_file, origin_x, origin_y,6 Y- R! b% y# h8 j. l
  950.         window_width, window_height))0 [" {/ ~0 d6 j* E# v& [- B6 z
  951.         return 1;
    : C3 t4 g  q! D" a. n* ~3 O4 ~
  952. 4 K3 N8 L- E2 q
  953.     /* write the modified frame size tables back to the file */$ Z8 y/ ]" D  g8 Y
  954.     fseek(outrbt_file, rbt.video_frame_size_table_offset, SEEK_SET);
    / b2 Y* E5 V6 p" g) _
  955.     fwrite(rbt.video_frame_size_table, rbt.frame_count * sizeof(uint16_t), 1, outrbt_file);8 ~) _3 C% F( v6 n  d
  956.     fseek(outrbt_file, rbt.frame_size_table_offset, SEEK_SET);" g4 O) C/ k% s
  957.     fwrite(rbt.frame_size_table, rbt.frame_count * sizeof(uint16_t), 1, outrbt_file);/ r9 q& k/ ]: C5 \

  958. 8 ~2 {0 p6 [1 c+ \3 f
  959.     /* finished with files */, ^2 e9 j: \' P' T0 I& j6 h
  960.     fclose(inrbt_file);
    . q1 M- x4 P& E. f" o/ `; y
  961.     fclose(outrbt_file);
    , H( C' \1 s% J3 q* c7 O0 W

  962. 0 q; L1 `& l" X- i( B; _2 c# A. ^+ g
  963.     /* clean up subtitle library */2 @! U/ k1 y0 ?4 |0 M* }
  964.     ass_free_track(rbt.ass_track);
    : {, o1 V: H2 q0 j, _4 r
  965.     ass_renderer_done(rbt.ass_renderer);
    & M, Z. [% O0 F/ D- V' z
  966.     ass_library_done(rbt.ass_lib);% Y6 ~- p/ `- t2 x
  967. ( D/ B$ A' j8 r) p; ^( H
  968.     /* clean up */# t2 @4 _, B9 G! f! \
  969.     free(rbt.frame_load_buffer);
    ) F8 i1 ~* |* H8 |
  970.     free(rbt.video_frame_size_table);5 v- f4 O; B/ u, o
  971.     free(rbt.frame_size_table);
    2 y0 S. s8 v# K+ g( M# T8 N: R

  972. " {2 c( F& l) I
  973.     return 0;+ ^) u: s+ d' }& z! n
  974. }
复制代码
. c5 c. t/ v* _5 u* Q% p

+ z8 Z2 J$ e1 ?1 K& J! [
* X3 G8 {6 ^7 A+ Y/ U- @) L# X! x2 ~  D
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 很美好很美好 很差劲很差劲
回复

使用道具 举报

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

使用道具 举报

板凳
 楼主| 发表于 2009-11-19 11:38 | 只看该作者
引用第1楼soring123于2009-11-19 11:09发表的  :1 E/ [; V( d* i8 X1 ^* }/ C
这游戏有字幕吗?
* t* J1 z( d2 j1 o; {5 y# K
好像没有字幕,我说的是给视频外挂字幕方式的汉化。
( u1 N; l; P/ P& }( u% v3 A% @7 ~6 J就像syberia2汉化版下面那行字一样。
回复 支持 反对

使用道具 举报

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

使用道具 举报

5#
 楼主| 发表于 2009-11-19 17:39 | 只看该作者
引用第3楼soring123于2009-11-19 17:07发表的  :, l* d2 |' B; c# |2 x* o' s
我记得是没字幕的 比较麻烦 都是视频的
1 Q- G, b! q) r8 x' S- ?7 j
给视频外挂字幕方式汉化也许能行。% m. y+ e0 D: Y3 b; 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日,是全球华人共同的冒险解谜类游戏家园。我们致力于提供各类冒险游戏资讯供大家学习交流。本站所有资源均不用于商业用途。

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