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

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

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

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

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

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

本帖最后由 shane007 于 2021-1-2 13:56 编辑 % J9 z/ ~. K6 W( v

, n! p- I- k9 i* n% F6 ]$ W* q# m最近找到了一些和幽魂系列Phantasmagoria 有关的资料,3 X& p( I" {6 w# ~4 b6 S
也许将来可以用于汉化。
) t) F4 s$ C6 v% b2 H' a% S+ M) ]. S6 J/ y* L
和日文版有关的信息1 r! m) H7 ?$ N* T
http://anthonylarme.tripod.com/phantas/phintgtp.html
% B- [# B4 C9 R& s: w( m6 M% u  q- u" d
相关工具+ n1 L2 C$ p0 S: m
http://anthonylarme.tripod.com/phantas/phcheats.html( y  r$ G$ {/ k8 Z" V6 G
-----------------------------------------------------------------------& X; H! c, N$ ?( s# |/ T
2012/1/2  更新
2 ?8 m/ t$ Q! ~( @+ K' Z" s' o关于幽魂游戏的字幕/ [1 l) |; a% v  A3 c2 Q
Phantasmagoria subtitles function discovered - ScummVM :: Forums  r) C* |9 l) W4 M

. {$ o# ]  r2 s. c6 B' V3 Y$ UVMD文件
% c1 Q/ U0 D# Z3 R2 L9 }5 DSubtitling Sierra VMD Files | Breaking Eggs And Making Omelettes (multimedia.cx)VMD - MultimediaWiki
2 E+ ]+ n0 J  L6 A/ P- B2 A! C: `& Z4 E6 T
字幕
% i( ?5 r! x6 ]6 C7 [$ pSubtitling Sierra RBT Files | Breaking Eggs And Making Omelettes (multimedia.cx)" t- u+ y# c4 o" |% o* O

7 O" n4 {5 ^  `' n: r' UFFmpeg/subtitle-rbt.c at feature/VMD_encoder · multimediamike/FFmpeg · GitHub) `& T2 X7 [1 a: p, {
  1. /*0 q# N/ R$ \" X& L& b* A
  2. * subtitle-rbt.c
      V! v3 {1 Y( i7 N; n8 I. U
  3. *  by Mike Melanson (mike -at- multimedia.cx)
    : b, o. }4 E. X
  4. *
    $ z6 i5 U5 H8 \, q9 u& r
  5. * build with this command:' ]2 {0 w" e5 L. B; \
  6. *   gcc -g -Wall subtitle-rbt.c -o subtitle-rbt -lm -lass
    2 S0 S2 X) I& x* \0 S, [  v
  7. */
    , y9 A6 k6 h: k, \8 ~
  8. ! ^: [( Y7 R$ e  V
  9. #include <inttypes.h>
    * N: T7 `4 W' a) `- K
  10. #include <math.h>
    - {  \1 Y  q+ d1 e
  11. #include <stdio.h>
    ( U7 V8 q( [6 b, V/ u( {
  12. #include <stdlib.h>
    5 H! ~* n7 M" G( N0 s( }
  13. #include <string.h>: L* T9 c. w( k
  14. & y$ p( V  y$ z$ `# \3 E* D
  15. #include <ass/ass.h>
    8 E# m6 |+ _0 d3 x: C. M0 x; x

  16. 3 \& X# P0 R6 E* f
  17. #define LE_16(x) ((((uint8_t*)(x))[1] <<  8) | ((uint8_t*)(x))[0])- U2 k! z- |8 o: J

  18. 7 w  q+ P: J4 a6 C7 _
  19. #define LE_32(x) (((uint32_t)(((uint8_t*)(x))[3]) << 24) |  \+ I0 Q1 l" O9 }
  20.                              (((uint8_t*)(x))[2]  << 16) |  \( e+ y$ `0 D0 p% w' T) t2 w& G
  21.                              (((uint8_t*)(x))[1]  <<  8) |  \$ g$ M/ B# `3 v* n
  22.                               ((uint8_t*)(x))[0])
    3 h. q2 k1 ~7 b/ S; a9 H
  23. 5 y+ h8 K& T+ K. c9 W+ A
  24. /*********************************************************************/  `' I/ d+ k8 e0 F- |
  25. # n  i# {+ D4 a! V0 u
  26. /* Bit reader stuff */! N; w& }3 j  L% g$ R, N  B
  27. - f  c$ c" [- j) P0 @, N; e; k
  28. typedef struct. W, [* P' S8 w0 s
  29. {5 T7 n1 B8 a" Z, b
  30.     uint8_t *bytestream;
    . X6 E4 T: E; Y/ ^
  31.     int bytestream_size;
    7 {2 t+ X  Z. d  T
  32.     int index;8 D# }2 {" ?5 ^8 G+ e: p
  33.     uint32_t bits;) o* C9 k6 {9 J
  34.     int bits_in_buffer;
    $ M! H3 o9 J3 ?1 ~0 y
  35. } get_bits_context;
    7 {& a9 ~9 N7 ?- {3 M

  36.   o) Q8 T8 j2 I
  37. static inline void reload_bits(get_bits_context *gb)  ^8 R1 `. D# j+ H8 ~8 Y% b6 }6 S
  38. {
    # S3 w! J' n% l" D3 T- Y
  39.     while (gb->bits_in_buffer <= 24)% \5 v. K% ]& S: c; F2 {
  40.     {1 @# G: L# ~0 e" @( B' W) }9 e
  41.         if (gb->index < gb->bytestream_size)
    ; K, ]7 d) L$ f: D( k
  42.             gb->bits |= (gb->bytestream[gb->index++] << (24 - gb->bits_in_buffer));4 N$ }' y% i2 {/ p
  43.         gb->bits_in_buffer += 8;% ~1 e+ g% n; ?8 T  R7 D( Y: a& M8 A
  44.     }
    $ J0 k9 ]9 @! @: p
  45. }
    3 G8 \9 F  K/ |- n' H& {0 t

  46. 9 Q6 X: \# f2 t' _
  47. static void init_get_bits(get_bits_context *gb, uint8_t *bytestream, int size)
    ! o2 v: a7 `" Q; X! _
  48. {( }& a& i/ Q! K
  49.     gb->bytestream = malloc(size);) H0 q- O5 Z+ m  F& ^( o( v
  50.     memcpy(gb->bytestream, bytestream, size);
    & U! u( ?3 U7 t5 W! h
  51.     gb->bytestream_size = size;9 B+ l  b- M& @3 b0 P  t7 w% G
  52.     gb->index = 0;4 ?/ y1 V- G- {& b" B
  53.     gb->bits = 0;- Z. G- q0 {3 m! n" H0 Y$ Z
  54.     gb->bits_in_buffer = 0;
    ! P8 I# Y1 o- x2 X, ^

  55. " q5 }' ?9 ?# I* B( ]/ q3 s7 U$ F
  56.     reload_bits(gb);
    - s* c/ s: ?8 B  W, a
  57. }- R: [: p4 M( L4 \
  58. 2 y$ Z/ u1 F& [% B( A4 z( L( s& _
  59. /* read bits without consuming them from the stream */% t, J, I: E' T+ W' V9 s6 g
  60. static int view_bits(get_bits_context *gb, int count), V: b. Y9 ?! P/ A
  61. {
    ( |3 H- |& x3 o4 ^
  62.     if (count >= 24)1 i5 O  o8 d3 B+ |( j
  63.         return -1;, L5 M& h) l; x/ x
  64.     if (gb->bits_in_buffer < count)
    5 U) W* H' Z# q4 G2 W9 ?
  65.         reload_bits(gb);$ j2 z% f' }% G" G
  66.     return (gb->bits >> (32 - count));
    ! ~1 v, t% o, ^( ?2 b5 z+ m
  67. }7 |8 U9 ~$ |! X) e/ f4 `2 B" K
  68. % w8 x: z; g8 @9 z2 g3 V9 m
  69. /* read and consume bits from the stream */
    1 o/ Y6 h- W6 M7 h
  70. static int read_bits(get_bits_context *gb, int count)" w* d" l7 k% r
  71. {
    % H  l1 w$ t6 Z" P: [9 H
  72.     int value;8 Q+ B; B4 `8 O7 E2 A% R
  73. ! E3 @! S7 f2 }0 b# E0 W0 H
  74.     if (count >= 24)
    - T! M: m4 u0 |$ C8 ]. e; g# [- C
  75.         return -1;( r; f( v. X' l
  76. ; k6 _9 A  J8 o+ Z* A9 g% ]
  77.     value = view_bits(gb, count);& F) W" T8 c1 d+ X( U
  78.     gb->bits <<= count;
    7 ~6 [: ?% b/ I( ^, J
  79.     gb->bits_in_buffer -= count;
    2 H. h2 c- L2 [1 w1 q% i; _6 ?
  80. ! R$ ~" b+ z7 M0 l
  81.     return value;* }7 f- T$ L2 _
  82. }/ q6 l' v& W  V( @6 C

  83. % z  F5 s% A7 q" I
  84. static void delete_get_bits(get_bits_context *gb)
    & [* w! V7 D% R! L( `+ h+ m
  85. {
    ; q' l$ y, @4 Z% e: o( k
  86.     free(gb->bytestream);
    ) `  b5 e: N; `4 D5 g; u7 h
  87. }
    2 g4 W9 Z1 {/ W1 T$ {8 A

  88. 6 _, b# [0 n- A  q: d/ v
  89. /*********************************************************************/
    - S5 _- N& u/ Y- k, u" O

  90. 1 E5 G2 I4 U8 j1 K; o8 Z
  91. /* Bit writer stuff */; Q/ x6 `  ?+ c7 |7 ~+ B' a

  92. ( W4 V) r) E1 U) J
  93. #define MAX_PUT_BITS_BYTES 63000
    9 V) r0 v% Q! I" `7 m
  94. typedef struct6 M+ q3 u: E/ S) N# p, g" S
  95. {
    . y- t4 c# O( U( X$ R# v
  96.     uint8_t bytes[MAX_PUT_BITS_BYTES];/ ]/ A# }( s/ q4 ?+ B' O( F% m) p, ~# x
  97.     int byte_index;! C% P* U& ]4 n; Z; d
  98.     uint32_t bit_buffer;8 r! Y' B/ G6 n) q3 q9 i2 x
  99.     int bits_buffered;" U: x( a+ R6 ~5 z; @
  100. } put_bits_context;1 z& c0 v4 J% B* p( T

  101. 3 e9 l* t; ~7 L8 ^3 d7 J# _& _
  102. static void reset_put_bits(put_bits_context *pb)" L1 O0 q8 ^$ S1 j2 |$ l% K
  103. {! J$ C! u0 P8 T* _# M
  104.     memset(pb->bytes, 0, MAX_PUT_BITS_BYTES);
    - f' t' F2 N, H/ j4 g# u$ q
  105.     pb->byte_index = 0;
    : b: ], f4 F& m6 q) k, k
  106.     pb->bit_buffer = 0;
    5 n. }" k; ?2 Y6 P" E+ I  b
  107.     pb->bits_buffered = 0;
    * j( b; K4 R9 ]" [( ~7 A+ D0 E
  108. }
    - t* P5 b4 c1 R: o, U  @

  109. 2 `' @$ s; j3 e7 M
  110. static put_bits_context *init_put_bits()" e' l; e" X2 @4 {- o
  111. {9 A/ e; a, ]/ G5 o
  112.     put_bits_context *pb;4 X+ T2 M/ t9 b8 ~. X; @
  113. ! U! w; \3 M: U! _2 n& ]
  114.     pb = malloc(sizeof(put_bits_context));1 Y% v$ b9 w0 C/ T  K( _
  115.     reset_put_bits(pb);
    3 ]5 M' M" p4 J- U' C
  116. 8 w/ I( Y; Y% ^( J3 M- n/ Z. q+ U
  117.     return pb;
    3 d6 Z* _* n# T; F. {0 y% ]" \5 Y
  118. }
    3 A5 ]' D& D+ v  \/ m2 E1 W
  119. ( G5 V* U: I9 G' p
  120. static void put_bits(put_bits_context *pb, int bits, int count)
    7 X. |) b4 G! L0 l1 q: |- ?
  121. {
    ) A" e. Z% ^: x8 P7 t6 |$ K
  122.     pb->bit_buffer <<= count;6 f2 c. N" g: J* g  a+ f0 c5 U
  123.     pb->bit_buffer |= (bits & (~(0xFFFFFFFF << count)));# ]% D; H8 M9 U* J* A0 Q' T
  124.     pb->bits_buffered += count;4 K" M7 P, z1 {, X; T8 a  |
  125. 5 u9 v6 k- Y  V' }% N# A
  126.     while (pb->bits_buffered >= 8)2 n1 w0 Y1 e0 p" _" l9 X, D
  127.     {: o" U* V  ^0 W; g% ]
  128.         pb->bytes[pb->byte_index++] = pb->bit_buffer >> (pb->bits_buffered - 8);
    / G% `$ D- W. b: o2 \
  129.         pb->bit_buffer &= (~(0xFFFFFFFF << (pb->bits_buffered - 8)));9 S1 @7 W. e9 ?
  130.         pb->bits_buffered -= 8;' g  `) W# c% o3 f6 ?6 z1 g  M
  131.     }3 p' m! C0 E. p

  132. , i' @$ v9 e4 I7 S
  133.     if (pb->byte_index >= MAX_PUT_BITS_BYTES)% [  ^0 I% \* I+ Y+ Y2 @% H
  134.     {
    6 D- ?: o& H# k7 I0 d# |% [* S+ d
  135.         printf("HELP! Bit overflow\n");: F' T7 [5 f- Y4 C9 o
  136.         exit(1);
    3 d* b, Q; M9 C) D7 P% P' q
  137.     }1 U+ X: n- t" T8 Q" O" }2 |3 L
  138. }2 m- ~4 O5 X) V/ _3 h) V
  139. , M; h' S9 F. O: i
  140. static void put_bits_flush(put_bits_context *pb)' v+ D) N- @0 p& ?% y& @7 L
  141. {
    0 Q: {" B: N4 O
  142.     if (pb->bits_buffered > 0)3 y8 H( |% [/ F. A" d& Q& M
  143.         pb->bytes[pb->byte_index++] = pb->bit_buffer << (8 - pb->bits_buffered);
    ( s) X# v& @5 Q1 J; f
  144. }
    & `& D  d* I% D0 \! C' {& W
  145. 7 d: d! P  H( V2 o" b; h, x
  146. static void delete_put_bits(put_bits_context *pb)
    4 i5 Z2 L! i' W$ s! H: x7 ]. Z2 n
  147. {$ v  k, o+ p( T
  148.     free(pb->bytes);3 g. `+ x* W6 w9 E/ z- u
  149. }
    , U. S8 O' ?7 H# J/ \

  150. & T4 h5 R' c; a' n$ c# N
  151. /*********************************************************************/" }* j. ]4 z- Z2 w7 g

  152. & j+ L. L) R4 f; }# U
  153. /* RBT functions */; p" m& j( j, h' T2 I
  154. / i! }/ \4 X% J( j& E
  155. #define PALETTE_COUNT 256
    , Q3 \  f# G9 b  N( M8 c* e
  156. #define RBT_HEADER_SIZE 602 k! ]5 A0 b' i  Q
  157. #define UNKNOWN_TABLE_SIZE (1024+512)
    0 B  Y( I6 F+ y
  158. #define SUBTITLE_THRESHOLD 0x70
    * T/ p, e& r) k! r$ c  n/ P# `
  159. #define MILLISECONDS_PER_FRAME 100$ }0 e# S+ o& J

  160. & I: E" I- |  H$ y9 n$ F
  161. /* VLC table */8 y; K1 r  |6 W% _1 E
  162. #define VLC_SIZE 4
    7 a* [( K/ Q3 k; d$ a
  163. static struct# x1 p$ q8 E' A7 {) O8 Y  l
  164. {# n8 ]9 x8 x6 u" Y! B1 E
  165.     int count;$ v. T/ a6 C! i. T& c3 e
  166.     int value;
    5 ?1 b/ P. g4 p4 r9 }5 ]8 D- f
  167. } lzs_vlc_table[] =
    7 A: x& N* t1 F! D/ G3 L
  168. {
    ' x  V3 \$ {- F; c1 S/ R5 t
  169.     /* code length = 2 bits; value = 2 */  B) ^) K4 W! U" d
  170.     /* 0000 */ { 2, 2 },
    4 K/ K8 L# p- ~' h
  171.     /* 0001 */ { 2, 2 },7 K9 s5 Z  t# t" J" C
  172.     /* 0010 */ { 2, 2 },
    - a! [, j& I& B! E
  173.     /* 0011 */ { 2, 2 },3 Q; [, P# k3 B! c3 I
  174. " n0 x( G1 H3 e1 Y3 i# _
  175.     /* code length = 2 bits; value = 3 */; R' }( m% j: ?
  176.     /* 0100 */ { 2, 3 },) X8 L: _+ i* B' Y8 m( Q$ Y- j
  177.     /* 0101 */ { 2, 3 },* o6 P% z; {/ e% P5 x/ n
  178.     /* 0110 */ { 2, 3 },% M0 d. v4 K+ @7 s" A# x0 F
  179.     /* 0111 */ { 2, 3 },
    5 T' u( R* `! x: f7 f  L2 q
  180. # ]3 S1 P# Y4 Z  y: [9 l
  181.     /* code length = 2 bits; value = 4 */
    " g2 h- B# D5 i6 H: H
  182.     /* 1000 */ { 2, 4 },
    % s2 D$ l! k: }: f" a3 B
  183.     /* 1001 */ { 2, 4 },
    2 `5 l+ @, N5 l% w3 c" {/ [/ F
  184.     /* 1010 */ { 2, 4 },- E+ C+ n0 o7 c5 |5 A0 n( j
  185.     /* 1011 */ { 2, 4 },# f, O% ^1 V6 G

  186. + Z, n4 y1 n0 {0 `/ Z7 @) c% n
  187.     /* code length = 4 bits; value = 5 */; H$ p4 T6 o. J0 F( @6 `8 k. R
  188.     /* 1100 */ { 4, 5 },
    5 m3 n! E& Z& o: ]

  189. - h5 d1 {# `$ }: ?- W) Y
  190.     /* code length = 4 bits; value = 6 */0 N% \: J: k% Y( G
  191.     /* 1101 */ { 4, 6 },
    2 D* ]: T5 M& b8 o$ ?1 w3 ^3 b4 l

  192. # E; ]" u8 X1 n5 ]/ [: v4 a9 T* ]9 A7 n
  193.     /* code length = 4 bits; value = 7 */
    , ]; n" T0 k) {- A
  194.     /* 1110 */ { 4, 7 },
    5 z+ n  S/ S) t8 {0 O* ~/ w( L/ u
  195. 9 t2 f; _& `+ u! ^; O, Q! j" K
  196.     /* special case */
    3 l7 p6 B4 e& C* \  `8 a
  197.     /* 1111 */ { 4, 8 }
    ; T1 p+ N3 j+ d8 ^$ q
  198. };
    6 f. u2 u( j% M! _
  199. $ x6 ]# g5 s4 L( l4 V
  200. typedef struct
    6 {6 h3 `" U( Z$ B- \( I4 h
  201. {+ W8 }- C2 q' V) ~8 D) E
  202.     int version;0 g3 U5 x$ d/ Z5 r
  203.     int width;% e7 B& x3 c' v  I4 o( m7 c
  204.     int height;
    ) d+ G# ?8 f, p& G5 `
  205.     int frame_count;
      J' \8 V9 ]5 W
  206.     int audio_chunk_size;
    : j7 ]* s9 p0 ]
  207.     uint8_t palette[PALETTE_COUNT * 3];
    , ^( G! a! i" g: I3 a; p5 Q
  208.     off_t video_frame_size_table_offset;& t# G4 M9 l! R' j: ?- ]
  209.     uint8_t *video_frame_size_table;3 ^6 Z) _5 R0 ]1 O
  210.     off_t frame_size_table_offset;9 N% Z% v) h8 j5 M' t7 k# e6 Z
  211.     uint8_t *frame_size_table;
    4 k& c  D5 G' I( N, M4 V+ v2 _% ?
  212.     uint8_t *frame_load_buffer;0 A% W* z2 J( ~' `
  213.     int dump_frames;
    , V2 D- C4 ^5 u* g2 b
  214. 7 a+ j- g$ G9 P) W- j
  215.     /* subtitle library */* @7 L! P' l. X( n
  216.     ASS_Library *ass_lib;9 m! l$ c1 Q2 m; E6 V1 l  N
  217.     ASS_Renderer *ass_renderer;
    + N& l5 b; R+ e) g) s4 w; h
  218.     ASS_Track *ass_track;; k7 d% C# s, K. N4 G
  219. } rbt_dec_context;
      I% `9 Z; k. H' z8 ?
  220. 3 ^4 V: b" u% U+ l3 b" z/ z6 b# V
  221. static void dump_pnm_file(char *filename, rbt_dec_context *rbt,
    ( m9 f- B! \4 I  c6 D3 F* E% T
  222.     uint8_t *image, int width, int height)* A* d* g8 D+ K8 J, x6 T9 o$ l
  223. {* `! H1 [; j: [) u9 N. L  l! p: `
  224.     FILE *outfile;
    * d8 d$ F& m. V. t' v! ?% N9 ]3 a5 T
  225.     uint8_t bytes[3];- F) Q: r2 q" ?- u  [
  226.     int p;( Q1 s/ U$ N! A& |! H$ e
  227.     uint8_t pixel;! a% n# J7 E. f% t- m) n3 h
  228. 2 T; b$ D+ v' k) h3 r
  229.     outfile = fopen(filename, "wb");
    " u5 c5 F7 r4 d
  230.     fprintf(outfile, "P6\n%d %d\n255\n", width, height);+ k+ i" ~1 G0 s8 [1 ]- S
  231.     for (p = 0; p < width * height; p++)
    1 ~$ |/ E9 u6 R! W/ i0 r
  232.     {3 _! K+ f- w( O# J5 F. r% T5 y
  233.         pixel = image[p];
    $ P' e7 T0 d% f3 F5 z
  234.         bytes[0] = rbt->palette[pixel*3+0];
    ) b+ X  A5 l# t8 [. M
  235.         bytes[1] = rbt->palette[pixel*3+1];( }( P4 S" U4 e! {# b/ `4 K
  236.         bytes[2] = rbt->palette[pixel*3+2];
      t* t" X7 ^5 s3 ?/ p; |
  237.         fwrite(bytes, 3, 1, outfile);0 |% B6 u, S$ a( K$ C
  238.     }& A$ p* ^3 {( U% R
  239.     fclose(outfile);+ _- w+ ~) n3 U) @! {
  240. }
    - H5 {. Z7 }/ Q  O

  241. 3 ]; D6 N/ P& T0 c( n
  242. static int load_and_copy_rbt_header(rbt_dec_context *rbt, FILE *inrbt_file, FILE *outrbt_file)
    ' U$ X, T2 y! k+ B7 Y+ K/ k' H
  243. {9 x+ b9 }3 ^: y8 B' m
  244.     uint8_t header[RBT_HEADER_SIZE];) ~' e+ F! o- h8 i5 B3 E: e* b$ p
  245.     int palette_data_size;
    ) o$ s% I7 W- x% C  [
  246.     uint8_t *palette_chunk;, C  v1 p+ r- z$ T/ Z; @7 ~
  247.     int unknown_chunk_size;
    $ o& x; Y: ]. C3 I' n( j
  248.     uint8_t *unknown_chunk;
    6 u; k" Q/ @5 \" F. O8 q
  249.     uint8_t unknown_table[UNKNOWN_TABLE_SIZE];2 t7 {- Z7 H" J+ R: z
  250.     off_t padding_size;8 n' F: ^% T% h7 ]1 b( I4 X  z
  251.     uint8_t *padding;2 c7 h# z0 V/ W
  252.     int i;
    4 o0 [0 J  [& [; H
  253.     int frame_size;4 }1 B4 h6 k2 E+ a  ^, b  R+ I
  254.     int max_frame_size;8 G3 Z5 _! n& o
  255.     int first_palette_index;
    . p- }2 T# ?. W, F- |
  256.     int palette_count;
    ( e* y. ]6 E' @2 V0 x
  257.     int palette_type;
    1 x! E7 o$ w2 \* U3 V# T
  258.     int palette_index;
    7 d4 b8 |7 i; B: V5 c
  259. " y/ ^2 v; a" i3 s9 T1 \# T
  260.     fseek(inrbt_file, 0, SEEK_SET);: U1 _# J: k' ^( I5 E0 K
  261.     fseek(outrbt_file, 0, SEEK_SET);
    ; R2 w5 g9 l! \: w. i
  262. ; s4 F- t5 x9 z# D, ], t; e2 v
  263.     /* load the header */$ J; O3 A. h% Y/ F8 b: r
  264.     if (fread(header, RBT_HEADER_SIZE, 1, inrbt_file) != 1)
    ( @4 E; q8 z9 \: t) C
  265.     {0 m* |0 U% T& t+ Q
  266.         printf("problem reading initial RBT header\n");) ]5 w6 J1 Z* K7 x; t& i
  267.         return 0;
    ; Y" F+ {$ M. C! F* p2 Z+ c
  268.     }
    ; T7 L+ ~& \+ R2 V: F1 Y/ l
  269. 4 D9 h: u2 G7 C8 i7 l
  270.     /* copy header to the output */& V6 {  C% k. _, R4 L2 f; k
  271.     if (fwrite(header, RBT_HEADER_SIZE, 1, outrbt_file) != 1)
    : u# t' y' q/ B3 q: I2 T3 n
  272.     {/ ^* ^2 \0 m% c% r6 d7 `# Y/ x
  273.         printf("problem writing initial RBT header\n");
    ( ~( @& V9 [$ B0 S
  274.         return 0;0 a) _7 c- M# y0 |( s; ~0 Z
  275.     }
    . r8 J6 r  @  W
  276. ) |/ R3 f# b1 Z- e
  277.     rbt->version = LE_16(&header[6]);4 G+ a% `6 s7 B
  278.     rbt->audio_chunk_size = LE_16(&header[8]);
    ' N/ i' H( L! Q( l7 @; R
  279.     rbt->frame_count = LE_16(&header[14]);
    $ R) G4 m! s+ \9 ^7 k

  280. 1 i6 _5 m+ Q/ ]" {* ~8 F) Q$ e* r
  281.     /* transfer the unknown data, if it's there */. l5 M! k2 R. v/ |' A
  282.     unknown_chunk_size = LE_16(&header[18]);2 W9 L- c; w9 U6 d6 y4 k% S
  283.     if (unknown_chunk_size > 0)0 J6 `- q  F  ~6 H( K
  284.     {% B3 w. X7 K- k! l
  285.         unknown_chunk = malloc(unknown_chunk_size);7 U- z* u* e7 z  F
  286.         if (fread(unknown_chunk, unknown_chunk_size, 1, inrbt_file) != 1)0 G0 B5 _  F' M8 k1 H
  287.         {
    * N. p. ?# d/ `& X
  288.             printf("problem reading unknown data\n");
    " p0 _( [; \* Z& e
  289.             return 0;
    ) n5 F, Y) Q6 ]$ p
  290.         }
    6 p5 D8 f! X9 v) X& f. G5 [( @! R
  291.         if (fwrite(unknown_chunk, unknown_chunk_size, 1, outrbt_file) != 1)4 i# r& k+ f  K' a: z
  292.         {0 S9 R0 a! Y7 T6 k$ Q+ d5 D
  293.             printf("problem writing unknown data\n");
    - T& ]% b! H' F4 }) \
  294.             return 0;2 L5 p& c* F. U, O! A0 V
  295.         }4 u$ s' z# G& {# s6 }
  296.         free(unknown_chunk);2 o( a8 d9 V* Y/ i6 j( e/ M
  297.     }
    % G9 e6 l2 N  |
  298. 9 x" p5 I3 V# f
  299.     /* transfer the palette chunk */) w! a, ^& n( Y( I2 j
  300.     palette_data_size = LE_16(&header[16]);7 }5 ?1 ^8 j$ ?" o2 f  J
  301.     palette_chunk = malloc(palette_data_size);" ^, |1 g7 K& ]2 Z3 E" n7 b. y
  302.     if (fread(palette_chunk, palette_data_size, 1, inrbt_file) != 1)( f* B  P0 Q/ l7 s9 U1 ?
  303.     {
    1 L* b1 d+ v# ?, X. D( g( }
  304.         printf("problem reading palette\n");4 ]* [( |! N) E2 x! [: d: I
  305.         return 0;9 o1 D; r" p0 L8 X6 O4 e
  306.     }5 d0 t4 T6 q$ u9 C- o6 w8 Y
  307.     if (fwrite(palette_chunk, palette_data_size, 1, outrbt_file) != 1)
    8 _) b, u( I) h& M2 ^
  308.     {8 `& S6 k# I- t: l7 E/ ]+ a
  309.         printf("problem writing palette\n");
    9 W9 e" F/ D) l$ h6 n
  310.         return 0;
    5 a& V  _7 ]* }
  311.     }& X  I1 l* w" Z+ b) P; w6 I  p2 N, l5 \2 A
  312.     /* load the palette into the internal context */8 m, v7 P$ o2 |8 n7 F
  313.     memset(rbt->palette, 0, PALETTE_COUNT * 3);
    0 v$ h5 p$ E' S6 ^% _! X/ z) a
  314.     first_palette_index = palette_chunk[25];+ z( G7 S/ Z, x/ h" B
  315.     palette_count = LE_16(&palette_chunk[29]);) \" r6 }* ]* f+ f" m
  316.     palette_type = palette_chunk[32];9 I6 C+ d3 H) ~" m; l
  317.     palette_index = (palette_type == 0) ? 38 : 37;
    $ X" H# i9 i, v. o0 e' j8 |
  318.     for (i = first_palette_index; i < first_palette_index + palette_count; i++)8 a- k# J5 W8 l8 L$ C
  319.     {4 R' Z  r( m/ J
  320.         rbt->palette[i*3+0] = palette_chunk[palette_index++];: @! V* z+ k9 K; D* d9 Q
  321.         rbt->palette[i*3+1] = palette_chunk[palette_index++];
    & x  w- W0 Q9 f5 e3 i
  322.         rbt->palette[i*3+2] = palette_chunk[palette_index++];" [! m* w0 C# e5 N! c( z
  323.     }; P6 r0 v& }; g% J% y
  324.     free(palette_chunk);9 D% g1 U# ~: y6 a) ~& H. V
  325. # C( \5 l' w, O5 W- w9 O$ E; w
  326.     /* copy the video frame size table (2 bytes per frame), as a placeholder */
    ( w6 C2 d1 [# o$ D  w& q  g
  327.     rbt->video_frame_size_table = malloc(rbt->frame_count * sizeof(uint16_t));
    - E+ W- u+ y& q2 W5 Y8 C  n
  328.     if (fread(rbt->video_frame_size_table, rbt->frame_count * sizeof(uint16_t), 1, inrbt_file) != 1)
    0 J" u8 p& g: I9 u6 x6 v
  329.     {
    3 F# Y5 `7 C, {0 w8 i/ h; ?- {( w5 d& b
  330.         printf("problem reading frame table\n");* _7 x) f" g3 t0 s- p0 O3 |
  331.         return 0;
    9 L; R" t, }1 X# G$ d% o
  332.     }4 H  U- d6 o: e- Y# X" I5 S
  333.     rbt->video_frame_size_table_offset = ftell(outrbt_file);6 n# [4 a3 y; l6 S2 ^
  334.     if (fwrite(rbt->video_frame_size_table, rbt->frame_count * sizeof(uint16_t), 1, outrbt_file) != 1): O8 p% l5 W- k9 x% d
  335.     {
    + }) F; g, o& M$ l3 z# Q3 z
  336.         printf("problem writing frame table\n");
    8 m, A9 u& a% d3 C! k
  337.         return 0;  ]+ N9 j( P& S" M& Z+ j2 [
  338.     }
    8 S' U$ f0 q( E/ ~$ k) Z
  339. ) G% L+ {9 A7 J9 A
  340.     /* copy the frame size table (2 bytes per frame), as a placeholder */% g) ?1 b9 o& F6 m6 m8 x; x
  341.     rbt->frame_size_table = malloc(rbt->frame_count * sizeof(uint16_t));
    4 C- _4 b' K. r1 d+ s
  342.     if (fread(rbt->frame_size_table, rbt->frame_count * sizeof(uint16_t), 1, inrbt_file) != 1)
    7 _3 ~0 L9 Q' j! x" S! ?7 h
  343.     {3 f+ ]* h3 l. \4 [) u" e5 H
  344.         printf("problem reading frame table\n");
    4 u. ~' T) G9 t, k4 M; I8 L
  345.         return 0;
    / r9 G& u0 e" {# B! W
  346.     }7 z* f+ Z2 y3 @- x
  347.     rbt->frame_size_table_offset = ftell(outrbt_file);
    " B6 `4 d& o# [* U7 K* p/ d; @
  348.     if (fwrite(rbt->frame_size_table, rbt->frame_count * sizeof(uint16_t), 1, outrbt_file) != 1). R* d. ?6 B6 U3 ]2 d1 G: J. x9 z) ?! r
  349.     {
    * ~) k5 U% V3 U
  350.         printf("problem writing frame table\n");
    * Q; E, k1 H5 U8 {7 {
  351.         return 0;+ \5 u6 A1 Q  C8 X" E
  352.     }/ I; P- d6 R1 ?
  353. ' a+ r- ?+ \" a6 @- M0 L' h# H
  354.     /* find the max frame size */
    % A  k/ V) g7 |. Q
  355.     max_frame_size = 0;$ e) }3 _! d0 d! g: X
  356.     for (i = 0; i < rbt->frame_count; i++)9 I7 m* N( p/ Q$ U! f6 u6 C
  357.     {
    # O6 I+ B$ w$ O4 t- _0 L
  358.         frame_size = LE_16(&rbt->frame_size_table[i*2]);
    4 k; m# g# a+ k- u& ^
  359.         if (frame_size > max_frame_size); u& {2 _" y' Z% H" c/ c
  360.             max_frame_size = frame_size;
    : Q8 A( v* W2 ^+ Q3 ]7 k
  361.     }
    ( H; }/ M5 n% M8 J3 i& u
  362.     rbt->frame_load_buffer = malloc(max_frame_size);3 ]- c+ G% j* U9 l& l" \  P
  363. , y2 y) V# x. k5 d4 S+ S# G! r0 p% {
  364.     /* transfer the unknown table(s) */' U7 O. G! D  |$ [0 h: A% K* V
  365.     if (fread(unknown_table, UNKNOWN_TABLE_SIZE, 1, inrbt_file) != 1)% c' _5 z5 q' X) ^. w1 ]8 c
  366.     {
    $ l" D& c9 T7 z0 [3 ~5 C: d0 I
  367.         printf("problem reading unknown table\n");
    ) S2 Q! c5 M# |! ]# }
  368.         return 0;# f9 V4 C$ B: v. r) @, ^9 {
  369.     }+ y) ]. B% M, ?& _8 }$ r+ s3 l* y
  370.     if (fwrite(unknown_table, UNKNOWN_TABLE_SIZE, 1, outrbt_file) != 1)9 F! G3 I5 Y. l4 F  C5 Z: z
  371.     {' A7 d* ?7 F: }2 ?/ H% V( m% w: O
  372.         printf("problem writing unknown table\n");
    , V% o  x$ I) K. W& N7 N6 n8 Z  W
  373.         return 0;$ A5 j. U( c: I  h1 w
  374.     }- @* U( c  `- a' f5 F( v2 [& Y
  375. ) }: c) z$ ~7 a7 M; v) u; t
  376.     /* copy over padding */9 ~8 L4 Y  G# m( u7 Z
  377.     padding_size = 0x800 - (ftell(inrbt_file) & 0x7FF);
    ! _6 H0 n+ _/ I0 v  c
  378.     if (padding_size)( d6 S4 \0 o2 W5 d. l: u; q
  379.     {
    * J$ M. `: k8 i: K
  380.         padding = malloc(padding_size);! w. @/ t4 F# |
  381.         if (fread(padding, padding_size, 1, inrbt_file) != 1)
    - R+ A' E! s; j4 z! U+ X
  382.         {
    ! ~* v0 S. {$ _, i  Y
  383.             printf("problem reading padding\n");
    1 k0 i0 H& H7 C0 x9 x
  384.             return 0;
    + p/ B. J0 ]- F7 D
  385.         }1 o; X) C. B5 L. j* j7 m$ h4 ?3 q
  386.         if (fwrite(padding, padding_size, 1, outrbt_file) != 1)
    : k* K, ?3 }% x( D. P& a
  387.         {, B* E- S6 d0 C9 C, t4 D( `
  388.             printf("problem writing padding\n");1 T/ I/ J3 y3 D/ p" `/ e2 P
  389.             return 0;
    0 ^! L; L8 J$ w* z! p+ b6 R' x% \
  390.         }
      ^) K7 d2 e5 ?7 B" n
  391.         free(padding);
    6 P0 M/ d. h+ F6 ]; U' i4 q* t
  392.     }
    6 K8 b( ?& K* Q' ^9 V

  393. 2 L3 b% W2 h0 O, \  r
  394.     return 1;* i* n; s. g) p: m, Z3 M* }4 @+ f
  395. }5 b0 _' r. e% u3 |7 t# l( C
  396. 8 D3 S5 G1 P& R4 _2 m$ @( _
  397. static int get_lzs_back_ref_length(get_bits_context *gb): e5 B( [( J; m' {
  398. {
    1 G  H9 m0 m( U$ Y
  399.     int vlc;
    7 @) y( s3 T' A8 S3 v- N6 G1 x2 q" ?
  400.     int count;& F$ \7 N/ N3 o5 W
  401.     int value;! [8 ^1 D9 Y9 L' E. D9 y
  402. " W  t9 Y* b  D, t3 w/ ^
  403.     vlc = view_bits(gb, VLC_SIZE);- b( I1 A' A5 ]( c$ |$ J
  404.     count = lzs_vlc_table[vlc].count;  A$ a5 ?# ?) u% e6 h! x& z3 `! @
  405.     value = lzs_vlc_table[vlc].value;
    ( W& g* P5 g& K
  406. % K  T5 Q2 A! Y! q( x
  407.     read_bits(gb, count);# m+ Q6 P0 X: y! B- ~
  408.     if (value == 8)
    7 [2 N/ ^7 U: J  f
  409.     {
    ; F7 }% U1 D/ d3 l$ U5 z6 K# Q
  410.         do
    ( S" ?. o& W0 N/ A
  411.         {4 I. w. z3 l5 W/ P+ v! p
  412.             vlc = read_bits(gb, VLC_SIZE);
    % ~0 _+ U  q0 ?! a
  413.             value += vlc;
    9 w; H- N: Q7 G) h
  414.         }# n9 {0 w' M' W. N+ W
  415.         while (vlc == 0xF);
    ( j( s; \3 m$ F4 r  x3 m
  416.     }
    + Z* T& t3 K- H

  417. ; ~( O9 M% L! v: u) a9 |9 ], x  p
  418.     return value;8 \5 z& F6 `3 J" H
  419. }4 {8 G- w5 L$ L
  420. 2 j* P' c: ?- U2 f6 r$ @
  421. static void compress_window(put_bits_context *pb, uint8_t *full_window,
    8 v' |+ ]" o* G; X; B: E
  422.     int full_window_stride,2 ^6 F; v5 s0 m- C
  423.     int window_top, int window_bottom, int window_left, int window_right)
    6 D" s% h0 S) ]' T% m- o
  424. {
    / n' a* a% S( X* r
  425.     int last_pixel;3 P& l- e3 I" q3 `. ~9 x' d: U9 O4 k
  426.     int run_size;# D7 v0 B! |$ t4 i# D3 w7 S! k
  427.     int x;
    & \1 T/ f( w( N% E4 d3 _. H
  428.     int y;
    - F$ q  \3 f6 l' S) m
  429.     int start_index;
      M( J4 |8 X( Z, Z2 T; V4 N
  430.     int end_index;; H9 `1 I$ W9 A/ N# s+ [. Q1 D
  431.     int encode_last_run;
    . ~  n) W4 W6 h/ Q& x) t8 {) [

  432. , a, c' n( r' g; J3 j) ?9 T
  433.     last_pixel = full_window[0];/ N2 g7 W1 n4 q2 u0 e) d3 O
  434.     run_size = 1;; d5 u" Y6 R0 |6 O
  435.     for (y = window_top; y <= window_bottom; y++)# `$ d6 h' ~3 E
  436.     {
    5 X% p/ F9 B3 ]# f! b
  437.         start_index = y * full_window_stride + window_left;
    / A1 I# s  H& Z& H0 O4 A
  438.         if (y == window_top)
    7 P# l; r3 T3 s
  439.             start_index += 1;
    , n- x2 e0 q( o+ s! P& ^3 m' K6 {
  440.         end_index = y * full_window_stride + window_right;
    - r  ]+ p$ \0 v" M' j
  441.         if (y == window_bottom)
    " K1 J. F5 F/ F4 L5 }( v5 A
  442.             encode_last_run = 1;; g: |# G1 Z; }6 K) C3 _
  443.         else
    ' Z2 `9 q  r+ V6 b  ~6 r+ B7 w
  444.             encode_last_run = 0;8 [! J2 d5 r4 f, M( @5 X+ \& s
  445.         for (x = start_index; x < end_index; x++)
    5 b  ]: }8 E" y2 W
  446.         {
    ; Z5 K& t3 @9 M3 z# [/ j7 ^+ Q
  447.             if (!encode_last_run && full_window[x] == last_pixel)# K" e; t& Z; m6 q
  448.                 run_size++;- {1 q. Q: e1 Y  g% ^; Q9 h
  449.             else; [% L+ k' n2 C# C
  450.             {
      G$ ]. o; G6 f" q1 Y: `# H# U5 m
  451.                 if (run_size == 1)+ W" S3 G  _, g" G8 m8 G2 a
  452.                 {! H) c7 _; U! ?4 y6 I* L* A
  453.                     /* encode a 0 bit followed by raw pixel byte */
    $ K. e& t% R+ r4 s7 A
  454.                     put_bits(pb, 0, 1);/ ]" Y/ ^% M* b5 n0 R: J
  455.                     put_bits(pb, last_pixel, 8);
    " L6 Z' R- T" A6 C
  456.                 }
    0 d) S: v# E7 f* c! x+ o! E
  457.                 else if (run_size == 2)5 W8 s+ e4 b* a1 [4 d0 k
  458.                 {/ P3 R1 ~1 a4 x  {; r
  459.                     /* encode a 0 bit followed by raw pixel byte */
    ; u% W0 P+ E, ^% ]6 w( t( q- `
  460.                     put_bits(pb, 0, 1);
    1 x& {# K; U$ I, n
  461.                     put_bits(pb, last_pixel, 8);7 G/ p% W! [0 t7 N2 q6 u, s
  462.                     put_bits(pb, 0, 1);
    ; ?- J& q4 `+ x; Y& N
  463.                     put_bits(pb, last_pixel, 8);
    # v/ z4 w; m) V
  464.                 }
    . W# @7 U' k; V  t$ ~7 f5 V( ]
  465.                 else
    ; p  g& b: W' w2 {
  466.                 {
    " W) x; V3 ]0 L4 a8 T' c
  467.                     /* encode a 0 bit followed by raw pixel byte */
    4 A4 g1 c+ I2 J' w0 I. V: N' e
  468.                     put_bits(pb, 0, 1);2 i6 e' p7 `6 J# l+ M. a6 ^
  469.                     put_bits(pb, last_pixel, 8);
    # M0 o2 X, l' Y6 o$ \& l+ c" e
  470.                     run_size--;7 y% c4 j- o( ^. l( y
  471.                     /* encode a run: a 1 bit, followed by a back reference+ d; ~" u" l$ z9 S. W* z
  472.                      * offset (-1), followed by a length */
    $ z1 ^' ~4 J0 G# K4 |' C0 T2 W5 W
  473.                     put_bits(pb, 1, 1);; l% C, p- E6 t% V
  474.                     put_bits(pb, 1, 1);  /* 1 = 7-bit offset */' `& r" o+ T2 V5 p. G
  475.                     put_bits(pb, 1, 7);. w9 \( o+ |# Q4 `' [' B
  476.                     if (run_size <= 4)- u& _  H/ W( m. A# \( h
  477.                     {1 _* k3 C$ N) D: Y
  478.                         /* lengths 2, 3, and 4 are 2 bits */, [6 _$ F: N! z' s- j
  479.                         put_bits(pb, run_size - 2, 2);
    3 Q+ b/ ]9 d6 d% ]: X; z
  480.                     }
    # N3 }) y- N4 W' w0 K+ q- f4 ]6 ]! P
  481.                     else if (run_size <= 7)$ P; ^8 c9 H5 g0 V
  482.                     {/ G6 l  Z) u+ T& [$ w
  483.                         /* lengths 5, 6, and 7 are 4 bits */1 D- g& K7 l: O5 ^4 a* A
  484.                         put_bits(pb, run_size + 7, 4);
    * W8 E4 n3 x$ _6 Z$ A+ _4 j
  485.                     }
    / D7 k: q1 m4 Q9 R! r9 O
  486.                     else% \+ K$ O3 p: S: P8 k
  487.                     {
    8 `, v' E; k3 m, q8 o
  488.                         /* arbitrary length; start by encoding 0xF which, q1 z- T. C6 E! ~8 S5 ]
  489.                          * stands in for an initial version of 8 */
    + }5 {. q) S. H
  490.                         put_bits(pb, 0xF, 4);
    8 P3 Q0 q) v) d- ~6 T  l( k
  491.                         run_size -= 8;' x6 t; J$ l" P1 `8 Z5 o
  492. 7 M0 s3 f4 V( Z6 C7 ^" ]$ _& v
  493.                         /* encode blocks of 4 bits until run_size is 0 */3 R5 i3 |3 L6 O
  494.                         while (run_size >= 0)5 |2 j% a7 S( ^7 E" b- w
  495.                         {- k6 e6 e4 j- m* B$ i
  496.                             if (run_size >= 15)
    : B. f2 Y% |% S5 O( {* _3 J0 g
  497.                             {( J& a" O$ V  W6 ]) M
  498.                                 put_bits(pb, 0xF, 4);2 H8 y2 j' ^4 x  |0 A% t$ I- N
  499.                                 run_size -= 0xF;
    - T8 g% n5 {7 X' J
  500.                             }- q" M- T6 {# K# {
  501.                             else: o8 S) r2 h% A$ `- B
  502.                             {( W7 M$ L" U- S* L4 V
  503.                                 put_bits(pb, run_size, 4);2 c' n0 w( I% w& Q  e, a: J( d" n% j
  504.                                 run_size = -1;
    + R) C8 b  ^- Y# P( K" t
  505.                             }
    2 w0 e0 H) S, x
  506.                         }/ I4 h" E0 s5 Q; R* L$ |( T/ D" `
  507.                     }  C8 K6 ?0 n" @) p4 I, U7 l: [
  508.                 }
    # j$ \) @6 x; `9 x
  509. - `+ Z4 T7 d& C" i8 o
  510.                 last_pixel = full_window[x];2 |9 Q" N0 I2 d) `. k% |2 l
  511.                 run_size = 1;
    / a; N+ n: {% h# y1 [2 s( ]

  512. 0 t/ t2 t" k5 x2 z) M: U
  513.                 /* this single x iteration was only here to close the final run */
    9 W  y. k1 k6 l9 v9 F5 u5 u% r
  514.                 if (y == window_bottom)  F, s( ]# @2 G: j
  515.                     break;9 U1 R, k- A/ t
  516.             }( z% z1 N4 y! v% D. y+ y- G0 ?  y
  517.         }
    ! g* ^8 w. f8 @6 h
  518.     }2 A/ O$ i7 G' e. d0 u0 |( t# L

  519. ' R( f9 u. Y7 Z% u! I) f, c
  520.     /* close the bitstream by encoding a back reference with length 0 */
    + b7 A+ w0 o! f% }- ^
  521.     put_bits(pb, 1, 1);  /* back reference run */# t' k' }* N) E& T
  522.     put_bits(pb, 1, 1);  /* 1 = 7-bit offset */$ i8 K+ Q4 R0 p) l
  523.     put_bits(pb, 0, 7);  /* length 0 */
    6 c3 J$ S2 G; P) m3 i" w
  524. % e$ r% C6 O3 V" c4 W# x
  525.     put_bits_flush(pb);
    + N. K7 U; ^; _" l9 h, `( ]% F
  526. }
    0 B. H. i* n% U; E

  527. $ z9 A4 T1 ~5 `8 M7 w
  528. /* compute Euclidean distance between an RGB color and the desired target */
    1 ]' L! s2 f4 l4 W7 |
  529. static int compute_rgb_distance(int r1, int r2, int g1, int g2, int b1, int b2)
    7 F  L* ?4 d/ I; L1 ^
  530. {
    $ F5 [: j5 v; ^+ R: O+ K+ t
  531.     return sqrt((r1 - r2) * (r1 - r2) +3 b2 H0 Z  U" Y
  532.                 (g1 - g2) * (g1 - g2) +
    1 |8 {: s: B( f7 J
  533.                 (b1 - b2) * (b1 - b2));
    % `; l/ a; m" b) d5 a/ o( C. O
  534. }* h; ]2 s' E4 Z
  535. & l- C0 N4 J- u  I2 y
  536. static uint8_t find_nearest_color(rbt_dec_context *rbt, int r, int g, int b)
      P$ i3 [8 r; C$ ]7 z+ ~
  537. {8 X4 w7 I# y: ?8 N
  538.     int i;
    & R! D' r: G) r: N% K
  539.     int nearest_distance;
    # ]  n9 @2 k; H; Y2 {- P' z7 v
  540.     int distance;
    : e; E. t9 ?/ `0 m! W( P
  541.     int rp;
    3 E. _5 }( o; V3 D9 t: }' _
  542.     int gp;
    , u) L1 V. D. f1 n# I, y- a: f" f
  543.     int bp;; ^7 |$ L: U, ^& R# a- d0 g4 m4 I4 A
  544.     uint8_t palette_index;7 E$ t) z8 w# y0 H# W, q* t( ^: T

  545. ; y4 V3 j( P! M
  546.     nearest_distance = 999999999;
    2 N% c, P  d* l  R2 F# _+ U
  547.     palette_index = 0;8 ~) Q+ f0 V0 C  A+ f
  548.     for (i = 0; i < 256; i++)
    * t  \4 N8 G! }% c9 r( R
  549.     {3 @6 H, R& {! j* ~1 {* h4 w
  550.         rp = rbt->palette[i * 3 + 0];0 j! x) i+ h& B: X6 r& J
  551.         gp = rbt->palette[i * 3 + 1];  C( O9 c0 J5 R" z) w  p/ G
  552.         bp = rbt->palette[i * 3 + 2];' ?1 f+ T8 @! f3 J% f0 [7 `
  553.         distance = compute_rgb_distance(r, rp, g, gp, b, bp);8 R: C5 R% D7 \( v* W8 z+ r4 M4 j5 d/ m
  554.         if (distance < nearest_distance)
    + U9 L- I* v& P6 ~
  555.         {# j/ O8 C" v* c: _- n* D8 M, L
  556.             nearest_distance = distance;0 l% T6 P, ^: O  S$ W
  557.             palette_index = i;
    + z& V4 o9 O: @) v  b# _7 O9 M
  558.         }# h, C. j5 I# w
  559.         /* can't get closer than 0; break early */3 n: T5 G0 `. ?
  560.         if (distance == 0)5 e0 \+ q$ a9 d6 R# a( O
  561.             break;' u, C0 ~1 c8 T& q2 Y( L
  562.     }; o7 x& v! E/ r4 d" ~" Y6 o
  563. & L* i3 h2 ?/ z4 P$ Y% i
  564.     return palette_index;
    : X6 n  |% F# i
  565. }
    8 r3 l3 g9 t% K  S& D$ W

  566. $ d. Y* C4 [- l8 B( u% O. V5 C
  567. static void subtitle_frame(rbt_dec_context *rbt, uint8_t *frame,4 I0 t- `4 ^9 m6 s
  568.     int width, int height, int timestamp)
    " y, ~/ u: o7 Q# C- r: |" T
  569. {( A* }. ^$ X" z' J8 z+ x9 I
  570.     ASS_Image *subtitles;2 `3 w$ N. U% L0 i5 `
  571.     int detect_change;& s; W2 l& I" R# _, G6 C$ v
  572.     uint8_t subtitle_pixel;& C2 A. B3 u, C- o: @. t/ h$ T' ?
  573.     int x, y;. }& s! @2 y4 s# x
  574.     uint8_t *frame_ptr;( H( ^2 _' D( y2 `
  575.     uint8_t *subtitle_ptr;9 B; S0 u$ C8 P! ^' w& M# V* V

  576. " w% A; {1 Y2 L- E1 x
  577.     /* ask library for the subtitle for this timestamp */; g3 x6 f3 n( F1 y' I
  578.     subtitles = ass_render_frame(rbt->ass_renderer, rbt->ass_track,
    * c* n7 I  B) z' v+ ~5 U
  579.         timestamp, &detect_change);' C, r1 M7 L- t0 u/ U4 l- v
  580.   w8 u6 o7 U: N8 _
  581.     /* render the list of subtitles onto the decoded frame */) \$ b, B% F' n* M5 O. D
  582.     while (subtitles)) n' y* j) r# Q! n* J* z( h
  583.     {9 J$ I' f& j+ B4 y: x# M1 K
  584.         /* palette components are only 6 bits, so shift an extra 2
    , v! K9 h) Q7 V! ?  m$ A
  585.          * bits off each component */
    4 y% Z$ o3 S. f5 Z
  586.         subtitle_pixel = find_nearest_color(rbt,
    8 C# r$ r% y, O2 a8 Q6 ?. x  H- y$ U) w
  587.             (subtitles->color >> 10) & 0xFF,+ O6 L0 b( ]+ I, j
  588.             (subtitles->color >> 18) & 0xFF," d' J" E* [3 t, ?  z" L
  589.             (subtitles->color >> 26) & 0xFF);- P: S9 ~0 k8 `; L9 n2 Z! h- T
  590.         for (y = 0; y < subtitles->h; y++)
    " t2 I' T9 j4 B6 N
  591.         {
    4 b2 ~; e- N" l; y
  592.             subtitle_ptr = &subtitles->bitmap[y * subtitles->stride];
    + K; B" F1 t, v% k$ W
  593.             frame_ptr = &frame[(subtitles->dst_y + y) * width + subtitles->dst_x];
    8 ?( h6 g7 x- J/ u; g7 U) N
  594.             for (x = 0; x < subtitles->w; x++, frame_ptr++, subtitle_ptr++)
    0 z6 |2 R6 u4 A
  595.             {
    4 y( w( y8 l/ `% D, o' F! i, x
  596.                 if (*subtitle_ptr >= SUBTITLE_THRESHOLD)
    8 K0 w8 W- M5 ^% h7 A' G1 v" r
  597.                     *frame_ptr = subtitle_pixel;
    ( k0 h4 ?/ I, X" ?
  598.             }( B3 D  C7 Q( J
  599.         }! a" p& Q- u; _0 ]6 ^% y/ W
  600.         subtitles = subtitles->next;
    + D9 b  u7 c1 l' @5 x6 `
  601.     }+ Z+ u- w/ f( W# U. S, k
  602. }1 b" T/ w) O& B" `/ X! n$ h
  603. 9 |! Z$ d+ x2 f0 f* \
  604. static int copy_frames(rbt_dec_context *rbt, FILE *inrbt_file, FILE *outrbt_file,
    7 \$ [' }5 W( K" P
  605.     int origin_x, int origin_y, int window_width, int window_height)
    # \% `0 h4 E6 @
  606. {( N5 r& t+ m1 N$ }* ?2 x( |) A( c! W
  607.     int i;% d& b6 F: ]0 A# l/ K3 v9 {1 I
  608.     int j;1 B- G, y4 X' u, j6 X, J
  609.     int scale;" C* U: o6 z2 u! D8 }
  610.     int width;5 D6 N9 ^$ L2 e! w- ~1 B
  611.     int height;! u7 v  a" L0 s- b$ E
  612.     int max_width;/ k/ n+ q4 e6 B, `
  613.     int max_height;
    * u  t8 d( Y: t4 R" i
  614.     int frame_x;1 i7 B& O0 i7 [+ T
  615.     int frame_y;
    ( h9 R; o0 G% j% u1 N5 q4 x
  616.     int fragment_count;
    5 \* P; S0 R' v0 d6 r: R, U
  617.     int decoded_size;% h  Z( o/ D0 s3 c# I7 R, W7 e
  618.     uint8_t *decoded_frame;" Z0 i' H/ _- _0 m
  619.     int fragment;
    ; x, ~; d* W/ u. U2 H
  620.     int fragment_compressed_size;9 i) e. U; `% w9 ^0 X& w9 d
  621.     int fragment_decompressed_size;& T* ~+ ]9 V1 N( c
  622.     int compression_type;
    8 ]0 d* V. W+ y/ I. K
  623.     int index;
    - Q. R# R( R; ^; C2 Q3 H* l& w
  624.     int out_index;
    6 v5 A+ j' s) l4 X2 l7 [- ~# [
  625.     get_bits_context gb;
    , @" o/ I# P5 |6 g
  626.     int frame_size;! {& d; h0 f  I( p; R, s( y- s
  627.     int video_frame_size;- Q; b# i1 p4 s9 D# f$ J3 a
  628.     int audio_frame_size;* V2 A/ h% i+ ~& z1 x

  629. / s% A4 D* ?+ r5 a' H
  630.     int back_ref_offset_type;
    3 h6 r& J% ~6 l# I! z
  631.     int back_ref_offset;& u- N4 Z$ \0 U4 t1 t! i
  632.     int back_ref_length;; w: B/ _8 P2 ]5 R" p& @: k# u
  633.     int back_ref_start;' d7 y4 p6 H2 @$ O$ b
  634.     int back_ref_end;; L& ^6 X- N$ E- Y( P& a" u

  635. 9 f5 u; f9 ?; j; E  N
  636.     uint8_t *full_window;; }* X+ G- j. Z8 W! m+ O
  637.     int full_window_size;5 ^; G6 A, t+ ~  d+ F
  638.     int y;
    ( |( `1 b3 R4 Q) w: t6 l! y
  639.     int window_top;0 u# j8 f1 W, M: q3 S- m. v  j+ v
  640.     int window_bottom;8 N) F2 M1 B( J
  641.     int window_left;
    , c2 I3 m" e* N* X  y8 X+ t
  642.     int window_right;6 x+ i; k4 K' d. C# N9 T" Z
  643.     int window_size;: `; O2 ^! T: Y2 Y  L9 R! q1 U
  644. - O, o7 \, E) v" Z% d9 B
  645.     char filename[30];& d8 I. @6 q0 t; F. l; m

  646. ) H# w% l/ s* O$ f; D9 J- n- O3 W, n
  647.     put_bits_context *pb;' j1 X9 F  D7 a4 m2 [/ \" s- N
  648.   S6 f4 s+ c" p: l' e  r: ^
  649.     full_window_size = window_width * window_height;
    7 _% c5 Z% [2 x7 V
  650.     full_window = malloc(full_window_size);
    ! e# B* ^  I% V7 W% J
  651.     pb = init_put_bits();
    5 G1 ^/ z1 e5 _! X- z, `' D

  652. # m& N3 ^8 r; A  B8 w
  653.     max_width = 0;
    : m+ i* |5 K5 l% j6 g
  654.     max_height = 0;. W1 A0 X9 h4 i4 j! e7 ]2 f
  655. $ f& D# _, Y, o2 U. Y
  656.     for (i = 0; i < rbt->frame_count; i++)
    - r! a" c, V0 _  E2 t( `$ t: p
  657.     {
    7 L' k! V$ E4 U5 J
  658.         /* read the entire frame (includes audio and video) */
    5 r1 B' r" a# ]
  659.         frame_size = LE_16(&rbt->frame_size_table[i*2]);
    ) O# q; G& d. k
  660.         video_frame_size = LE_16(&rbt->video_frame_size_table[i*2]);
    ) _0 `6 [+ `7 x, W
  661.         audio_frame_size = frame_size - video_frame_size;; ]8 s( A6 L  Q3 F
  662.         if (fread(rbt->frame_load_buffer, frame_size, 1, inrbt_file) != 1)
    $ Z" r$ a! H! s' a- Q
  663.         {. ]8 N1 J/ M2 ?# d/ {& J$ d; `
  664.             printf("problem reading frame %d\n", i);
    , U7 Q3 N  U5 d1 X
  665.             return 0;
    ! J! F7 H" Y7 L# Y/ D
  666.         }$ }% [& B  Z- i% g: z

  667. 0 ~. S5 _. r* v$ o# q3 \& F" H
  668.         scale = rbt->frame_load_buffer[3];! Q0 _  w8 U( T) k' Y% J1 Y) u
  669.         width = LE_16(&rbt->frame_load_buffer[4]);
    & M3 @4 o2 \  Q: p' Y  f
  670.         if (max_width < width)
    * n/ |" M) j! v1 g" r/ @
  671.             max_width = width;6 ^8 H/ w" ^$ j8 u' u( p& Q) P
  672.         if (max_height < height)) `3 i4 |8 G/ [: e: P
  673.             max_height = height;, h' M/ J* W1 O) ^' L& q6 E& T) a
  674.         height = LE_16(&rbt->frame_load_buffer[6]);) j' B5 t4 c! @4 m% L
  675.         frame_x = LE_16(&rbt->frame_load_buffer[12]);
    - K2 I* b( D4 `7 Z
  676.         frame_y = LE_16(&rbt->frame_load_buffer[14]);1 d: Y" K5 b+ I2 d0 k7 w
  677.         fragment_count = LE_16(&rbt->frame_load_buffer[18]);& b* |) h: }5 |. H
  678.         decoded_size = width * height;( ?4 z& o, [* u) E
  679. ( S/ u8 v% K* S; f7 B- \& ]
  680.         printf("processing frame %d: %d%%, %dx%d, origin @ (%d, %d), %d fragments\n", i, scale, width, height, frame_x, frame_y, fragment_count);+ v1 Y2 T9 l# c1 ?. ^8 _7 ^

  681. 3 L; Q, V, L: d2 U; U6 u/ R
  682.         /* decode the frame */
    ) @% E+ z4 T  ]! w" s. S; c0 e8 V
  683.         decoded_frame = malloc(decoded_size);
    0 [+ K$ G9 H7 s0 @7 M
  684.         index = 24;# @4 f! Y: ~8 v7 w
  685.         out_index = 0;1 j! ?+ O& T. k7 n% w
  686.         for (fragment = 0; fragment < fragment_count; fragment++)
    - C, ]: U/ {/ x- @/ ]  S: ]9 y7 R. z
  687.         {
    ' {2 R3 N1 o- X9 C, v: W" I
  688.             fragment_compressed_size = LE_32(&rbt->frame_load_buffer[index]);
    7 g. Y3 F% h  U0 I
  689.             index += 4;/ f. @& U$ R  f
  690.             fragment_decompressed_size = LE_32(&rbt->frame_load_buffer[index]);
    6 {) K* q& B. d5 u' c  P
  691.             index += 4;# C1 ^: U8 W( |
  692.             compression_type = LE_16(&rbt->frame_load_buffer[index]);- P* H( ]7 H' f
  693.             index += 2;6 w8 E- W+ F" J- J, U

  694. * h8 E3 W* O" {& V* `, J. Y. a
  695.             if (compression_type == 0)( S; s: n: Q8 S) g/ g
  696.             {, `/ n9 o8 x8 s
  697.                 init_get_bits(&gb, &rbt->frame_load_buffer[index],+ ^2 A% K) A& }! y$ v
  698.                     fragment_compressed_size);# O) H: e; h0 ?8 l3 A7 Z* k2 F
  699. 0 I% }; E3 q" z! Z* y
  700.                 while (out_index < fragment_decompressed_size)' v1 D+ X" ]( m3 V9 P) ~7 w
  701.                 {
    # a( J3 H) {; }5 F" l* B
  702.                     if (read_bits(&gb, 1))
    / f8 u4 f+ F! s# J. E( g
  703.                     {6 a, w- I9 }, O- Q/ r/ Y+ w
  704.                         /* decode back reference offset type */1 V1 q6 u- n3 Q7 O. N
  705.                         back_ref_offset_type = read_bits(&gb, 1);+ j4 e, v2 \# k5 K: N6 d, H4 T
  706. & d& m: i$ v2 _( |. m/ X- A
  707.                         /* back reference offset is 7 or 11 bits */4 x( Z) K, m: i4 F9 }7 d+ }
  708.                         back_ref_offset = read_bits(&gb,
    & v8 s' j! E- ^* O4 W
  709.                             (back_ref_offset_type) ? 7 : 11);0 A* x  \. K* ^' t  o5 h

  710. % s/ ]$ ~4 t% p* U: L/ b
  711.                         /* get the length of the back reference */
    / B: e) V* B# Q6 T
  712.                         back_ref_length = get_lzs_back_ref_length(&gb);
    ( Y) H7 k* v* o8 {
  713.                         back_ref_start = out_index - back_ref_offset;
      X9 I" b. S( X# |+ W  [4 u7 c
  714.                         back_ref_end = back_ref_start + back_ref_length;
    ; G7 I5 O: {3 \$ o7 A/ Y
  715. 8 O9 k4 v1 Y' L* J1 b
  716.                         /* copy the back reference, byte by byte */
    " _$ t, M. x3 S0 ?" o$ O
  717.                         for (j = back_ref_start; j < back_ref_end; j++)
    1 p% ?' `0 c1 V9 y
  718.                             decoded_frame[out_index++] = decoded_frame[j];
    . I1 L$ A0 A" B- K
  719.                     }
    6 D) C3 V& m9 j9 q# j) ]# Q( @1 o
  720.                     else3 o1 P! _8 i" j) \0 K' y8 w
  721.                     {
    - W! H1 m8 W7 P4 ~8 U$ J
  722.                         /* read raw pixel byte */+ U7 p8 }! U9 W4 @; i! w/ V
  723.                         decoded_frame[out_index++] = read_bits(&gb, 8) & 0xFF;9 ?2 a1 P7 s! U, ]
  724.                     }3 o9 X1 _5 v# z8 c+ @0 R
  725.                 }* ~  s! g6 \8 T# u: K
  726. % l! C0 v6 r( B1 X7 F
  727.                 delete_get_bits(&gb);
    . B2 c2 g, c5 ?! j! S! u% h# [5 s5 i
  728.             }
    : b" f2 x5 f; e' p& _

  729. / b$ k" u( V2 A
  730.             /* next fragment */
    ; F* _+ L$ }% P/ t# o* ]# M
  731.             index += fragment_compressed_size;
    : ~9 G6 h' H- C, N" [# N
  732.         }
    ; Q+ f( I8 a1 M) H; [$ y% c
  733. 5 s+ d) a$ l4 V/ i( U7 ~( o/ [
  734.         if (rbt->dump_frames)
    5 ^7 w. y: _/ p' `* O1 r
  735.         {
    * G$ N) L& E( g' Y- f+ i
  736.             /* dump the original frame */0 F1 N# h7 N% `: }' R
  737.             sprintf(filename, "original-frame-%03d.pnm", i);  Y4 B5 w, L7 l& b
  738.             dump_pnm_file(filename, rbt, decoded_frame, width, height);, G1 v  `, l! A$ z0 A8 \
  739.         }
    ) b0 W3 \( |+ ~  t2 c7 v
  740. * t* J, U4 W0 A1 S0 S
  741.         /* transfer the image onto the frame window */
    6 U  h) j/ `+ C0 r5 g7 r# V6 f
  742.         memset(full_window, 0xFF, full_window_size);
    + [  R3 h/ g% N1 l5 g/ U& B
  743.         index = 0;, W# g- c2 A: u7 R; K% I
  744.         for (y = 0; y < height; y++)
    , i" S  ]1 b9 `
  745.         {$ H, c. f; M# v6 [* D$ u: R$ k% @
  746.             out_index = window_width * (frame_y + y) + frame_x;$ C( O7 a5 @2 R
  747.             memcpy(&full_window[out_index], &decoded_frame[index], width);. g" }9 n6 [: N: y6 n% S
  748.             index += width;; c: Q8 W7 o  v: \
  749.         }0 Z( ^9 O" N2 x  l' Q) U
  750. / r' S: B/ v/ B! J, o4 A  `- {. `
  751.         /* write the subtitle */1 d- t6 \9 n- g* i) N& G& b) W
  752.         subtitle_frame(rbt, full_window, window_width, window_height,' r% u. I+ `* w. a
  753.             i * MILLISECONDS_PER_FRAME);
    3 Z) r5 H& @4 }8 d& z/ H
  754. 6 Y1 h7 P8 C/ }9 e1 x
  755.         /* figure out the smallest change window */0 }. F, N) O; T
  756.         window_top = frame_y;
    + q9 d/ i- ^9 n% R& X" ?/ p
  757.         window_bottom = window_height;
    4 }# _& |' H! f8 ?$ ?, L+ ], c
  758.         window_left = 0;
    1 d' w9 _3 S& C; L) x( H3 A
  759.         window_right = window_width;
    0 G0 u3 j- w2 k& x0 K+ @5 F
  760.         window_size = (window_right - window_left) * (window_bottom - window_top);
    # z9 I: |5 Q0 V" \
  761. : ~: w" x. z9 w5 L# O
  762.         /* compress the frame */
    6 M+ u  z9 g+ Z. L
  763.         reset_put_bits(pb);
    7 x# v0 H* Y+ W8 e, x, f0 T0 b2 W
  764.         compress_window(pb, full_window, window_width, window_top,, B) w2 K& M1 i, X
  765.             window_bottom, window_left, window_right);8 A9 Z* j* I% A# n

  766. 1 X1 N( G  P- L' P
  767.         if (rbt->dump_frames)% e5 v- J- p% g5 L+ j1 d/ j
  768.         {
    ) H, A' D4 `, M$ i
  769.             /* dump the frame plotted onto the full window prior to encoding,1 i* o9 `. M# p' j1 R. S
  770.              * with subtitle */  m+ Q: K+ d% v
  771.             sprintf(filename, "pre-encoding-frame-%03d.pnm", i);4 I0 d0 _, C7 s5 i
  772.             dump_pnm_file(filename, rbt, full_window, window_width, window_height);
    # a' U/ J% Q" x/ J  ?  S. z+ Z" x
  773.         }5 g5 L" G3 @3 h

  774. - d2 K4 S- {, Y! ]
  775.         free(decoded_frame);
    & x1 G& m, T! E) z8 P: H* J; H% ?: c1 d
  776. 5 ]+ W5 W! P9 P/ H8 h% t( Z
  777.         /* update the frame header */' [- c3 P8 }# g# ^) h* L( B
  778.         /* width */. {$ ]1 _3 x- F, f: J8 d
  779.         rbt->frame_load_buffer[4] = (window_right - window_left) & 0xFF;
    2 i+ l7 |, a5 C6 M2 T1 N& f
  780.         rbt->frame_load_buffer[5] = (window_right - window_left) >> 8;9 D  b7 i7 w. k' ?
  781.         /* height */
    % Z$ f7 K9 f& ^
  782.         rbt->frame_load_buffer[6] = (window_bottom - window_top) & 0xFF;
    2 ~) V; E) j; k$ |" U: E4 P  S" e* s+ v5 b
  783.         rbt->frame_load_buffer[7] = (window_bottom - window_top) >> 8;, ]' L* ]8 T4 p/ n' Z# O! w8 S
  784.         /* origin X */; b2 W  \  F1 b
  785.         rbt->frame_load_buffer[12] = window_left & 0xFF;/ S1 \% t; a6 }. J6 w3 C' q: @
  786.         rbt->frame_load_buffer[13] = window_left >> 8;. G3 a/ u, d+ o: _1 ]# ?$ B
  787.         /* origin Y */
    : D; e: \' f- w6 r, k
  788.         rbt->frame_load_buffer[14] = window_top & 0xFF;
    % m/ V9 l5 V" ~( z
  789.         rbt->frame_load_buffer[15] = window_top >> 8;
    / ~5 @/ Q( C: n& d( {. F
  790.         /* fragment payload size */
    4 k4 O+ R5 a! Z& K$ u
  791.         rbt->frame_load_buffer[16] = (pb->byte_index + 10) & 0xFF;
    ' a6 q5 m) S* [
  792.         rbt->frame_load_buffer[17] = (pb->byte_index + 10) >> 8;
    ; y8 F2 Y* A8 I# N  m  r! X$ Y& m# B
  793.         /* fragment count (1) */
    , f2 a  N( a7 f# s  G$ E4 u. U
  794.         rbt->frame_load_buffer[18] = 1;
    ( W4 C' \( a4 l
  795.         rbt->frame_load_buffer[19] = 0;3 X0 ?" }# @) h; ^* u
  796. / O3 J1 L- O& }
  797.         /* update the fragment header */( E3 W. ?4 h# S) o; I& s# d) e
  798.         /* compressed size */
    ' k  `0 k! X. V
  799.         rbt->frame_load_buffer[24 + 0] = (pb->byte_index >>  0) & 0xFF;
    + P7 P9 T/ w8 l; G: T$ S2 c
  800.         rbt->frame_load_buffer[24 + 1] = (pb->byte_index >>  8) & 0xFF;* _# ~( T3 ?7 H9 M9 }
  801.         rbt->frame_load_buffer[24 + 2] = (pb->byte_index >> 16) & 0xFF;
    $ r2 w% O; b. E. n- T
  802.         rbt->frame_load_buffer[24 + 3] = (pb->byte_index >> 24) & 0xFF;4 l* g1 R& W8 ?( i5 [0 p& n8 Z( p
  803.         /* decompressed size */
    # k2 w0 w$ x0 f
  804.         rbt->frame_load_buffer[24 + 4] = (window_size >>  0) & 0xFF;; Q& Z( F) e# P" ~- _
  805.         rbt->frame_load_buffer[24 + 5] = (window_size >>  8) & 0xFF;+ S3 _4 g  Z/ S: |
  806.         rbt->frame_load_buffer[24 + 6] = (window_size >> 16) & 0xFF;
    * v1 T1 ]* B- G
  807.         rbt->frame_load_buffer[24 + 7] = (window_size >> 24) & 0xFF;
    ; F( ?4 D* b" s: r2 V9 o1 [
  808.         /* compression format 0 *// {# M! }/ E, ]8 o
  809.         rbt->frame_load_buffer[24 + 8] = 0;1 J8 b, V2 s8 }" s; c' N
  810.         rbt->frame_load_buffer[24 + 9] = 0;/ @& K0 l- G, P: H
  811. 4 Q& Z+ P+ x0 e
  812.         /* write the 24-byte frame header and the 10-byte fragment header */
    + M& }5 V: b% c
  813.         if (fwrite(rbt->frame_load_buffer, 24 + 10, 1, outrbt_file) != 1)8 u5 D  Z  v; p9 C
  814.         {( E" |( y$ n5 a+ l2 V5 t2 r4 g; `
  815.             printf("problem writing frame %d\n", i);0 g4 M  e0 g' ]* n( |5 d
  816.             return 0;* O8 V4 {+ U) l# p+ n
  817.         }  ?" u2 \4 B' W' m. }

  818. % ?3 w0 s% Y2 C' H2 A+ }! R
  819.         /* write the new compressed frame data */
    : m' c7 D5 B9 F3 ?% s" s- Y
  820.         if (fwrite(pb->bytes, pb->byte_index, 1, outrbt_file) != 1)
    8 c, R, i8 d' J2 H. |0 t
  821.         {3 \" U, H" i! ^. c, W! _" m
  822.             printf("problem writing frame %d\n", i);
    6 s( m& N5 k  r
  823.             return 0;
    7 [, T7 E: @5 G) O0 n
  824.         }5 v& F- d& _; C

  825. ' l& G" [4 f; I6 |
  826.         /* write the audio data */
    - G; ^5 Q9 G4 s6 }
  827.         if (fwrite(&rbt->frame_load_buffer[video_frame_size], frame_size - video_frame_size, 1, outrbt_file) != 1)
    4 H: i7 l! G& R5 O% G
  828.         {
    ; Z6 ^# a% ?2 _$ ^7 w
  829.             printf("problem writing frame %d\n", i);
    8 [* T8 f- c$ w$ y: A
  830.             return 0;
    + q* t9 L. m4 w3 l5 g6 G
  831.         }! V  J- C" j/ T  Y) s* C

  832. 9 I: L7 ?/ U. \' R
  833.         /* update the table entries */
    2 p- e! J: Q3 T1 F; Y* }# Z
  834.         video_frame_size = pb->byte_index + 24 + 10;) F: d$ v1 |9 g( p+ K5 f
  835.         frame_size = video_frame_size + audio_frame_size;" U$ V- x' u9 v* W9 [
  836.         rbt->frame_size_table[i*2+0] = frame_size & 0xFF;4 Y& b/ p1 U  G2 ^+ N
  837.         rbt->frame_size_table[i*2+1] = frame_size >> 8;" E2 Q, f/ |/ Y! P: }2 ~1 d; [5 G
  838.         rbt->video_frame_size_table[i*2+0] = video_frame_size & 0xFF;  j  l: T7 a/ A6 X' v
  839.         rbt->video_frame_size_table[i*2+1] = video_frame_size >> 8;& W: N4 S6 p3 R& P* v) _' X! v) W; R9 V
  840.     }  l) i6 t+ O8 Y) ~% N
  841. 3 Y; h5 x2 {2 h% R: [  W( t+ y
  842.     printf("maximum dimensions seen are %dx%d\n", max_width, max_height);; U& ~; F# n8 m/ D5 o3 R5 m

  843. % k! T9 d4 R; D  Q) Q
  844.     delete_put_bits(pb);
    % R3 n1 g2 ]8 R  g+ A  s! Q
  845.     free(full_window);3 w* t* N! S. D/ |) ]( C" g# m

  846. # h' X0 R7 J7 ~9 N1 \) ^) _
  847.     return 1;
    # g) A; c9 A. Z8 `+ r! H
  848. }
    ; E1 t& b3 ]6 f

  849. * x* o7 }7 M+ n+ s6 U+ a; q
  850. int main(int argc, char *argv[])
    % C7 |+ j6 i( N, S# {
  851. {
    5 ?+ U: J& n. T% k, d# Y
  852.     char *subtitle_filename;2 l4 l# C2 x# O- I: C! f/ H5 \
  853.     FILE *subtitle_file;( [7 g2 T  z1 X3 i
  854.     char *inrbt_filename;5 o2 D- O1 }2 X( z6 s
  855.     FILE *inrbt_file;
    8 J' z& A2 g) w" i! O1 W$ T8 ~
  856.     char *outrbt_filename;
    - v: m# }" ^. _: J
  857.     FILE *outrbt_file;3 r$ m; m" `; d. G; N! s* D
  858.     rbt_dec_context rbt;
    . m0 H! r* b& }* b( m
  859.     int origin_x;
    0 J4 }  A0 ?) q7 o* ^4 E+ S
  860.     int origin_y;  c) g+ o) I; L& c. U, c
  861.     int window_width;3 s& g) \9 G* a+ h; O" Q7 k
  862.     int window_height;% n; m; t% c  n& B0 L+ t* b+ L0 o

  863. + M- z. h" V. q8 \6 d3 h) ~
  864.     /* testing the bit functions */3 v* ]1 }6 ~: i/ ^
  865. #if 0
    8 ?4 w5 r1 z% k
  866.     int i;! Z% v; o4 V; D4 O& h
  867.     uint8_t bytestream[] = { 0x55, 0xAA, 0x00, 0xAA, 0x55, 0x77, 0xFF, 0x1B, 0x70, 0x8F };8 \$ A- z1 P8 n
  868.     int bytestream_size = 10;
    " A8 b/ t& U+ r
  869.     get_bits_context gb;; }' x9 c+ V# [" q7 q* I
  870.     put_bits_context *pb;
    * b$ y9 m4 @4 `( u2 f- W, T- g) L; x
  871.     int bits;$ U% @" G6 k2 a2 I! _" L
  872. 7 `5 c! B- v' P* p8 k
  873.     init_get_bits(&gb, bytestream, bytestream_size);
    8 c% J  q* m) A" e3 f: K
  874.     pb = init_put_bits();8 W3 j2 @4 L* x9 _

  875. . W( H) O5 L4 i# s& k
  876.     for (i = 1; i <= 12; i++)9 \6 n: _4 y) v5 D7 P6 ~/ C
  877.     {
    ; W% }1 l" A# Y7 o' P
  878.         bits = view_bits(&gb, i);
    7 W; z3 g7 N3 }: I0 H- j- R3 _8 A
  879.         printf("view %d bits: %d\n", i, bits);
    8 }5 e; u  x3 ]* ?4 k
  880.         printf("read %d bits: %d\n", i, read_bits(&gb, i));2 a3 B, U4 G- K0 f  Y
  881.         put_bits(pb, bits, i);
    - B" w" V3 H, {8 v# ~
  882.     }6 w1 \- c! S7 m# p% n9 R
  883.     put_bits_flush(pb);- b$ K6 l/ i. e2 z5 q* I; L& E

  884. - W# X# V1 d3 v5 S2 `% [
  885.     printf("original bytestream:\n");0 ?) X' L0 Y  K
  886.     for (i = 0; i < bytestream_size; i++)
    4 m& ]7 Q  M& N% q
  887.         printf(" %02X", bytestream[i]);$ J  v+ ]5 T% e# c
  888.     printf("\nnewbytestream:\n");- y( ?0 b4 }- A$ E1 u6 [
  889.     for (i = 0; i < pb->byte_index; i++)
    ) e/ X, M+ K6 \/ m
  890.         printf(" %02X", pb->bytes[i]);, m- g5 a* \3 a8 `- a$ x
  891.     printf("\n");  A8 q  }. k% F+ [7 Q, R) Y

  892. ( A& ^" S5 U2 H& f( A
  893.     delete_get_bits(&gb);6 q4 O- u/ Q" W* [/ e
  894.     free(pb);
    ' r/ T  B1 R' F+ a2 I' z
  895. #endif% i& b' @, g! C2 A# `

  896. 9 n4 W4 L( U' t0 j
  897.     /* validate the number of arguments */9 |$ s/ G% r: G# w( k1 g
  898.     if (argc != 8 && argc != 9)
    ; m8 l* I! J3 U" x1 q+ w& J' F
  899.     {
    + n* l" N; l8 H( w9 a1 e
  900.         printf("USAGE: subtitle-rbt <subtitles.ass> <in.rbt> <out.rbt> <origin X> <origin Y> <width> <height> [dump_frames]\n");; u/ i6 W4 v$ g! e, M' x
  901.         return 1;, C# ]) y: M/ W3 ^6 Q  H# S! x
  902.     }* M# [8 U2 {9 T; i
  903.     subtitle_filename = argv[1];5 a, A, H  [( Y/ F
  904.     inrbt_filename = argv[2];) A3 M" u9 m+ Y) Q% \" }
  905.     outrbt_filename = argv[3];
    1 m* E, E3 v* O, m* c) `
  906.     origin_x = atoi(argv[4]);) X. [% c/ X4 n
  907.     origin_y = atoi(argv[5]);
    ( i4 d* Q9 \: o  x! N1 ]7 z* c" L
  908.     window_width = atoi(argv[6]);
    5 f- _0 A) S; D0 V* `' ?2 F
  909.     window_height = atoi(argv[7]);" n* Q9 @! B7 X
  910.     rbt.dump_frames = 0;+ ~/ u5 j9 F: a. }9 Q9 I
  911.     if (argc == 9)  u' T; T/ T! Y9 A2 W: V( B, _
  912.         rbt.dump_frames = 1;! L8 V2 }+ O+ W2 V

  913. * H; a3 }" A3 E6 x) J
  914.     /* verify that the specified input files are valid */) d  p% M2 _8 M9 L$ R8 b
  915.     subtitle_file = fopen(subtitle_filename, "r");
    ' K- B! l, {6 B7 d9 S6 @. ~: |
  916.     if (!subtitle_file)
    8 D  N% x! k4 L# ?: |
  917.     {2 ?3 [8 `, }8 H: J4 E
  918.         perror(subtitle_filename);; y- j4 F- N  `$ `; N
  919.         return 1;
    # `$ ?7 u8 d9 R) O
  920.     }
    * }' S4 A- E4 _% r
  921.     fclose(subtitle_file);
    ) l2 F7 O- l# _3 u1 r- @" }% {* y
  922.     inrbt_file = fopen(inrbt_filename, "rb");: K- @5 b6 h6 d3 j+ T
  923.     if (!inrbt_file)
    , N, x! d6 Y# H8 l. z" n7 ^4 J
  924.     {. V5 {, F+ c$ {. J) l
  925.         perror(inrbt_filename);
    ) E& ^6 w$ {- N5 m* y9 h2 q
  926.         return 1;' k1 B$ F9 e9 }3 _& A+ ^& p; X( i
  927.     }) E6 u1 t2 D. `: U

  928. ' v$ `2 C  S9 Z' Y* q! Z9 `
  929.     /* initialize the subtitle support */
    1 D, v1 {" y+ m' K
  930.     rbt.ass_lib = ass_library_init();$ U) A5 K( O) X: J" H7 Y
  931.     rbt.ass_renderer = ass_renderer_init(rbt.ass_lib);
    / {, |& M  v7 X. s' V* x
  932.     rbt.ass_track = ass_read_file(rbt.ass_lib, subtitle_filename, "UTF-8");/ h. I4 Q8 |/ `4 W+ T& Z
  933.     ass_set_frame_size(rbt.ass_renderer, window_width, window_height);/ K+ x1 y* x" O/ v$ O
  934.     ass_set_fonts(rbt.ass_renderer, NULL, NULL, 1, NULL, 1);( C3 Y6 n( [( R3 |

  935. 7 b; g6 Q- ]. X3 g% Z1 r
  936.     /* open the output file */& s% n9 `( y3 n5 m
  937.     outrbt_file = fopen(outrbt_filename, "wb");! ~5 O  E; A, ?3 R. S, e0 v7 g
  938.     if (!outrbt_file)# T" k# l; `% q/ o  G
  939.     {
    - M- a4 Z8 b1 V1 K2 z4 \+ S
  940.         perror(outrbt_filename);
    . t' y; D' g- j7 d, q, T7 P% A
  941.         return 1;/ R, H* @7 \4 ~% _( _5 h
  942.     }) ^0 u* e. t/ t9 M4 ~6 \
  943. & [7 t- ~  T# @6 y2 t! |3 ?% x  u
  944.     /* transfer header from input to output */5 k- z8 v& G# k& W, B0 I; l
  945.     if (!load_and_copy_rbt_header(&rbt, inrbt_file, outrbt_file)). ~; z( A' b* I! i& u3 A
  946.         return 1;
    & b0 d* c0 E, I, K4 ?# ~
  947. * h5 b: G" G- y
  948.     /* rewrite the frames */
    8 H; n" @' n7 t6 T- A& k' a9 T
  949.     if (!copy_frames(&rbt, inrbt_file, outrbt_file, origin_x, origin_y,( o) @- C6 H! u1 q
  950.         window_width, window_height))
    + W* z* a4 M  _
  951.         return 1;
    ; w; _" M, a2 a3 z
  952. # b$ m8 W& S- Z7 S
  953.     /* write the modified frame size tables back to the file *// S0 }) Y) |5 E; P& m1 E9 t
  954.     fseek(outrbt_file, rbt.video_frame_size_table_offset, SEEK_SET);' c# X. t! C3 S9 b/ Z! }
  955.     fwrite(rbt.video_frame_size_table, rbt.frame_count * sizeof(uint16_t), 1, outrbt_file);% v7 g3 q1 n0 U& U
  956.     fseek(outrbt_file, rbt.frame_size_table_offset, SEEK_SET);
    5 ~2 ]' X( U/ E8 B. |! Q! {$ F# Q
  957.     fwrite(rbt.frame_size_table, rbt.frame_count * sizeof(uint16_t), 1, outrbt_file);8 h; y1 g4 G4 F0 V. O

  958. 2 @) g- l6 F/ U5 T( c
  959.     /* finished with files */
    8 [) j- b2 }6 u; {
  960.     fclose(inrbt_file);: S% K( U2 F' K
  961.     fclose(outrbt_file);, N& u2 N; S6 Z) r! k1 W* Y

  962. : X' V' T/ d7 T1 p$ M: A) J7 d  m
  963.     /* clean up subtitle library */
    & C5 N: q" u( [( k9 X; E
  964.     ass_free_track(rbt.ass_track);0 d$ ?9 _! S& G. n1 Y8 S9 r$ n, c
  965.     ass_renderer_done(rbt.ass_renderer);, }3 f* c3 Y  y9 }
  966.     ass_library_done(rbt.ass_lib);( z/ r9 [' w) M  d: |) ]& e/ p* W/ I
  967. , p  i; M1 h3 e
  968.     /* clean up */
    1 T; Z( ?7 R0 ^* g6 ^# x
  969.     free(rbt.frame_load_buffer);
    5 |  B4 q  n* I) U/ V
  970.     free(rbt.video_frame_size_table);. _- Z6 P6 X( _7 }/ g
  971.     free(rbt.frame_size_table);
    ( g; z/ k1 u: i3 e: @

  972. , v1 b, R$ @9 r! X! Y
  973.     return 0;+ f1 h) e2 W6 @  G  o2 e. i
  974. }
复制代码

2 ?4 N6 y* d% ]% l" h2 t3 }( ~: p; {6 K0 q% @" `

- j& ~3 `) k: `3 Y( [4 `5 q& W) x. r. ~& P/ M
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 很美好很美好 很差劲很差劲
回复

使用道具 举报

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

使用道具 举报

板凳
 楼主| 发表于 2009-11-19 11:38 | 只看该作者
引用第1楼soring123于2009-11-19 11:09发表的  :! [0 A- O& N% M+ F+ w
这游戏有字幕吗?
, r; h8 j2 X" M8 Y
好像没有字幕,我说的是给视频外挂字幕方式的汉化。, V  k+ i/ k0 o- _
就像syberia2汉化版下面那行字一样。
回复 支持 反对

使用道具 举报

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

使用道具 举报

5#
 楼主| 发表于 2009-11-19 17:39 | 只看该作者
引用第3楼soring123于2009-11-19 17:07发表的  :) M3 R2 g) M' E* }
我记得是没字幕的 比较麻烦 都是视频的
1 E1 S9 m" O, `; L$ g) F2 |  |* _
给视频外挂字幕方式汉化也许能行。# D5 F2 n" [1 v2 X3 H1 m# ^
要结合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日,是全球华人共同的冒险解谜类游戏家园。我们致力于提供各类冒险游戏资讯供大家学习交流。本站所有资源均不用于商业用途。

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