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

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

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

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

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

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

本帖最后由 shane007 于 2021-1-2 13:56 编辑 7 E9 U0 t, w$ M  L

; T0 P' x- I$ _; l& h# n最近找到了一些和幽魂系列Phantasmagoria 有关的资料,
9 h; o6 H& K7 i$ A7 L5 j( M, p也许将来可以用于汉化。8 b3 O2 t: H9 ~/ K  Z6 e: r( F
. W( I% Z, p* S; C1 _8 W4 x
和日文版有关的信息
) z, m7 \  M6 u; |1 i5 @3 Uhttp://anthonylarme.tripod.com/phantas/phintgtp.html
6 d" E9 }) g7 a! f' _2 m: F4 L4 R# `0 K8 U
相关工具0 D8 Y7 b) a2 \. u* A
http://anthonylarme.tripod.com/phantas/phcheats.html$ U$ m9 N  ^4 [! K6 I
-----------------------------------------------------------------------) m" R+ e9 h9 U  t- C
2012/1/2  更新  ^: F0 a' t2 |9 Q( h7 R- Q
关于幽魂游戏的字幕0 g# o8 H2 w4 t  ?4 G4 E; l0 n. T
Phantasmagoria subtitles function discovered - ScummVM :: Forums
; k6 o+ @3 t3 P2 n7 O2 ?" e, T2 j; Y
VMD文件
, E1 D. B) F; V2 s7 q9 r( K$ q* USubtitling Sierra VMD Files | Breaking Eggs And Making Omelettes (multimedia.cx)VMD - MultimediaWiki# v, [: u" ]* Y; Z2 g8 r) b
/ p- X% L7 s: f& k$ V! g
字幕$ C% K: ~. H7 ^1 G5 f1 [
Subtitling Sierra RBT Files | Breaking Eggs And Making Omelettes (multimedia.cx)
! F7 r- G8 q, R: s4 h+ F+ d' `5 k" V. v+ l$ x* ?
FFmpeg/subtitle-rbt.c at feature/VMD_encoder · multimediamike/FFmpeg · GitHub
0 v5 h9 x5 a' z+ c1 ^0 e" ]6 J
  1. /*
    . P) i! L. Y# t  v9 O9 y6 \9 o
  2. * subtitle-rbt.c
    ) ^4 s" k7 f% k  Z. h8 L- U
  3. *  by Mike Melanson (mike -at- multimedia.cx)6 r3 v# G; C/ r; H6 w& I& Q
  4. *
    7 V, U- V5 v( S0 M0 k  C2 {
  5. * build with this command:
    3 D" K" m" U" k& s
  6. *   gcc -g -Wall subtitle-rbt.c -o subtitle-rbt -lm -lass
    5 [8 \! X; _& F, |  w: C( c
  7. */
    1 O& C& i" I9 s8 n% h% }. ]$ |

  8. # Z$ h. F  r( }* C. _
  9. #include <inttypes.h>
    , W& c* A3 @  l2 Q3 M; S
  10. #include <math.h>' N0 t! Z% }. N% \
  11. #include <stdio.h>' S! {5 N/ z4 V* Z" |
  12. #include <stdlib.h>8 o  T8 q' y4 V
  13. #include <string.h>
    % f; L1 B- \5 I$ j
  14. 5 `5 C$ j6 D6 ]9 A1 c2 W: {3 e
  15. #include <ass/ass.h># {, z2 P2 f5 d+ f0 o  K$ e

  16. 9 o# A. Z" Y" K; c
  17. #define LE_16(x) ((((uint8_t*)(x))[1] <<  8) | ((uint8_t*)(x))[0])
    * P1 P( C% {0 A& T  D( b

  18. 7 ^* Y' n# B2 z: h" p
  19. #define LE_32(x) (((uint32_t)(((uint8_t*)(x))[3]) << 24) |  \' D$ S5 T! J7 q$ Q+ H8 k
  20.                              (((uint8_t*)(x))[2]  << 16) |  \; s, I" E6 I$ b' E
  21.                              (((uint8_t*)(x))[1]  <<  8) |  \9 W5 G+ t) J/ |( B0 n
  22.                               ((uint8_t*)(x))[0])" F, X" W1 y! g' n4 T
  23. ( w* |/ w% E7 R$ \8 B
  24. /*********************************************************************/, _2 R5 M  j' [, p

  25. " v( x1 N7 p7 W) |
  26. /* Bit reader stuff *// k4 Y7 i' y1 E) k! \

  27. # c: O% A9 j& k$ G
  28. typedef struct0 u* z% ~2 r0 |7 U+ v; W
  29. {2 V, U3 y3 h* k, O
  30.     uint8_t *bytestream;
    4 Z) O: V! v# D' D; X0 V
  31.     int bytestream_size;; ?( P' c/ e# N7 O& y
  32.     int index;
    1 H( M- L# W! L  w* B* \. I
  33.     uint32_t bits;
    2 @/ P. E$ s6 K; v# e" Y3 P
  34.     int bits_in_buffer;& P: l1 h: Z7 N5 N$ j
  35. } get_bits_context;
    ! N, w7 Z! s; \3 k

  36. % W" S- [2 Y$ }6 k9 ^6 U# H
  37. static inline void reload_bits(get_bits_context *gb)" @9 M) ^5 X6 o) {! O" K5 ]5 U
  38. {
    " c/ V8 }7 ~+ a8 s' N: y, w* E" d  y
  39.     while (gb->bits_in_buffer <= 24)
    0 h6 Z6 A  S* z, n! J3 J: a  c
  40.     {
    + D' \' \0 Y" t  w) D$ j
  41.         if (gb->index < gb->bytestream_size)/ P, x4 c* t- ^, `; g$ O+ {# z
  42.             gb->bits |= (gb->bytestream[gb->index++] << (24 - gb->bits_in_buffer));
    8 N; y. ~' z. ]. C
  43.         gb->bits_in_buffer += 8;
    9 D0 {. }+ s4 D. X- x9 o/ X- y
  44.     }9 A3 i, n4 z2 ~) Q
  45. }% O- b9 c3 d1 S' s

  46. 4 ~$ x9 N% C1 S0 s9 S2 m
  47. static void init_get_bits(get_bits_context *gb, uint8_t *bytestream, int size)) J9 z  M. \$ `+ b6 B9 R2 X
  48. {4 q; b0 t, ~4 B! O
  49.     gb->bytestream = malloc(size);
    + w4 l: a; ?8 J! B$ ?
  50.     memcpy(gb->bytestream, bytestream, size);- t, ?0 H# J) C1 Q. ?# ^8 E% R
  51.     gb->bytestream_size = size;
    - X+ V+ m0 {, D6 S& a8 i
  52.     gb->index = 0;$ n- l) ^) H1 H' |6 h9 D
  53.     gb->bits = 0;! t( ^) ]+ e" N- H4 S% [
  54.     gb->bits_in_buffer = 0;2 I* y# r5 N: V$ r1 o+ ]' i

  55. 6 L& R6 P1 n2 W0 Y" w# q7 ?
  56.     reload_bits(gb);
    ; E- Q5 a' E. k9 V
  57. }# m0 N( Y* g# r0 \( T! q2 L( _
  58. 7 f$ y5 ^7 o5 Y0 j. J
  59. /* read bits without consuming them from the stream */
    " |" T& g. K) L( r' j
  60. static int view_bits(get_bits_context *gb, int count). @/ P) `% c0 `- n: a6 `5 f" u
  61. {
    + e3 q/ S. B+ P7 {8 z" B
  62.     if (count >= 24)9 Z( G4 t6 I# K# H+ i5 q( L
  63.         return -1;& M) D( Z9 H- v$ ?5 Y0 A1 t1 ?
  64.     if (gb->bits_in_buffer < count)' [2 O' c- J) |4 y# y
  65.         reload_bits(gb);
    1 V6 Z7 g7 h* D
  66.     return (gb->bits >> (32 - count));
    - y: d, e4 |# ?! R
  67. }
    5 O9 K" D- D, D$ W" ^# O
  68. 4 w1 @1 @4 c+ \
  69. /* read and consume bits from the stream */
    - W" j. }1 X! A; T, t
  70. static int read_bits(get_bits_context *gb, int count)5 M% P) [6 O3 o' x! j; u# h: w6 V
  71. {
    & o# [7 S( l, O: s0 N) w7 }7 ]
  72.     int value;$ L4 l" m; Z" h9 Z
  73. 8 r" p/ f5 N& @$ E
  74.     if (count >= 24). a! g. `: A0 c3 f1 p
  75.         return -1;8 B" t5 W( o, p" n, s$ z

  76. 9 x8 J+ o: x0 ]% b& e1 S
  77.     value = view_bits(gb, count);
    8 O$ C8 P& w6 |
  78.     gb->bits <<= count;0 \: t, ]( k* B+ [
  79.     gb->bits_in_buffer -= count;8 n- @$ q! a8 F$ q

  80. 8 ?* ^1 u1 ^  o  X, r+ U
  81.     return value;( A( r! d: n. \" e0 O7 r
  82. }
    5 ^$ ?* h* x) g6 \6 S
  83. 3 Z, }2 s7 ^  z: j/ N
  84. static void delete_get_bits(get_bits_context *gb)
    " V9 {2 u& f+ w8 N0 \/ x1 Y
  85. {
    # d% A- A8 S% t- J7 [. ?
  86.     free(gb->bytestream);
    1 y- q, p& {- T( A! n
  87. }
    & Y9 u9 e: x& k
  88. , Y# y% i6 e) `( O! G# L
  89. /*********************************************************************/
    " C" o8 w% u+ r3 A
  90. ; f/ Z& ]( T6 X6 `9 P
  91. /* Bit writer stuff */
    # \' J5 z4 V# O; H1 z0 F  v$ h+ k
  92. ( k% a0 ]: R& M5 a
  93. #define MAX_PUT_BITS_BYTES 63000, ]; `2 D6 M) {/ o* q' r
  94. typedef struct4 D. Y% e- T& J2 I* s
  95. {
    0 N4 a1 }+ E" {, Y- c0 ~
  96.     uint8_t bytes[MAX_PUT_BITS_BYTES];9 S$ w. g- a, T; V- F. Z3 n; g
  97.     int byte_index;2 X2 o! s5 c0 ?! z) t! D+ v
  98.     uint32_t bit_buffer;; q: t8 U6 z; ~+ b) O. P  H4 @
  99.     int bits_buffered;9 n; z! R8 P4 S+ R% P# S
  100. } put_bits_context;$ w0 Z$ Z6 R0 o
  101. ) _/ |! `) `; ?- z' @  m8 V
  102. static void reset_put_bits(put_bits_context *pb)
    . q8 Q+ i3 d' z, v+ r1 R$ k
  103. {. o( \9 ~; d0 w# U
  104.     memset(pb->bytes, 0, MAX_PUT_BITS_BYTES);* P; g; R7 P$ P4 v2 P) e
  105.     pb->byte_index = 0;
    1 L7 X; E' f& h2 B2 ~0 {
  106.     pb->bit_buffer = 0;
    9 @( z  [9 M% ]" b1 j
  107.     pb->bits_buffered = 0;
      }" J7 j, d+ a% ]6 }
  108. }
    , {, o7 M0 b/ L# a* x/ H0 @) V' f
  109. 3 P# R! C+ B8 x- N) P$ \
  110. static put_bits_context *init_put_bits()3 L# A3 k  T6 S; H. F& g2 p
  111. {! d' M* M) L; {3 R' @- M8 M4 `
  112.     put_bits_context *pb;1 z$ N  Z3 U, p5 A! r
  113. 5 x) w7 \3 h/ C4 h
  114.     pb = malloc(sizeof(put_bits_context));
    1 \" J( i6 W) I$ Q- O
  115.     reset_put_bits(pb);, X* Q8 u) R0 i9 w! ]6 ^

  116. 8 T( u) C8 l" m2 O% y
  117.     return pb;
    ( `) S) G* s5 D0 \$ I+ B
  118. }
    ' O+ q$ ]0 I. S+ L& c" ^

  119. / g4 H4 u. f+ |) e! [
  120. static void put_bits(put_bits_context *pb, int bits, int count)
    ( X( C* l4 M" K6 W) e% J7 ]1 ^# @
  121. {, {! I( y. U7 w/ ]
  122.     pb->bit_buffer <<= count;3 P1 x1 V: ?3 u; H/ R  [
  123.     pb->bit_buffer |= (bits & (~(0xFFFFFFFF << count)));) V( G  _  d, r# h( M+ V
  124.     pb->bits_buffered += count;
    " d% [5 @& m- N8 C- a! G* V

  125. " l1 Z' R/ o8 w
  126.     while (pb->bits_buffered >= 8)
    5 Z( E- x% l- r  y
  127.     {& }0 }" z8 ?- ?9 L/ }
  128.         pb->bytes[pb->byte_index++] = pb->bit_buffer >> (pb->bits_buffered - 8);. u# D0 Q) S7 _
  129.         pb->bit_buffer &= (~(0xFFFFFFFF << (pb->bits_buffered - 8)));) g6 b8 ~8 ]4 S
  130.         pb->bits_buffered -= 8;
    & [6 h9 b" f0 @" J, x
  131.     }
    ; Z9 {" P; N$ [4 U+ A+ N* L9 q
  132. 5 w9 d; C5 _( P3 {
  133.     if (pb->byte_index >= MAX_PUT_BITS_BYTES)% y$ T! n( w" H
  134.     {7 ^& d0 S' g: p9 e  c
  135.         printf("HELP! Bit overflow\n");
    4 O. w( ^7 @- V
  136.         exit(1);3 D- @/ z0 Z& G  a% s
  137.     }+ N/ @& k5 A  i% I9 |
  138. }( Q) q  \2 A1 ^9 N/ O5 \9 c
  139. - s2 d, W# _+ u. e1 t% T- [
  140. static void put_bits_flush(put_bits_context *pb)
    + @8 q, m5 r6 o) M! S( d
  141. {2 f: o) ?8 \' P
  142.     if (pb->bits_buffered > 0)9 j- Z( \9 F2 @" v/ ^6 U
  143.         pb->bytes[pb->byte_index++] = pb->bit_buffer << (8 - pb->bits_buffered);
    0 A" K8 C/ v0 i1 Z
  144. }
    4 Y5 M+ p$ a8 U7 M' r5 p/ f% g
  145. ' Z; ?% o4 W, W
  146. static void delete_put_bits(put_bits_context *pb)- Z) B  j; ]8 u. @: ]; Z+ N5 n7 u
  147. {
    0 I( T) b4 S0 Q" D1 ~& e+ P2 [
  148.     free(pb->bytes);
    7 r3 m" ~4 }6 ]/ |2 \' A. ]
  149. }8 J. A% S: z4 i

  150. ! l5 Y& e7 F0 X2 c
  151. /*********************************************************************/& X- m2 I" Z7 \' Z6 h' H# Z% p
  152. 5 X9 y7 u' E( r- [2 I
  153. /* RBT functions */& y* f7 Y8 b# `, I  i" a: j. M
  154. # c3 `2 v4 v8 M$ L! S
  155. #define PALETTE_COUNT 256
    $ N+ T: `* E  }+ i! M0 h
  156. #define RBT_HEADER_SIZE 609 N8 p7 \4 \' V
  157. #define UNKNOWN_TABLE_SIZE (1024+512)5 ^- w' ~/ O) X9 K& Y
  158. #define SUBTITLE_THRESHOLD 0x70
    + h8 Q% M* N1 q3 O/ B) Y
  159. #define MILLISECONDS_PER_FRAME 100
      y; L* S4 j. ~
  160. : j: }; V! }+ A- E( \
  161. /* VLC table */* o7 @! e) e" L% ]9 e% D
  162. #define VLC_SIZE 42 {' R- e9 ]* L$ u( G  {8 I
  163. static struct
    1 d7 l: @, r! x% U4 y$ Z) I  i0 b, R# ]8 Q
  164. {
    - I0 \- U) N+ X3 k3 Z
  165.     int count;
    & O/ ~9 S% M6 s$ Y3 S/ h% n
  166.     int value;
    " D+ q) d( h8 O7 D# w7 D5 q
  167. } lzs_vlc_table[] =
    6 C" S) ]' i1 W/ J, Y
  168. {
    , `( W. @7 D+ ~9 n' c( ]7 W; w  T
  169.     /* code length = 2 bits; value = 2 */; p+ u3 Q4 `  X1 ~) R
  170.     /* 0000 */ { 2, 2 },
    ' U/ o1 S( S  o  x  e$ T8 f) W7 s; s
  171.     /* 0001 */ { 2, 2 },
    & O- i* }$ e6 B/ T. d) `! j, e
  172.     /* 0010 */ { 2, 2 },
    3 j9 t& z4 N' r7 y! X5 X& O, G' j
  173.     /* 0011 */ { 2, 2 },
    8 g& O# M$ Z: j

  174. / B  g- K" i& m" U/ y
  175.     /* code length = 2 bits; value = 3 */" C0 g6 N! c2 V% o/ A' s
  176.     /* 0100 */ { 2, 3 },
    5 ], C2 M, [- h. a0 H  Z
  177.     /* 0101 */ { 2, 3 },3 q2 `6 Y$ o* B: y
  178.     /* 0110 */ { 2, 3 },6 r+ O/ B% K5 j* n
  179.     /* 0111 */ { 2, 3 },
    % I  Q7 h' j1 P* {/ P: u4 c

  180. . |. n6 G; a  s+ q
  181.     /* code length = 2 bits; value = 4 */
    ; s$ H. a8 i, y: f' h
  182.     /* 1000 */ { 2, 4 },/ ^4 U5 f" w! D+ r6 @' o* s* q4 L
  183.     /* 1001 */ { 2, 4 },1 H2 ]8 T$ }. Z4 S/ J
  184.     /* 1010 */ { 2, 4 },
    / ~$ Z. S& S' N( L
  185.     /* 1011 */ { 2, 4 },
    0 T3 _& ]# g; ~/ O/ Z

  186. * k8 @5 V$ h  N- v" L
  187.     /* code length = 4 bits; value = 5 */
    9 n- K! }9 Q! D' f( ^
  188.     /* 1100 */ { 4, 5 },
    % A9 V+ _/ J+ U3 X) e/ D
  189. ! ?& d4 t8 o* I% M7 k; k% \* N
  190.     /* code length = 4 bits; value = 6 */
    - g) M3 N$ z& u
  191.     /* 1101 */ { 4, 6 },* F+ ^6 O, w+ o( h, B1 g  V. S
  192. & h( S0 Z+ q, k( P2 z5 x
  193.     /* code length = 4 bits; value = 7 */
    9 Q  p# A. g8 X! P( d' J( @
  194.     /* 1110 */ { 4, 7 },
    3 W4 _1 v8 @  r2 C- e
  195. - c7 n" N; e) ~( }8 p2 Y$ \0 g
  196.     /* special case */
    * C  H2 u/ B! T. e4 R
  197.     /* 1111 */ { 4, 8 }* D# b7 r5 A" |! B& |: G
  198. };
    7 _0 c! Q  Q; f% h$ |1 J

  199. : x4 S% m* g5 k0 Y- E3 F0 ?6 o
  200. typedef struct
    7 N4 j. Y3 E4 x& i" C1 P
  201. {
    - S" ]% {: q% Z7 d7 `
  202.     int version;3 _) B. Y: T: j( ]$ o9 O
  203.     int width;3 F7 t9 J7 {7 V8 R) ~* D
  204.     int height;
    $ Y, U1 n3 Y: o7 ^( Z
  205.     int frame_count;
    9 P" g6 S# P) ]6 U1 `) P
  206.     int audio_chunk_size;
    ( G- n, A, R) G
  207.     uint8_t palette[PALETTE_COUNT * 3];
    / n; g+ {* N" ~$ @" f; J
  208.     off_t video_frame_size_table_offset;
    . j' u: W; H% ]
  209.     uint8_t *video_frame_size_table;) e+ g: }! U, o
  210.     off_t frame_size_table_offset;
    + ?% l4 Q0 S8 s. u8 ]( a: P
  211.     uint8_t *frame_size_table;
    & @/ M6 I0 u6 R& y/ {
  212.     uint8_t *frame_load_buffer;
    , L: k1 Z" y+ C; @
  213.     int dump_frames;
    2 t2 d8 ?/ ?; l

  214. + c5 i+ I8 u/ q
  215.     /* subtitle library */+ x. d0 z& V( m3 P" k; j" {
  216.     ASS_Library *ass_lib;0 ]9 m6 P$ ?! B& F- i  g# S
  217.     ASS_Renderer *ass_renderer;) o" A& w4 d, g: n2 t
  218.     ASS_Track *ass_track;
      k9 u* `! s' H! e
  219. } rbt_dec_context;. c$ g$ C  n$ H5 m- E7 `3 _; `
  220. $ o8 U, g: x; M0 q
  221. static void dump_pnm_file(char *filename, rbt_dec_context *rbt,- j8 t4 p* [" B' \% d1 P
  222.     uint8_t *image, int width, int height)5 e8 P: J  E' c% Q( C
  223. {9 `; A8 o6 G2 J5 d& u/ F9 @2 e* e9 p
  224.     FILE *outfile;
    1 Q8 t% X& h/ S3 @+ F1 w
  225.     uint8_t bytes[3];& k9 `2 e& e6 [2 R; A( H" Q
  226.     int p;
    . ]" \" S) ^, o
  227.     uint8_t pixel;
    ; m9 G2 v# s4 h) `8 T* z& V2 d

  228. ) @; j9 H3 v$ }4 ^
  229.     outfile = fopen(filename, "wb");* A' |: c( ^: H; `& f/ f" S2 S
  230.     fprintf(outfile, "P6\n%d %d\n255\n", width, height);/ T& H( b# n4 G. h2 e
  231.     for (p = 0; p < width * height; p++); k- R4 H& _9 J% X
  232.     {
    - r- C& k- x4 k# s8 U( h7 S) ^
  233.         pixel = image[p];
    4 S7 C, j  W( H9 o0 A
  234.         bytes[0] = rbt->palette[pixel*3+0];* ?# V8 Q; |+ Z7 C
  235.         bytes[1] = rbt->palette[pixel*3+1];$ q5 N; M- h/ |/ B; x' ~5 d
  236.         bytes[2] = rbt->palette[pixel*3+2];
    2 `0 d; S% q$ z- D0 E
  237.         fwrite(bytes, 3, 1, outfile);- B) y+ l: \2 n, U3 H5 v( [2 N' f% O
  238.     }
    2 Z* [3 f4 G6 m+ f
  239.     fclose(outfile);- G: ?3 c/ }- w
  240. }
    % `+ i, o' k& f# x2 A

  241. 8 S; ~. z, }" g7 @# q* D% w
  242. static int load_and_copy_rbt_header(rbt_dec_context *rbt, FILE *inrbt_file, FILE *outrbt_file)
    2 g+ Q& l6 \! r8 I* x8 `
  243. {. `& i% w/ M9 D0 n; s( A
  244.     uint8_t header[RBT_HEADER_SIZE];
    $ }0 n$ i% ?( W0 \5 [7 A
  245.     int palette_data_size;
    : ?$ j$ a7 u9 u3 L" G, H2 {  f
  246.     uint8_t *palette_chunk;
    7 |5 ~; @6 i5 k% Q0 c
  247.     int unknown_chunk_size;
    9 r0 P6 Q8 y/ y$ {/ Z6 ~2 g
  248.     uint8_t *unknown_chunk;! I$ f8 Y/ o# ?; w! B
  249.     uint8_t unknown_table[UNKNOWN_TABLE_SIZE];
    . e$ n& Z4 W4 ]6 y, M+ K, D0 K" F
  250.     off_t padding_size;0 A8 s5 Y: b% p  S, i
  251.     uint8_t *padding;
    ! S8 ~" J6 E, i6 x+ N
  252.     int i;
    ( _. }# v$ Y" h5 K. k8 H
  253.     int frame_size;
    0 G7 i0 N' h" X) v
  254.     int max_frame_size;$ v2 ?1 v0 g7 G* d
  255.     int first_palette_index;$ {* c7 o' e. i% Z' d" j/ S
  256.     int palette_count;
      t: v& D$ j1 X: b3 a7 u
  257.     int palette_type;
    ) r( b- n! r! G. }% m
  258.     int palette_index;7 O5 d( }* S* i) Z
  259. / p1 ~6 z% ?6 o8 ?" C
  260.     fseek(inrbt_file, 0, SEEK_SET);& T, Z# {6 l  q* r4 _* Y
  261.     fseek(outrbt_file, 0, SEEK_SET);% N" P/ j" s  T) m& |, B; Z, M
  262. ! _3 p" s; z9 l' A2 Y, F
  263.     /* load the header */
    : S* b; N" D" s; E/ m0 f
  264.     if (fread(header, RBT_HEADER_SIZE, 1, inrbt_file) != 1); h" q! D( a2 g9 _6 W5 u' d
  265.     {
    * y- M+ E8 U% f2 s- q6 i; \
  266.         printf("problem reading initial RBT header\n");8 D( [& d0 s2 t3 _# m5 g
  267.         return 0;3 U/ `* a- V0 j* a
  268.     }3 J$ k" P+ \1 e2 S, o5 p9 L* f' X

  269. . z, i: X. Z! Q9 r, I8 K
  270.     /* copy header to the output */+ U2 y9 s* I# D8 A/ @/ ~0 S
  271.     if (fwrite(header, RBT_HEADER_SIZE, 1, outrbt_file) != 1)
    + S) L7 c1 N- \9 r# K1 N/ ?
  272.     {
    ! T- S0 M6 n, ]% A8 m
  273.         printf("problem writing initial RBT header\n");8 a: ]1 i9 h0 T3 F  C
  274.         return 0;
    - J2 E4 q! o  @$ B9 ]. i  n0 n
  275.     }8 q! S/ b* e" N) C8 G+ F8 @

  276. 5 G: W2 _9 z7 \  h
  277.     rbt->version = LE_16(&header[6]);
    5 Y% B4 ~7 `9 k% p2 \2 {1 a
  278.     rbt->audio_chunk_size = LE_16(&header[8]);
    # z# |5 C, ?) D1 H2 |' j3 f
  279.     rbt->frame_count = LE_16(&header[14]);
    ) ~, X- P* s% k8 `# c
  280. 2 b$ b8 T1 `, P" x, I
  281.     /* transfer the unknown data, if it's there */# }" v3 B* \/ u& X( T) _% i
  282.     unknown_chunk_size = LE_16(&header[18]);  Q  R3 Y5 k' u* v2 [2 c
  283.     if (unknown_chunk_size > 0)/ J' ]8 f/ k1 l) o# _. H6 t: L. \
  284.     {# m  b$ r" n7 ?
  285.         unknown_chunk = malloc(unknown_chunk_size);
    , ^7 d" J5 k" e8 `4 C  P, O
  286.         if (fread(unknown_chunk, unknown_chunk_size, 1, inrbt_file) != 1)
    : q9 h1 q, ^- q  d5 m: b+ e# S
  287.         {
    : M  g2 N# Y& h$ J  S' j
  288.             printf("problem reading unknown data\n");
    3 P( B7 y6 _; Q; d2 _0 q9 R
  289.             return 0;
    * c5 d( u; O! ]
  290.         }
    $ e) z# Q9 Z, W' L
  291.         if (fwrite(unknown_chunk, unknown_chunk_size, 1, outrbt_file) != 1): ?1 ?& B7 H4 z0 x& i8 H
  292.         {9 ~' W; s) ?4 H
  293.             printf("problem writing unknown data\n");
      \3 F6 Y7 i* j5 o8 U/ o" s1 G
  294.             return 0;
    - v/ `! g$ v; T4 d$ D# U
  295.         }
    ; p" a4 n5 g; {7 Q
  296.         free(unknown_chunk);8 j2 u0 L" x: X* X) h
  297.     }9 E' Z) a& f; l5 q

  298. / I6 W4 ?( b% Q' K
  299.     /* transfer the palette chunk */2 k0 N9 f/ K4 `9 I8 F+ F1 g
  300.     palette_data_size = LE_16(&header[16]);
    - d5 D! v0 y( h+ V- F% @
  301.     palette_chunk = malloc(palette_data_size);3 b* r! R2 c* [7 r7 Z
  302.     if (fread(palette_chunk, palette_data_size, 1, inrbt_file) != 1)
    & d, Z3 i& N0 e9 N
  303.     {1 e' U0 q  t8 E5 w
  304.         printf("problem reading palette\n");
    3 \9 Q2 K; P' H2 o$ `  z0 Q! J" H" A
  305.         return 0;" c/ f" e: V" s  r
  306.     }
    / ]+ d, U* F) `* @
  307.     if (fwrite(palette_chunk, palette_data_size, 1, outrbt_file) != 1)
    4 U: H0 P% T+ a0 \
  308.     {, g6 o6 z1 r5 A0 r' y+ i/ Z9 d
  309.         printf("problem writing palette\n");
    , K( ?+ A. K- f. q9 J& }
  310.         return 0;* v, Z' }$ z3 D4 ~
  311.     }# M0 {6 z& n# l: J8 X& r/ Y
  312.     /* load the palette into the internal context */- i" z" |( m/ c0 h; g2 ?6 T: G& ~
  313.     memset(rbt->palette, 0, PALETTE_COUNT * 3);
    9 `1 B$ P# l# n0 y  r% G1 D% b
  314.     first_palette_index = palette_chunk[25];
      F5 g# C- O( S8 _; H
  315.     palette_count = LE_16(&palette_chunk[29]);
    5 K. F0 j, [7 u4 r; b3 d/ Q, h
  316.     palette_type = palette_chunk[32];2 S3 }( l( h! _3 E
  317.     palette_index = (palette_type == 0) ? 38 : 37;: o0 G0 x! P9 [% t5 d! j2 C* E
  318.     for (i = first_palette_index; i < first_palette_index + palette_count; i++); n: {" K% @% j0 \
  319.     {
    & X7 Y  n% t1 v, d: t! ~8 E
  320.         rbt->palette[i*3+0] = palette_chunk[palette_index++];
    " f; |- L  W. V
  321.         rbt->palette[i*3+1] = palette_chunk[palette_index++];3 e& f! y+ n' t$ @% q
  322.         rbt->palette[i*3+2] = palette_chunk[palette_index++];  m! f- K4 R! r* @
  323.     }
    2 w: C7 c% M, o* g& {
  324.     free(palette_chunk);
    1 r8 D& v- Y3 `/ v5 q
  325. 9 `, r0 T/ e$ E0 [2 F+ r
  326.     /* copy the video frame size table (2 bytes per frame), as a placeholder */
    ) J$ s1 X( c1 p& U3 g& n
  327.     rbt->video_frame_size_table = malloc(rbt->frame_count * sizeof(uint16_t));0 m  @  z0 v9 f" K' A
  328.     if (fread(rbt->video_frame_size_table, rbt->frame_count * sizeof(uint16_t), 1, inrbt_file) != 1)
    % Z% w. `6 J& T
  329.     {* m1 k: r- h1 b9 q
  330.         printf("problem reading frame table\n");
    & A2 n" }9 [& E) [% c  M, R
  331.         return 0;. p9 E; o' B8 m7 p  Z3 l* e& Z
  332.     }3 Z0 M7 Q, [0 x' j* V: S
  333.     rbt->video_frame_size_table_offset = ftell(outrbt_file);9 g- @, C5 I' w* F* q0 ^
  334.     if (fwrite(rbt->video_frame_size_table, rbt->frame_count * sizeof(uint16_t), 1, outrbt_file) != 1)/ I9 c/ C& |7 G
  335.     {
    ; w# Q. s* f5 r9 s5 U
  336.         printf("problem writing frame table\n");
    3 r3 @! @5 ^! l+ F" _1 n
  337.         return 0;
    % e* d. C% `' D0 T2 F6 D5 l4 c: H
  338.     }
    ; Q7 \- n+ v. z& q

  339. % U' h  W) A) \% A; U$ }8 {
  340.     /* copy the frame size table (2 bytes per frame), as a placeholder */' h, H# t7 I/ {
  341.     rbt->frame_size_table = malloc(rbt->frame_count * sizeof(uint16_t));
    " o& V4 \$ J9 ]8 P
  342.     if (fread(rbt->frame_size_table, rbt->frame_count * sizeof(uint16_t), 1, inrbt_file) != 1)$ ~, E) w4 ?. J
  343.     {
    , c  B: ^% t5 @9 d
  344.         printf("problem reading frame table\n");4 n! J! v& L0 D* K! h1 O2 N: {3 H
  345.         return 0;
    / k0 I# S' X+ Y! s+ x$ o% i/ m
  346.     }
    - T8 h, g8 X, |/ y$ E1 f
  347.     rbt->frame_size_table_offset = ftell(outrbt_file);
    $ i# U% t0 a, O- W/ }: P0 `
  348.     if (fwrite(rbt->frame_size_table, rbt->frame_count * sizeof(uint16_t), 1, outrbt_file) != 1)
    $ n3 ~+ _2 ^9 T; H5 k
  349.     {( j& w0 a) ?/ Q0 y
  350.         printf("problem writing frame table\n");
    - _  E+ B' _  b, S
  351.         return 0;, X6 Z: l5 d, H0 \) Z. }. k
  352.     }
    1 q* D3 B. e4 o0 r/ `7 a

  353. / ?8 X/ M) W3 Q  f! O- c* O2 l
  354.     /* find the max frame size */4 v4 @) A, s4 [7 m/ q
  355.     max_frame_size = 0;
    9 |; [3 }8 Y" g
  356.     for (i = 0; i < rbt->frame_count; i++)
    9 c+ x4 a8 r% Q, p
  357.     {
    5 h1 K: F, F1 N" b* {
  358.         frame_size = LE_16(&rbt->frame_size_table[i*2]);
    - n% E+ \+ G5 y1 O# z) L) J
  359.         if (frame_size > max_frame_size)
    ! p: M, b+ n9 T4 p% s# W- |1 Y
  360.             max_frame_size = frame_size;
    / ~$ F. D. W# J. E, x0 b# E4 v
  361.     }
    . n1 f; w/ `0 c$ n" P, l1 H
  362.     rbt->frame_load_buffer = malloc(max_frame_size);
    6 p3 a' [! Q+ v

  363. ; p: u& p2 ?; J5 E: M. @) A
  364.     /* transfer the unknown table(s) */: B0 e+ O3 A" \) R7 Y! N! y( }
  365.     if (fread(unknown_table, UNKNOWN_TABLE_SIZE, 1, inrbt_file) != 1); m8 u  A$ O, ]+ ^6 D
  366.     {: O1 m& `) ^( h
  367.         printf("problem reading unknown table\n");+ Q6 V0 _- m) x
  368.         return 0;
      }  D4 f: h3 g; [
  369.     }
    ) {  G& b* {: V- }, \6 k( G
  370.     if (fwrite(unknown_table, UNKNOWN_TABLE_SIZE, 1, outrbt_file) != 1)! z& I* J, \8 a7 U& x
  371.     {# V3 p/ R6 I  y; G% w& E/ C
  372.         printf("problem writing unknown table\n");/ }& q+ V# i6 ^  N9 ^( a! ~. }+ y
  373.         return 0;
    0 Q" q4 i# |- g8 f( @
  374.     }$ ^2 z7 J. C5 q* k6 |

  375. % Z- C9 X$ S: v3 u3 [# }3 C  T# ^" D
  376.     /* copy over padding */
    ' F/ K+ w0 T) O
  377.     padding_size = 0x800 - (ftell(inrbt_file) & 0x7FF);
    2 ^6 ]& z: i0 D& X
  378.     if (padding_size)* X8 j  O5 e$ c* O6 A3 n* a( K
  379.     {
    ! w/ _: G0 A- p& G8 g
  380.         padding = malloc(padding_size);/ o+ O/ b4 U: J& a. [: x
  381.         if (fread(padding, padding_size, 1, inrbt_file) != 1)/ J6 e4 D2 J! T' w
  382.         {$ h) Z3 F. B+ M1 V! D
  383.             printf("problem reading padding\n");  N. ]* z* J4 f' {0 l
  384.             return 0;
    # X" E1 ^' s5 a& D2 |
  385.         }5 v; s$ s* z: w, b  A
  386.         if (fwrite(padding, padding_size, 1, outrbt_file) != 1)
    - U- T, e2 R$ v; r+ S& Z6 ~' N
  387.         {
    8 y9 r1 {0 u0 P4 A/ N
  388.             printf("problem writing padding\n");
    ; g( u1 J- h6 Y3 ~' g. d
  389.             return 0;
    6 C; r; ?2 y" X7 t4 a' R
  390.         }
    " D* w3 i9 o  q" I( ~; p
  391.         free(padding);3 ~/ L( y4 U5 _' s* R
  392.     }
    . O3 S& \( @+ G; U) H; ^8 `6 H

  393. * k. O0 K" {- [, s: o8 O
  394.     return 1;1 @4 m1 h3 p' e' U! c1 f' n% m
  395. }0 I/ Y3 {2 O, n

  396. % @; l* [# P% I1 n4 E
  397. static int get_lzs_back_ref_length(get_bits_context *gb), x4 v" F1 O3 o2 e" o
  398. {
    ( |! d5 s- A9 r! D
  399.     int vlc;
    , T/ ~3 t: R2 a+ s
  400.     int count;- {1 C( ?) _; h. f: N: S
  401.     int value;; F: q, |0 p/ l! e7 B+ e% V

  402. 1 S9 s1 O4 R- `" G" V( r; E. @
  403.     vlc = view_bits(gb, VLC_SIZE);3 G# T  G. S" S' k. y5 ~  {
  404.     count = lzs_vlc_table[vlc].count;
    9 ~0 e4 ]$ J# A/ m3 |) c  ~
  405.     value = lzs_vlc_table[vlc].value;8 i) q  x$ o; R- Q
  406. . q, E* Q1 f) {, s' g) y
  407.     read_bits(gb, count);
    ' {% h9 ?2 X, R! S! w
  408.     if (value == 8)
    0 |- D2 M3 @( D6 A
  409.     {/ n# Y6 E2 V/ m/ _# V1 }  `( Q  q
  410.         do
    , b3 U* Q2 ~. |) x6 S% [/ F
  411.         {
    * C- n4 W  w  A# E& s/ v, ~
  412.             vlc = read_bits(gb, VLC_SIZE);1 }0 w0 Z0 p$ f, {% R" T
  413.             value += vlc;
    / ]. X/ r: I3 @
  414.         }0 @: n  T: S- M# H4 U* c% i8 C4 Q
  415.         while (vlc == 0xF);
    8 W* I6 D9 l8 N3 o
  416.     }
    . v8 a7 i2 T0 R& }3 ~

  417. 6 t0 w6 F& w* f; F- Y' V
  418.     return value;3 g* ?# J# }! K. l: s5 V$ I' z( \5 X
  419. }) d; b9 h( S& Y
  420. ( {9 p! B  }; V6 y
  421. static void compress_window(put_bits_context *pb, uint8_t *full_window,5 \8 o: c- Q& A6 T2 L% ?& ^
  422.     int full_window_stride,
    : Q# L/ [9 X- h5 P5 t( N
  423.     int window_top, int window_bottom, int window_left, int window_right)8 S1 f: `  H0 R2 c$ s
  424. {
    2 Y# R& [8 W1 y' P
  425.     int last_pixel;- r3 c3 k. x* X/ w6 ^
  426.     int run_size;
    % M3 \+ `+ I$ g
  427.     int x;, k, E0 g! T& G! X+ Q% ^# g
  428.     int y;
    % T9 {1 M+ ?, _4 Y) U. f. T" g
  429.     int start_index;9 c, v& A' P0 ?8 f" s: G% p! L# ~
  430.     int end_index;! n) n. }9 H" t- s1 z" q; ]
  431.     int encode_last_run;
    8 E/ H* s, {( }! j3 `4 M& F6 Z
  432. ! N. _  H$ R" N
  433.     last_pixel = full_window[0];3 z! x- b" |$ q' |& p: E
  434.     run_size = 1;
    ! K" C& e+ e0 y# P9 j
  435.     for (y = window_top; y <= window_bottom; y++), Z7 z  T8 H$ ?  D$ i
  436.     {
    0 r' ~! f7 X8 d0 p9 I* b9 P- Q1 ]1 V
  437.         start_index = y * full_window_stride + window_left;
    5 m3 r6 Q6 M" w: C: Z, d) i: }% H# M
  438.         if (y == window_top)$ D" B' p3 N, e, D
  439.             start_index += 1;
    0 g- q8 z6 p. `
  440.         end_index = y * full_window_stride + window_right;0 \' ^" z, G7 m2 A4 O+ X! f
  441.         if (y == window_bottom)
    * U4 w2 Y' L  e$ J. `
  442.             encode_last_run = 1;
    , y; `1 y7 d- X% G/ X- q& L
  443.         else) b/ n( a2 M- M) z7 M) K  s; S
  444.             encode_last_run = 0;
    ) X8 S1 ]5 a; e8 x! |8 |
  445.         for (x = start_index; x < end_index; x++)
    : K0 j7 d4 s( f5 i. m, I  w
  446.         {
    5 I+ a$ S( v7 k! A
  447.             if (!encode_last_run && full_window[x] == last_pixel)5 h7 u% `9 S* }/ ~
  448.                 run_size++;
    + _, p. D2 P6 U* i5 ?1 ?! E' [( d
  449.             else6 x5 k% u0 k* L% h- Z
  450.             {
    6 u" A& y( I* T/ h$ f: K: w
  451.                 if (run_size == 1)
    2 F3 W% J! I5 t) m- E
  452.                 {
    ( u/ ?. P: K  L; B7 k' Y  A
  453.                     /* encode a 0 bit followed by raw pixel byte */
    ( m4 c) i/ n0 K  i, C! G
  454.                     put_bits(pb, 0, 1);) m; W+ @% B1 b( I; g
  455.                     put_bits(pb, last_pixel, 8);
    ; {( ?' R: q( Q+ c3 k! f1 ^
  456.                 }0 u; g, F3 M1 B
  457.                 else if (run_size == 2)
      X' o3 b1 m0 ~
  458.                 {
    * t+ q* t3 ^8 ]7 ~0 q
  459.                     /* encode a 0 bit followed by raw pixel byte */
      s3 ?8 N8 j3 K% \  ]
  460.                     put_bits(pb, 0, 1);! H/ f. [% r+ v
  461.                     put_bits(pb, last_pixel, 8);+ |& q, _# U/ W9 K" X
  462.                     put_bits(pb, 0, 1);- n. g* |6 s3 J" r' N) x2 v2 p
  463.                     put_bits(pb, last_pixel, 8);
    ( B: k) j& K% `6 x
  464.                 }
    " o+ ?+ b8 f. B9 q/ `% [8 |: R
  465.                 else# S* H6 k( Y( P9 T9 {3 i) P
  466.                 {
    2 s8 |9 N/ r2 M" Y# J+ F, M
  467.                     /* encode a 0 bit followed by raw pixel byte */! s; h8 S! l! }. @9 s; T8 C  e
  468.                     put_bits(pb, 0, 1);
    & u" |0 z3 g2 c' p* i, c
  469.                     put_bits(pb, last_pixel, 8);9 j/ |$ S# R1 f* c6 M. d4 ]9 H
  470.                     run_size--;: u; x  P) R5 j: |/ @/ K  v
  471.                     /* encode a run: a 1 bit, followed by a back reference
    3 }  o& z6 ?; g
  472.                      * offset (-1), followed by a length */
    + S5 ~! m/ t( T: q
  473.                     put_bits(pb, 1, 1);4 V- X  C% G' d6 A
  474.                     put_bits(pb, 1, 1);  /* 1 = 7-bit offset */+ V# B. x: z. ~
  475.                     put_bits(pb, 1, 7);
    3 r5 I; u7 h- l) V  H9 J0 B7 m; G
  476.                     if (run_size <= 4)8 s! L: m* I2 _- x2 s
  477.                     {' i" s) o: X4 P4 X/ B
  478.                         /* lengths 2, 3, and 4 are 2 bits */
    8 b7 y2 B; n( n
  479.                         put_bits(pb, run_size - 2, 2);
    * k3 A3 T* @. h; X3 C3 I
  480.                     }
    + L) e0 I5 z# L2 Z: p
  481.                     else if (run_size <= 7)/ \9 W$ s9 q* N
  482.                     {
    + J4 r+ Y- n8 ]- ?8 }- m
  483.                         /* lengths 5, 6, and 7 are 4 bits */
    ) }0 G* t; b5 y1 ]  X7 J! ~
  484.                         put_bits(pb, run_size + 7, 4);6 Q& a6 \* W8 D0 {9 i( S. p
  485.                     }7 S9 }: d+ X5 W2 c+ p- f+ l; R
  486.                     else8 y8 p& t& D3 B) I+ X
  487.                     {1 Q6 l# I3 |8 M( b0 k) p* j# C
  488.                         /* arbitrary length; start by encoding 0xF which. o, A1 o& a0 r  ?
  489.                          * stands in for an initial version of 8 */
    0 F8 L+ Y8 }" o
  490.                         put_bits(pb, 0xF, 4);" @! |& A, K. g. H% S/ |
  491.                         run_size -= 8;  _, V; O& r7 R5 v' w2 v
  492. # Z' G- g( B% T( w/ |7 Z$ q9 x0 D! e& l
  493.                         /* encode blocks of 4 bits until run_size is 0 */. o7 N; D  Z3 Z
  494.                         while (run_size >= 0)5 X7 E/ e) n) [4 ~$ k* ?
  495.                         {/ w/ T; s" _  g) J% B. \
  496.                             if (run_size >= 15); l2 h* _$ r4 V- U/ ]2 S# o
  497.                             {
    9 s( O, O5 l: x# s; i
  498.                                 put_bits(pb, 0xF, 4);
    0 k) o% q0 o3 E: [
  499.                                 run_size -= 0xF;8 T8 o3 K1 n: p+ t! f( [1 J, T
  500.                             }
    " z$ C5 X  ~; I) V; N+ l5 N
  501.                             else
    : ~: L2 r# K2 W  {' ]# m# Y" U
  502.                             {
    5 Z, f# e8 q2 y& m& g* {+ H
  503.                                 put_bits(pb, run_size, 4);! u: e0 G( v4 R- R* A* a
  504.                                 run_size = -1;, V" C  ]9 H( t3 Y# w
  505.                             }
    + \$ l. F* Z) z& c
  506.                         }
      ^* S$ q- U" }7 K/ \$ b- I* h
  507.                     }+ e1 X( ^! q+ r1 D" D4 d, w: l4 P
  508.                 }3 L' p  q# F" t- J6 Q

  509. ; i6 A  V' N; E, s# ~: A+ @. s4 k
  510.                 last_pixel = full_window[x];* T2 H' L) r  ^7 O  ~
  511.                 run_size = 1;6 c9 K) o1 \" t

  512. 1 Z$ R; K* J) k: A9 g+ J
  513.                 /* this single x iteration was only here to close the final run */
    $ W; l( ~( B/ l9 B, L: a
  514.                 if (y == window_bottom)
    - M6 U" ?4 }7 _
  515.                     break;
    , c0 n, L3 y4 q
  516.             }. A, H# b- w/ V5 y1 M+ _
  517.         }6 M- L3 H( Q5 w" [& \# _" d
  518.     }
    # o6 S1 K, E( t, g
  519. , B- l: f% k" B7 |5 Q
  520.     /* close the bitstream by encoding a back reference with length 0 */
    ! B3 N) |. |/ Y/ n! u
  521.     put_bits(pb, 1, 1);  /* back reference run */3 G* A3 W1 A* q' }9 ^0 p9 `
  522.     put_bits(pb, 1, 1);  /* 1 = 7-bit offset */
    + h+ n1 |% m, q. ?/ h. e; ?
  523.     put_bits(pb, 0, 7);  /* length 0 */
      q9 \' g, }: v0 I

  524. ( m0 S9 Z: ^1 \, Z
  525.     put_bits_flush(pb);
    7 W" T1 y& C1 i& m6 k4 ?
  526. }
    . E+ Z; ^4 [3 G
  527. 7 Z5 V1 N, K# [9 ?
  528. /* compute Euclidean distance between an RGB color and the desired target */
    8 U# Z, c2 j9 X; Z# ^8 V
  529. static int compute_rgb_distance(int r1, int r2, int g1, int g2, int b1, int b2)& T: ?0 B5 N% {$ ~
  530. {3 C: ~+ R: k- w0 J4 j
  531.     return sqrt((r1 - r2) * (r1 - r2) +2 G* u& t) v% m: H
  532.                 (g1 - g2) * (g1 - g2) +/ p+ J! O' \- M8 x: r0 Y
  533.                 (b1 - b2) * (b1 - b2));
    ; i: I4 w0 J0 C9 V
  534. }2 ^' p" Z& X7 a9 C7 w

  535. . P2 b1 N# `4 w8 `! f( ?' U2 b/ Y
  536. static uint8_t find_nearest_color(rbt_dec_context *rbt, int r, int g, int b)
    + @# H# @  K% E: n7 I
  537. {- r/ e7 q+ @- m/ N) Y7 L
  538.     int i;
    $ D8 ^3 Z. i- ~- {, V$ N0 ]. r
  539.     int nearest_distance;: _* Y" u2 _8 b+ `( {
  540.     int distance;& s  c% A/ J2 D$ F2 ]
  541.     int rp;: l  _' e& l$ q5 G( w$ h9 O! F* Y
  542.     int gp;4 f  w" ^8 \& u. W1 C5 H( V5 h( G
  543.     int bp;
    ' R9 F4 H: q0 u, A6 N8 x
  544.     uint8_t palette_index;- B: S* q! Y2 v. E+ p

  545. . c# d/ r% r3 a: j' M( Z
  546.     nearest_distance = 999999999;( x6 u( u2 b# [* o% E. I
  547.     palette_index = 0;
    + n* x" ]  J* n
  548.     for (i = 0; i < 256; i++)
    4 R) M6 P2 t- ^/ f7 U# g. k
  549.     {
    ; S8 ^2 C  K% H7 H- I* a8 y
  550.         rp = rbt->palette[i * 3 + 0];- x5 b! y3 O! j5 e* w; X- V9 ]
  551.         gp = rbt->palette[i * 3 + 1];
    7 @) ?. K4 u$ _0 {6 }
  552.         bp = rbt->palette[i * 3 + 2];
    # M/ G+ \& ?2 z' `+ m5 {
  553.         distance = compute_rgb_distance(r, rp, g, gp, b, bp);
    4 }, R! Q. X8 Q
  554.         if (distance < nearest_distance)
    0 K# c: N3 [7 Y2 R1 H
  555.         {/ u: L6 H$ f, r2 ]+ o5 C
  556.             nearest_distance = distance;
    1 ?# C1 p+ Z7 N! G& k* Q
  557.             palette_index = i;. b8 |7 `: w" I$ z1 i* a
  558.         }
    # R1 p4 Z1 m; j# q: B1 m. X0 Y
  559.         /* can't get closer than 0; break early */# y$ x' k3 W" b! l" A
  560.         if (distance == 0)
    9 F* N7 A2 k5 K" `/ ?
  561.             break;! ^7 j' ]) J6 g; h9 s; H" @
  562.     }
    7 `' n# K! z. b

  563. . ]3 u0 u& G1 O. o
  564.     return palette_index;! X0 `% E0 w- [% }% A( {
  565. }
    . ^  R4 |( r# `5 _0 A

  566. $ u, c6 b6 `3 X6 A' p& R! w) _
  567. static void subtitle_frame(rbt_dec_context *rbt, uint8_t *frame,+ @* ?8 h4 Z+ t2 |2 M
  568.     int width, int height, int timestamp)- \  q2 {& d6 s6 M$ Q
  569. {
    1 A8 G: @! j* T
  570.     ASS_Image *subtitles;
    2 j  X$ d6 w$ Z# E
  571.     int detect_change;! d! Z! R. a/ W1 j
  572.     uint8_t subtitle_pixel;- `! x# ~& D3 F  R8 n4 u
  573.     int x, y;
    - @% }) D6 o& b/ M, e- m
  574.     uint8_t *frame_ptr;3 a. t5 ?$ }* x$ i* N
  575.     uint8_t *subtitle_ptr;- i9 M: D) @& |

  576. 1 D: a8 P0 I! ~3 @( k( V4 F
  577.     /* ask library for the subtitle for this timestamp */
    1 o2 S2 a3 l* Z  \2 T
  578.     subtitles = ass_render_frame(rbt->ass_renderer, rbt->ass_track,
    * s/ y% ~6 S) h8 m
  579.         timestamp, &detect_change);
    ! g7 {+ a! u9 p

  580. 8 {2 |5 J* ^- {1 f1 `0 B
  581.     /* render the list of subtitles onto the decoded frame */0 M$ k" }5 |. O1 Y1 @( a$ T$ u4 S
  582.     while (subtitles)
    ( y2 K0 }2 k5 D8 r! s; D  `. K
  583.     {+ m1 f% x2 p2 Q$ E% ?9 q4 K
  584.         /* palette components are only 6 bits, so shift an extra 24 r1 _, \7 f8 {- Y
  585.          * bits off each component */
    / K. `* E4 K8 y* d
  586.         subtitle_pixel = find_nearest_color(rbt,/ X& t8 v/ K- o2 O% }3 ?7 q% r
  587.             (subtitles->color >> 10) & 0xFF,6 \# Z7 w$ @4 J
  588.             (subtitles->color >> 18) & 0xFF,
    ; U$ x' W, S+ G6 ]2 p8 d
  589.             (subtitles->color >> 26) & 0xFF);& _) A, T2 W9 h$ K  [
  590.         for (y = 0; y < subtitles->h; y++)2 X4 a/ O; j6 R5 O8 d
  591.         {
    $ r' @2 ]- B% j7 G3 {: ?9 D
  592.             subtitle_ptr = &subtitles->bitmap[y * subtitles->stride];
    * H& {: G( h! Y" p; }) \( M
  593.             frame_ptr = &frame[(subtitles->dst_y + y) * width + subtitles->dst_x];; H; u8 c& @8 h3 P. s1 K0 V
  594.             for (x = 0; x < subtitles->w; x++, frame_ptr++, subtitle_ptr++)
    2 k9 x5 D) j' z! T9 Y
  595.             {
    ; ^" E* ?; O6 N  d& F3 e$ K$ l
  596.                 if (*subtitle_ptr >= SUBTITLE_THRESHOLD)" H1 U" `6 y% n, Z: T
  597.                     *frame_ptr = subtitle_pixel;
    , [1 Q6 m0 t) S# J0 F
  598.             }
    : t+ B' B( c# H$ Q" k+ @
  599.         }' g" w: o! T9 k$ o4 i5 M
  600.         subtitles = subtitles->next;
    + Y; N* O  S& m7 m1 j5 A; l
  601.     }7 t( P6 C( @/ }0 o
  602. }$ y6 L- t% r: L, u5 c

  603. * m% L+ l3 t5 q% }0 Z
  604. static int copy_frames(rbt_dec_context *rbt, FILE *inrbt_file, FILE *outrbt_file,
    1 ]" p6 ]+ R( L+ ?* }
  605.     int origin_x, int origin_y, int window_width, int window_height)  P7 P7 [" o9 `
  606. {
    / ?" ~0 k: t# n% ]
  607.     int i;
    . ~4 w! ?# E$ k
  608.     int j;# \- h) `3 u7 f  ^1 l
  609.     int scale;
    " P* V, a5 I0 u, G) w# R% K4 k
  610.     int width;
    8 y6 [- _  G3 C' c+ Q
  611.     int height;
    ( W/ u8 k/ ~; w/ I" I
  612.     int max_width;
    - d2 B& k$ j4 _. \
  613.     int max_height;, B; f( [) l8 ^4 R( S# _) |# O
  614.     int frame_x;" ]# }9 C0 W' R9 F" z
  615.     int frame_y;8 |' ?8 X, G& }( _! T" r
  616.     int fragment_count;! E/ l( h4 Q# r$ H' U$ I4 y5 V! Z( |
  617.     int decoded_size;
    , n2 m! Z4 S( {  B' D3 H; ~
  618.     uint8_t *decoded_frame;
    1 ^7 C0 u# Z5 P- m6 F
  619.     int fragment;/ o- a) w1 x8 }$ m, J5 Y# d! C
  620.     int fragment_compressed_size;0 Q) \: L- N/ D( `0 F; S$ Q
  621.     int fragment_decompressed_size;9 G3 m+ G) ^2 L1 u" M2 N8 d1 W/ l; S" X
  622.     int compression_type;
    2 U/ m. d2 N  v# t$ _8 C6 h, `
  623.     int index;
    ; k, {) l* n! t; |: g* \1 ^4 |# B3 @
  624.     int out_index;" o9 d+ D( i( A4 ]7 w; F6 R# Y
  625.     get_bits_context gb;
    - H4 U4 y. K+ z3 i* P: ~7 i
  626.     int frame_size;
    7 g' H1 z8 r1 |) [( V1 |% I
  627.     int video_frame_size;
    ! W# v& Y" W. Y0 n; f" I1 M* t
  628.     int audio_frame_size;
    2 A( }$ V# {' {, D

  629. ( K+ y; h/ _4 e) f: P+ y# ^4 L
  630.     int back_ref_offset_type;
    / R6 p6 v( y4 }$ ~! ]
  631.     int back_ref_offset;; U! S+ D, K( c1 |! X; a! }
  632.     int back_ref_length;
    ) `3 l( ?' |# r0 b& g$ I3 J& s3 m
  633.     int back_ref_start;' K% o$ `% O" N7 U7 J2 b. Y, _
  634.     int back_ref_end;3 B0 E3 @( L8 u$ I- P) i1 `

  635. - p. K% Z' U5 \- Y: `1 R
  636.     uint8_t *full_window;
    ( u1 r  A, f. S0 N0 [
  637.     int full_window_size;, I% s3 r8 h/ X5 E& L
  638.     int y;
    , T5 h! t5 f& _7 `$ ~
  639.     int window_top;
    ! z& @+ d: P2 B7 U. i8 f- E
  640.     int window_bottom;
    0 B  {0 w. ^/ Y( K! ~
  641.     int window_left;
    & ~7 u5 E- `. E2 @! U
  642.     int window_right;& c7 v, K. t. P
  643.     int window_size;" y$ A- y- v' D/ T
  644. , r0 A  R1 `) H- ^- _
  645.     char filename[30];% I3 m: i) ]7 C$ z% B
  646. : A* J% z8 |) G7 G( f
  647.     put_bits_context *pb;$ C2 d, B: q6 m5 k" X
  648. ! {$ p0 k: I: U
  649.     full_window_size = window_width * window_height;1 D  ?7 [+ R4 f- ~" C
  650.     full_window = malloc(full_window_size);" }6 F" r( G' R  c
  651.     pb = init_put_bits();
    ; e6 |5 |! b* \& _$ J! u' @

  652. ' W1 l& l" Q2 r0 @
  653.     max_width = 0;
    * z! a5 t! ^7 Y2 s. r
  654.     max_height = 0;8 i( E: i& H8 q  M9 S
  655. 0 j, }6 @3 ~$ H8 ~( F! Z
  656.     for (i = 0; i < rbt->frame_count; i++)
    * B0 `+ u" t. s$ ]$ n! [9 e
  657.     {/ V4 }- O7 o/ P$ |
  658.         /* read the entire frame (includes audio and video) */
    8 p3 D( E! [- D) S% j% z
  659.         frame_size = LE_16(&rbt->frame_size_table[i*2]);
    : D/ _+ [. B: ]
  660.         video_frame_size = LE_16(&rbt->video_frame_size_table[i*2]);
    3 N& ~; N% y7 R/ s6 w9 w! N& i
  661.         audio_frame_size = frame_size - video_frame_size;7 N% v4 `5 s9 T7 q- X
  662.         if (fread(rbt->frame_load_buffer, frame_size, 1, inrbt_file) != 1)
    0 y' S# o0 w! J
  663.         {+ ~; u" _! {0 z
  664.             printf("problem reading frame %d\n", i);# H4 o% e  b4 x: z7 v
  665.             return 0;
    - h% P" ?1 b. r
  666.         }
    ) S& x4 x% s+ V

  667. 1 O6 Z9 r1 C( ?+ E/ G& K" w5 ^* T
  668.         scale = rbt->frame_load_buffer[3];
    5 s, p1 }1 j; b! S" _. C1 _" A
  669.         width = LE_16(&rbt->frame_load_buffer[4]);
    : S& h$ f3 t4 S
  670.         if (max_width < width)$ \4 k( R$ q# q- j# G8 @" B
  671.             max_width = width;# M/ \! a" E8 @( y5 v/ Q2 k) H
  672.         if (max_height < height)! ~& R& F3 r/ }' `
  673.             max_height = height;
    * T& [" F1 e4 R. W+ e+ C
  674.         height = LE_16(&rbt->frame_load_buffer[6]);, h5 y7 r: r; m* y0 L* d% b" r
  675.         frame_x = LE_16(&rbt->frame_load_buffer[12]);& Z5 s( [: R7 P+ f) q7 @
  676.         frame_y = LE_16(&rbt->frame_load_buffer[14]);) b- w1 ]7 ^4 x
  677.         fragment_count = LE_16(&rbt->frame_load_buffer[18]);
    9 O3 Y; p3 m8 g0 i6 F1 R0 |+ T3 F! D* T
  678.         decoded_size = width * height;
    2 l: m+ r& F" X, K4 [0 v5 C

  679. 1 u) M- B4 i8 S
  680.         printf("processing frame %d: %d%%, %dx%d, origin @ (%d, %d), %d fragments\n", i, scale, width, height, frame_x, frame_y, fragment_count);* T: @0 D: ^  `! ]- d4 n; e
  681. 7 M- R  L: T8 s& n4 w6 w' N
  682.         /* decode the frame */* Y( t- M, L3 }; K7 x3 L$ R; y, i
  683.         decoded_frame = malloc(decoded_size);  ?0 `) w9 A* g' r
  684.         index = 24;
    5 L1 ]7 Y6 o, E6 P) \3 N' v" @
  685.         out_index = 0;
    - p* y) G' X/ T  z
  686.         for (fragment = 0; fragment < fragment_count; fragment++)
    5 y' j5 w" [( z/ L9 P( n
  687.         {7 Z! u3 c( {) h5 u
  688.             fragment_compressed_size = LE_32(&rbt->frame_load_buffer[index]);
    3 T1 W# Y# i( }6 T. S  B" a, S
  689.             index += 4;3 _, K* N5 Q% Z/ j) b, V; q
  690.             fragment_decompressed_size = LE_32(&rbt->frame_load_buffer[index]);
    0 M3 z6 \# d; E' u. i/ p$ h
  691.             index += 4;
    & w9 x. O9 g( R8 @
  692.             compression_type = LE_16(&rbt->frame_load_buffer[index]);' f% |3 D: j2 u4 w7 i) D  h
  693.             index += 2;
    , g) [; K- G- h/ t0 |
  694. . |* w  ]: ^1 V! R7 c/ V  y3 j
  695.             if (compression_type == 0)
    & s2 H7 [6 B2 M% L8 x( e, S
  696.             {/ i+ G$ c- V* J8 s1 c4 |# V1 Z( y- z
  697.                 init_get_bits(&gb, &rbt->frame_load_buffer[index],. c' \+ P  n5 B
  698.                     fragment_compressed_size);% E9 L! @- [3 g! x

  699. " d2 c" n0 K) s
  700.                 while (out_index < fragment_decompressed_size)$ D# V* o$ h& P/ v; `3 t
  701.                 {
    ( d* G& X& y/ }( T8 s1 c
  702.                     if (read_bits(&gb, 1)). T* }' Q5 F6 c  K1 G1 }8 B  @
  703.                     {  C9 i) E7 p. I+ J& v( l: b
  704.                         /* decode back reference offset type */
      o& n1 t+ w& i& t2 d( x% R, B
  705.                         back_ref_offset_type = read_bits(&gb, 1);+ l: E2 Y9 G; N3 i
  706.   J- ?+ q( Y2 r4 `
  707.                         /* back reference offset is 7 or 11 bits */9 x3 P$ |& A% W8 _& ]
  708.                         back_ref_offset = read_bits(&gb,
    : M4 P  Y" c" d! w
  709.                             (back_ref_offset_type) ? 7 : 11);7 H6 W+ [' n4 J9 f+ H

  710. 8 p) a' u/ V  n3 {9 p( Q0 o- c
  711.                         /* get the length of the back reference */1 O+ Y9 o: W/ F/ e
  712.                         back_ref_length = get_lzs_back_ref_length(&gb);' E% N! R) l3 `4 q9 ^$ h
  713.                         back_ref_start = out_index - back_ref_offset;
    0 \4 l: m3 i3 z
  714.                         back_ref_end = back_ref_start + back_ref_length;
    , D: V  ]3 O  d! m* ~* Y" Q. A% f2 j  M
  715. 7 k! J4 }& q& R5 R
  716.                         /* copy the back reference, byte by byte */. @2 t# J% Y/ i; e
  717.                         for (j = back_ref_start; j < back_ref_end; j++)
    , N+ Y! H7 N0 p9 G/ e
  718.                             decoded_frame[out_index++] = decoded_frame[j];% ~5 _0 S+ X( R# r4 E  E" T
  719.                     }9 K: [7 ^* Y1 ~2 |4 p
  720.                     else& O3 ^  V4 l1 Q1 t% v3 K
  721.                     {
    . C: Q9 z1 r3 G/ D/ m0 [
  722.                         /* read raw pixel byte */
    # x+ q$ Y9 ]1 W5 {: i/ @& R
  723.                         decoded_frame[out_index++] = read_bits(&gb, 8) & 0xFF;
    8 H" h% y, ^1 J5 u
  724.                     }2 o( H2 u+ h/ @% _9 k& ~
  725.                 }+ M9 @( ]( F" R5 P# h
  726. : o" l; o# G& V/ _' K; e
  727.                 delete_get_bits(&gb);' k" M2 X0 D' y. r( O
  728.             }* G  M* R9 z, a2 {, I) U& j8 H' z' y

  729. 0 q9 j9 i2 s* |+ g3 l
  730.             /* next fragment */
    3 ^! c+ p/ p0 U: q& o
  731.             index += fragment_compressed_size;7 R+ W9 o1 T$ n
  732.         }
    / o" W% S9 E8 y* ?# B6 G" ]4 o
  733. 9 D0 v, ]7 L: v' \/ @
  734.         if (rbt->dump_frames)
    $ e4 Q( H6 k( V( {/ K
  735.         {4 c0 w! n+ v2 i2 O  s* @
  736.             /* dump the original frame */( M. ^7 r+ b4 m9 F# Q
  737.             sprintf(filename, "original-frame-%03d.pnm", i);
    3 R: y: {& w: k0 s& ^
  738.             dump_pnm_file(filename, rbt, decoded_frame, width, height);. Z6 ~' e( v9 v# g& T7 j% w
  739.         }
    " K4 E9 X) H+ ^6 N9 S
  740. ! H' y. b0 Z7 J
  741.         /* transfer the image onto the frame window */! v& J7 r( g6 O% n! q4 k) n1 `) N
  742.         memset(full_window, 0xFF, full_window_size);
    ! n' N5 z- f% p
  743.         index = 0;
    9 S8 l& q. ^% k7 k
  744.         for (y = 0; y < height; y++)
    5 B' U) l/ e7 Z- k2 ^* i. E
  745.         {
    5 ]3 o$ _  X' e. P& p' @+ b/ e
  746.             out_index = window_width * (frame_y + y) + frame_x;. K0 M' k7 a4 R6 Z0 K
  747.             memcpy(&full_window[out_index], &decoded_frame[index], width);4 n; K- [. @( I! N- c
  748.             index += width;
    3 E1 D' C" j+ g, C" S% Z, d$ x
  749.         }7 G: ~. X  _- z1 E

  750. . {: g' z# G5 N+ {+ s( c
  751.         /* write the subtitle */
    : ^7 I) y, t; f: y
  752.         subtitle_frame(rbt, full_window, window_width, window_height,, K) X" z! @  C" F# T
  753.             i * MILLISECONDS_PER_FRAME);  v% N1 \0 k  d4 a
  754. 6 w+ p( F- ~3 U7 Y  {9 m7 q" Z
  755.         /* figure out the smallest change window */0 J* w: X" s5 v9 ^
  756.         window_top = frame_y;$ a- N7 z3 Q  @* i3 t9 Q
  757.         window_bottom = window_height;: g, t2 F; x- I* z. H
  758.         window_left = 0;* s# c* W% i' ~9 }! B0 V/ ^
  759.         window_right = window_width;
    , P# t% P% A1 {5 Y, C. W7 c8 r' z9 t
  760.         window_size = (window_right - window_left) * (window_bottom - window_top);1 I  ?- E, s& {8 Y7 a( W8 H8 e

  761. ! J( j$ t: N+ E) @/ ~% T3 b
  762.         /* compress the frame */7 L6 S8 t5 F- s' L
  763.         reset_put_bits(pb);
    ' V9 f/ v3 w- \/ r6 ?1 [* H
  764.         compress_window(pb, full_window, window_width, window_top,
    3 I$ d  m5 g2 B! B1 r, f
  765.             window_bottom, window_left, window_right);% j: Z8 ?& r5 K3 N/ f4 E1 t
  766. 1 \6 D7 o0 J$ X$ M2 ?
  767.         if (rbt->dump_frames)
    4 c7 O4 M& }: P/ t) a$ u
  768.         {. X1 P6 C9 v3 \4 W
  769.             /* dump the frame plotted onto the full window prior to encoding,
    & \2 I6 i1 Y7 o  m( ?, n
  770.              * with subtitle */% o+ Z8 N2 t9 S  u  i, S* P% x
  771.             sprintf(filename, "pre-encoding-frame-%03d.pnm", i);
    ! G& F) J9 l: w* Y2 r3 F9 n7 `, b
  772.             dump_pnm_file(filename, rbt, full_window, window_width, window_height);  f" g/ e5 X+ Z' r
  773.         }7 D- l6 A5 k9 B" D+ O

  774. $ N8 D" `5 C3 B
  775.         free(decoded_frame);
    6 G" v" N" v# Y6 e/ E2 F
  776. . y9 k6 A& T& E+ o/ Q
  777.         /* update the frame header */
    5 {0 q% z+ r8 N! q5 z8 d' X
  778.         /* width */% {3 Q9 O& f; H' }
  779.         rbt->frame_load_buffer[4] = (window_right - window_left) & 0xFF;
    3 l% y, H) b$ U4 U( t. _$ \
  780.         rbt->frame_load_buffer[5] = (window_right - window_left) >> 8;
    / l! ^9 R9 _8 B! k# W% d
  781.         /* height */
      n& Y; C, w2 ?
  782.         rbt->frame_load_buffer[6] = (window_bottom - window_top) & 0xFF;" ~8 B. T; S7 |" r3 X3 c3 ]
  783.         rbt->frame_load_buffer[7] = (window_bottom - window_top) >> 8;
    2 `/ F# v3 Q: f
  784.         /* origin X */
    " ]; J- U8 W% T1 {
  785.         rbt->frame_load_buffer[12] = window_left & 0xFF;2 ]8 x7 B8 h! K: ?
  786.         rbt->frame_load_buffer[13] = window_left >> 8;
    6 Y& i, H9 \/ @: w" ?1 e
  787.         /* origin Y */
    1 q! X- u# X. v
  788.         rbt->frame_load_buffer[14] = window_top & 0xFF;4 Y9 T: w/ B* ~4 m1 s
  789.         rbt->frame_load_buffer[15] = window_top >> 8;
    - }( P% c! u" \* T* P" L9 G/ Q% W( S7 T
  790.         /* fragment payload size */
    9 _5 a, O* G6 r  F" }! [
  791.         rbt->frame_load_buffer[16] = (pb->byte_index + 10) & 0xFF;
    + R% b( ?( X: t  |4 M2 {$ t! u
  792.         rbt->frame_load_buffer[17] = (pb->byte_index + 10) >> 8;/ U3 L, M2 \* ^
  793.         /* fragment count (1) */# Y1 P7 K4 I% f- V3 r
  794.         rbt->frame_load_buffer[18] = 1;1 k6 ]6 f+ @) Q! Y! g
  795.         rbt->frame_load_buffer[19] = 0;' p5 }0 ^3 K; q& H3 k* r
  796. $ j9 Z( c/ d  e3 ^+ Q7 S3 X
  797.         /* update the fragment header */' I7 k# L7 _3 e- x0 ~+ B- R
  798.         /* compressed size */
      D. p, T6 Y7 y0 H0 ]. J
  799.         rbt->frame_load_buffer[24 + 0] = (pb->byte_index >>  0) & 0xFF;
    2 U2 Y7 q' h: D3 E2 q9 ?6 Q: ?
  800.         rbt->frame_load_buffer[24 + 1] = (pb->byte_index >>  8) & 0xFF;
    1 |! _! R1 A. A4 t8 g( X5 F( s& o
  801.         rbt->frame_load_buffer[24 + 2] = (pb->byte_index >> 16) & 0xFF;
    1 [) `" |' J5 ~, }
  802.         rbt->frame_load_buffer[24 + 3] = (pb->byte_index >> 24) & 0xFF;( U+ N. p: p) N9 M. g2 @! {# y) @; y' U, _
  803.         /* decompressed size */5 P- N5 g5 H! W, G! q+ a6 o
  804.         rbt->frame_load_buffer[24 + 4] = (window_size >>  0) & 0xFF;8 ~3 R. Y, y+ @! l+ x0 w& l
  805.         rbt->frame_load_buffer[24 + 5] = (window_size >>  8) & 0xFF;
    % |% D  }% V; j# C* b2 |" C
  806.         rbt->frame_load_buffer[24 + 6] = (window_size >> 16) & 0xFF;0 J, m" x: T0 I7 K+ w' c
  807.         rbt->frame_load_buffer[24 + 7] = (window_size >> 24) & 0xFF;
    " J8 b# e% i. d5 \  Z  d4 l
  808.         /* compression format 0 */
      n- H$ D1 Q6 t$ M
  809.         rbt->frame_load_buffer[24 + 8] = 0;9 E4 q  ?0 Z4 C$ x7 Z: S
  810.         rbt->frame_load_buffer[24 + 9] = 0;8 G6 r0 Z* P9 K2 A7 ^# U; Q9 k
  811. : K: T0 U) U6 p2 J" U
  812.         /* write the 24-byte frame header and the 10-byte fragment header */) T& ]' K; K( ?$ x" t
  813.         if (fwrite(rbt->frame_load_buffer, 24 + 10, 1, outrbt_file) != 1). b: W( H7 k( b+ b
  814.         {* @9 s; a' o- a2 {0 w) C
  815.             printf("problem writing frame %d\n", i);9 c3 |" `1 Z$ ]2 N4 C1 C! P
  816.             return 0;2 T) B2 @" d7 r, q* B
  817.         }
    , p, V8 g* c  f1 P3 U

  818. ! |$ C( o4 J) Q8 p# @
  819.         /* write the new compressed frame data */
    , ?/ v( y1 ^6 H  b
  820.         if (fwrite(pb->bytes, pb->byte_index, 1, outrbt_file) != 1)
    ! H* o4 F% V0 a/ j1 B0 d
  821.         {- j7 \- c2 M2 ?  A! K; x5 E- @
  822.             printf("problem writing frame %d\n", i);
    3 {1 _2 d6 h  p) ~
  823.             return 0;
    " g7 D+ _. {3 ]
  824.         }) F: `: X+ U/ `" j2 s: W# Z; u% I

  825. 2 D9 R* U. u+ O- w- a0 {
  826.         /* write the audio data */
    , o  @# R( R1 {6 a9 W2 U* d
  827.         if (fwrite(&rbt->frame_load_buffer[video_frame_size], frame_size - video_frame_size, 1, outrbt_file) != 1)* g( U+ s2 k9 t: o) ]
  828.         {& K8 n1 _. a2 e5 B1 E% \1 T
  829.             printf("problem writing frame %d\n", i);
    4 \: `/ m# i" z6 g
  830.             return 0;
    7 m! P" @  X9 {, ?! t9 z' N
  831.         }
    . o) u: Z. s/ L& L& U, J1 f+ M/ C
  832. % _  k$ O" `0 k/ k) ~5 d
  833.         /* update the table entries */& v) E. N* N1 V, J5 h$ X, N% l
  834.         video_frame_size = pb->byte_index + 24 + 10;2 {( v- k  ^& V  |7 G
  835.         frame_size = video_frame_size + audio_frame_size;6 y5 x, u2 S. W5 |
  836.         rbt->frame_size_table[i*2+0] = frame_size & 0xFF;
    * b, M/ c9 j7 A' e0 n0 c
  837.         rbt->frame_size_table[i*2+1] = frame_size >> 8;0 Y: w, I# t( K  ~
  838.         rbt->video_frame_size_table[i*2+0] = video_frame_size & 0xFF;
    " y  y: Y) t# T8 O2 L
  839.         rbt->video_frame_size_table[i*2+1] = video_frame_size >> 8;
    ' D. ?# |* b8 s% C& r  j9 G
  840.     }
    % R" q# s) L, a4 B" T) G. @9 W9 I8 v
  841. , o. E/ Z5 @6 [7 D  H# ?3 t
  842.     printf("maximum dimensions seen are %dx%d\n", max_width, max_height);
    " O2 {, C! S6 _& U3 e; ]2 I
  843. 5 n8 h/ N# O* ?3 ~8 W  N! [& ?
  844.     delete_put_bits(pb);
    3 M7 G. O& P9 r5 ?
  845.     free(full_window);+ x4 N4 g- y# B4 y* m. r
  846. ( s' W0 j6 G! o# H- E
  847.     return 1;6 U1 B0 P: f+ C% v6 z4 j& Y
  848. }
    : E5 ^5 O& [9 v
  849. 5 X, u$ n# `$ p, w' Z+ \: o$ Y4 S
  850. int main(int argc, char *argv[]), d7 ~7 V. j- y4 ?/ s
  851. {
    8 A# g) f# y# O& w
  852.     char *subtitle_filename;
    5 D# G2 P7 c$ z" K7 y9 ^" ~0 \
  853.     FILE *subtitle_file;
    - I& F. }; ]. q' w8 F! Z& v
  854.     char *inrbt_filename;4 |9 d1 J* g1 V" D6 V2 x% z
  855.     FILE *inrbt_file;
    " J, \* ~, A( K$ j* d' ~  W* y
  856.     char *outrbt_filename;- i7 Z" f, ]$ e. f) a* w7 e
  857.     FILE *outrbt_file;, ~% a" U0 Y/ L/ @
  858.     rbt_dec_context rbt;
    # A( F3 \  }( @6 S
  859.     int origin_x;- K7 |& W& A7 f, R3 C- _
  860.     int origin_y;' W* y7 H2 |) C* y  `
  861.     int window_width;" }! |  K! ^+ F& M, i# T
  862.     int window_height;1 L: H! W2 d$ k8 z# z
  863. : `$ w3 X  H  G. k/ G: z8 @
  864.     /* testing the bit functions */6 W& ?2 I2 |: Q$ {/ b8 g- F% V6 T
  865. #if 0' }, m2 _# p' Q6 w
  866.     int i;5 }9 n/ }6 ]2 ]/ X5 g/ d: j  e5 ]
  867.     uint8_t bytestream[] = { 0x55, 0xAA, 0x00, 0xAA, 0x55, 0x77, 0xFF, 0x1B, 0x70, 0x8F };
    2 r' g) k! Z* q6 H; h. u
  868.     int bytestream_size = 10;, w% W$ V7 o. \" ]% B
  869.     get_bits_context gb;
    * T7 I. e% b' ^/ {
  870.     put_bits_context *pb;
    ; g8 d# i6 [- \1 x5 m
  871.     int bits;
    ( j$ M. D9 U) j1 H# d- X4 T. d
  872. / e  x) p8 ]6 E: o3 I4 z8 P
  873.     init_get_bits(&gb, bytestream, bytestream_size);. Z6 p* L& L. P
  874.     pb = init_put_bits();9 c6 z1 J; n( |' J+ m1 {3 A

  875. + {+ R: k1 Q$ u& e' Z
  876.     for (i = 1; i <= 12; i++)* T; @; k1 a; [& C% K0 t
  877.     {# h2 p# ?: s; @8 L6 B  T
  878.         bits = view_bits(&gb, i);
      T1 A' @' k- a0 @2 o# ~5 w9 a( D
  879.         printf("view %d bits: %d\n", i, bits);
    ) z8 }/ e9 C; }+ N
  880.         printf("read %d bits: %d\n", i, read_bits(&gb, i));
    : L' W$ P  L; y9 _
  881.         put_bits(pb, bits, i);2 q# g, U3 N  \: Q
  882.     }
    - K5 O5 p1 [. j" C# X6 }
  883.     put_bits_flush(pb);
    & R" ^$ o8 V1 U9 s* O( J% q

  884. 8 C* |1 ~( A# J5 n0 F
  885.     printf("original bytestream:\n");
    8 W( q( Y; ^9 K* L
  886.     for (i = 0; i < bytestream_size; i++)
    ; B( ~2 Z2 V: _& z( n
  887.         printf(" %02X", bytestream[i]);) R6 o6 ?* H  {
  888.     printf("\nnewbytestream:\n");" L; g0 L4 i) a6 X$ r
  889.     for (i = 0; i < pb->byte_index; i++)
    / R7 ?( D2 C& M
  890.         printf(" %02X", pb->bytes[i]);% \% Q0 }0 A( k9 j& q
  891.     printf("\n");
    + i" N& s0 }& b, _

  892. # j  H4 u( z" E7 ^+ B0 ^- ~) l
  893.     delete_get_bits(&gb);
    " c- |- G7 M. }; U1 S4 C
  894.     free(pb);
    : U3 r" [! N) m! ~
  895. #endif
    6 D, a% X* ^* F" F. P& ~

  896. & M/ {# Y" o* [6 B5 K5 N$ z
  897.     /* validate the number of arguments */
    + _1 c9 x8 h% {( e) n8 `! Q6 Z
  898.     if (argc != 8 && argc != 9)  u$ s7 Q9 F8 v/ F9 @5 b& r
  899.     {
    $ b+ B% x' R' @' Q
  900.         printf("USAGE: subtitle-rbt <subtitles.ass> <in.rbt> <out.rbt> <origin X> <origin Y> <width> <height> [dump_frames]\n");
    ) D) A! A# a7 M+ i/ n
  901.         return 1;
    + m+ B" C& r& q$ W5 w5 y8 Z
  902.     }) O9 l+ E* y4 @% q2 ]
  903.     subtitle_filename = argv[1];
    4 p1 F7 O' ?* `2 r0 n- g% Y! e; A2 m
  904.     inrbt_filename = argv[2];  Q( V, q% R% R6 k5 l* @
  905.     outrbt_filename = argv[3];
    : G* ~0 ?& ~1 X
  906.     origin_x = atoi(argv[4]);! L9 m/ F; {  ^% I/ \) _
  907.     origin_y = atoi(argv[5]);
    3 p0 W" Q. N8 [" ]2 j
  908.     window_width = atoi(argv[6]);
    9 @0 ?; v3 J* V" |& Z* C  i
  909.     window_height = atoi(argv[7]);$ d) [2 x* S- s* F: h! i9 X
  910.     rbt.dump_frames = 0;" r+ M, b8 {  E5 }
  911.     if (argc == 9)- Z6 F" y( B  T/ _0 G
  912.         rbt.dump_frames = 1;- C$ g7 Z  U- b
  913. 4 f& p, D% A9 H, b4 N
  914.     /* verify that the specified input files are valid */$ M: o7 R- N. Q9 r: q
  915.     subtitle_file = fopen(subtitle_filename, "r");1 O; _( }- K  K6 @% i- U; ]
  916.     if (!subtitle_file)& m; W" J! ]" C* }! R
  917.     {3 Z: X8 h1 B" @0 u* _3 I
  918.         perror(subtitle_filename);/ C" @% C2 X! E  M7 h& o* v# w4 o
  919.         return 1;. G0 K# M- c" p0 J5 X( V' }0 |+ ~
  920.     }
    6 ^- x3 B/ N3 ^2 D% A: M8 k
  921.     fclose(subtitle_file);
    1 N+ n) U- H) o8 I
  922.     inrbt_file = fopen(inrbt_filename, "rb");
    ( v  a: ^& c+ s( y9 l8 I  n1 `- H
  923.     if (!inrbt_file)0 p# M7 {$ p- R1 ?  q
  924.     {
    ! r0 i1 O9 M  P' z; u
  925.         perror(inrbt_filename);1 H6 j5 Z2 w6 @; D' i5 u! y
  926.         return 1;
    2 t  }& S( u) X$ K7 X
  927.     }) D6 G7 x) p( e1 p# J- R8 q0 z
  928. ' H+ _( Q9 G+ Q: I& P0 _. \
  929.     /* initialize the subtitle support */
    . X% u4 D7 |7 i9 h3 g
  930.     rbt.ass_lib = ass_library_init();
    0 {  w; O. {0 v4 ~1 I
  931.     rbt.ass_renderer = ass_renderer_init(rbt.ass_lib);2 h8 z* u/ z3 B8 }; U8 r. c! y
  932.     rbt.ass_track = ass_read_file(rbt.ass_lib, subtitle_filename, "UTF-8");
      }! g! i) N5 c; \% A) x
  933.     ass_set_frame_size(rbt.ass_renderer, window_width, window_height);8 c: S- ]0 ]! j( m
  934.     ass_set_fonts(rbt.ass_renderer, NULL, NULL, 1, NULL, 1);
    ! h' n9 e- p) b9 W; l( `3 R! U& {
  935. ( g. `3 S' _: T& e6 @
  936.     /* open the output file */; y& y8 E7 m* `5 J5 e0 C, F
  937.     outrbt_file = fopen(outrbt_filename, "wb");. _3 p: D- f& n: e9 A
  938.     if (!outrbt_file)
    1 D* O+ w! Z/ N! \0 ?1 |8 g
  939.     {
    0 W- g* L  d; o0 ?
  940.         perror(outrbt_filename);
    " a2 |3 x8 p) q9 _' t1 C
  941.         return 1;9 A  s# }! e. K9 s% P$ W: w
  942.     }1 T- V: l7 D0 u8 \6 }& j
  943. + v6 ^; v* P2 f( \9 O
  944.     /* transfer header from input to output */
    ; R. e+ h; _3 Q& u9 _2 G6 F& x
  945.     if (!load_and_copy_rbt_header(&rbt, inrbt_file, outrbt_file))
    % `; x! }' O  f# Y' S1 V& P! @
  946.         return 1;
    % v+ w2 m2 F0 K

  947.   E: p, R2 M/ J* K; `* w
  948.     /* rewrite the frames */
    6 \7 T6 L2 j3 [$ }* l2 _
  949.     if (!copy_frames(&rbt, inrbt_file, outrbt_file, origin_x, origin_y,
    : R0 ~! [3 l+ z* z
  950.         window_width, window_height))
    2 V" g2 q/ x, H# y7 L5 O
  951.         return 1;
    , V$ V2 J' q; n0 M2 y: Z

  952. / S, N' N# j6 D& q
  953.     /* write the modified frame size tables back to the file */
    ' t. M; \" O/ o8 h& ]5 y2 c5 P) r
  954.     fseek(outrbt_file, rbt.video_frame_size_table_offset, SEEK_SET);4 r) B) l1 i5 W, z9 y
  955.     fwrite(rbt.video_frame_size_table, rbt.frame_count * sizeof(uint16_t), 1, outrbt_file);
    ' ~  E% m7 _  }/ f9 K$ B, z
  956.     fseek(outrbt_file, rbt.frame_size_table_offset, SEEK_SET);
    - l( O) [" R! i) f6 }' a' u; W
  957.     fwrite(rbt.frame_size_table, rbt.frame_count * sizeof(uint16_t), 1, outrbt_file);
    + ~' S9 g! P9 }+ |" V
  958. 0 s" }- h& p2 I0 ?3 d6 C
  959.     /* finished with files */: b, ~  t/ Y/ K
  960.     fclose(inrbt_file);
    & x0 g$ w  A1 V( q7 ~; [5 G
  961.     fclose(outrbt_file);
    ( O. b4 g# u4 j/ A) I0 {! a/ _

  962. & A! O! w$ S3 y' Y+ u% l" ^
  963.     /* clean up subtitle library */
    3 x5 U  q+ o: _& `5 l% }9 {" b# v
  964.     ass_free_track(rbt.ass_track);
    ! o: t- K2 V. R) O9 V% N# n9 i
  965.     ass_renderer_done(rbt.ass_renderer);6 W8 E4 t2 }2 S7 Q3 k+ v( k- M7 E7 F3 B; ~
  966.     ass_library_done(rbt.ass_lib);
    " q3 o% a; |2 u: r$ l+ H
  967. 0 W: [4 ]* {  p
  968.     /* clean up */
    * J% z8 d* C4 Z& C2 u1 e1 Y, s
  969.     free(rbt.frame_load_buffer);
    ) c! ], z1 a4 k. ?. d7 |& h* t
  970.     free(rbt.video_frame_size_table);! g; n+ Q* l3 A' H* q6 c
  971.     free(rbt.frame_size_table);
    0 m) b* q- M( k0 {
  972. & j  ~# i3 T( v0 h" @  E: K- A2 g0 `3 D
  973.     return 0;& z5 P5 N# y1 u  U
  974. }
复制代码

5 [% i& Z8 T- @) ~% P, C$ Q1 k7 l

0 U* S; u5 K, V: Z; n
- d- d, x5 ^% N  @3 E
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 很美好很美好 很差劲很差劲
回复

使用道具 举报

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

使用道具 举报

板凳
 楼主| 发表于 2009-11-19 11:38 | 只看该作者
引用第1楼soring123于2009-11-19 11:09发表的  :0 z! p5 W# X# O1 {9 e
这游戏有字幕吗?

4 C* V: a% V: ]! n7 K好像没有字幕,我说的是给视频外挂字幕方式的汉化。
! m8 F  p$ C  G& k9 }就像syberia2汉化版下面那行字一样。
回复 支持 反对

使用道具 举报

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

使用道具 举报

5#
 楼主| 发表于 2009-11-19 17:39 | 只看该作者
引用第3楼soring123于2009-11-19 17:07发表的  :7 B3 a. r) }  U/ @7 [$ r: U$ m+ B6 i
我记得是没字幕的 比较麻烦 都是视频的
8 r$ s- T/ n6 M1 ]6 }) l
给视频外挂字幕方式汉化也许能行。/ O* m6 X' b( e8 P  D
要结合dosbox和代理dll技术。
回复 支持 反对

使用道具 举报

6#
发表于 2016-7-21 23:33 | 只看该作者
求汉化啊!
回复

使用道具 举报

7#
 楼主| 发表于 2021-1-2 13:50 | 只看该作者
顶上来
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

冒险解谜游戏中文网 ChinaAVG

官方微博官方微信号小黑屋 微信玩家群  

(C) ChinaAVG 2004 - 2019 All Right Reserved. Powered by Discuz! X3.2
辽ICP备11008827号 | 桂公网安备 45010702000051号

冒险,与你同在。 冒险解谜游戏中文网ChinaAVG诞生于2004年9月9日,是全球华人共同的冒险解谜类游戏家园。我们致力于提供各类冒险游戏资讯供大家学习交流。本站所有资源均不用于商业用途。

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