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

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

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

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

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

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

本帖最后由 shane007 于 2021-1-2 13:56 编辑
* _0 a" ~$ e0 M1 g& z. |: Z: }
# P6 @+ d4 F6 T0 _+ A' X最近找到了一些和幽魂系列Phantasmagoria 有关的资料,
+ \2 ]6 p7 z$ y& A  n" w也许将来可以用于汉化。
3 n6 N7 r$ v$ D* W5 A5 \& s
* h( i' ^' q/ k  @- `和日文版有关的信息8 ], q9 w  I* E0 ]) w/ S5 X  R/ O
http://anthonylarme.tripod.com/phantas/phintgtp.html
" N3 {  a0 J: k$ t; p% o2 e' ]7 V% H( |! e, t+ q  B
相关工具
0 K% n% P1 I# y" B7 F" S" u+ mhttp://anthonylarme.tripod.com/phantas/phcheats.html% j3 [9 {7 q8 l9 T  {' k
-----------------------------------------------------------------------& h1 M% b- M& Y  P% {  Q# I
2012/1/2  更新
% `2 W- h( m: z3 `9 C关于幽魂游戏的字幕/ D% W; m$ c. Z5 W6 L& I
Phantasmagoria subtitles function discovered - ScummVM :: Forums% W, p9 j: R8 s' F  P1 P, ]( c) ^, D

1 n& ^# Y8 y! |! ^& W( R7 zVMD文件
/ v8 C9 X) c+ T- s# t) Q2 `: PSubtitling Sierra VMD Files | Breaking Eggs And Making Omelettes (multimedia.cx)VMD - MultimediaWiki
4 T/ `! `' W1 D3 G8 p7 t; f+ \! r6 K8 |' G7 _5 j, e
字幕# r# M+ ^4 z/ E
Subtitling Sierra RBT Files | Breaking Eggs And Making Omelettes (multimedia.cx)3 B# g& a2 @$ X- |, f( p! g5 d

) Z$ @: I' }3 q5 k" uFFmpeg/subtitle-rbt.c at feature/VMD_encoder · multimediamike/FFmpeg · GitHub# {2 d/ L) T  y7 p. L7 z# v/ Y
  1. /*
    # G! u6 X+ S$ X
  2. * subtitle-rbt.c) T+ K9 e% k! V4 C7 q* @
  3. *  by Mike Melanson (mike -at- multimedia.cx)
    + m6 M+ d& i/ x" J. p
  4. *
    6 R5 `0 \5 T7 _. J- ~
  5. * build with this command:; T" r9 Q  O9 M" J/ S5 s
  6. *   gcc -g -Wall subtitle-rbt.c -o subtitle-rbt -lm -lass2 R1 ]8 U, w4 d: S
  7. */: w* [! w! J. X% \1 T* E

  8. ' X* C7 ^% h/ t% _: X( Q* r) X
  9. #include <inttypes.h>
    + s4 K# t% Z2 _) N! [! D
  10. #include <math.h>
    : H* [! k! \2 Q: e  ~' ~
  11. #include <stdio.h>
    ; h9 B' R4 ?) o0 G) f$ d
  12. #include <stdlib.h>
    ; P4 l7 {& z8 s/ `
  13. #include <string.h>( ]2 g0 N4 Q' k7 {, F

  14. 0 p6 N; r( b$ f: ^$ q
  15. #include <ass/ass.h>
    & z; h. ]% j* c* Q/ a

  16. 1 T' _; \, q1 f5 @" B% J: G
  17. #define LE_16(x) ((((uint8_t*)(x))[1] <<  8) | ((uint8_t*)(x))[0])
    / D5 Z' J# M' n: d8 y3 Z& o( n' \

  18. # E% s2 m# ^! I& p
  19. #define LE_32(x) (((uint32_t)(((uint8_t*)(x))[3]) << 24) |  \! g+ q2 A3 ^% r3 t7 t1 _8 D. }
  20.                              (((uint8_t*)(x))[2]  << 16) |  \. k/ E) e4 S+ o" d+ v
  21.                              (((uint8_t*)(x))[1]  <<  8) |  \" n. h4 U  o. }* ~5 l$ m
  22.                               ((uint8_t*)(x))[0])- p8 y' Z7 `8 p, W
  23. ! F1 t8 J9 |8 z
  24. /*********************************************************************/
    9 t/ R! D6 X, L& m/ v0 K

  25. , N% j+ p  K  ]4 N- A" ~
  26. /* Bit reader stuff */% K) O2 O% u2 L; A8 ^7 e3 d

  27.   L& u2 Q( ~( B" V2 Q2 F
  28. typedef struct
    " v: b# o! M6 b2 w$ u) I
  29. {
    * ~) m& d/ B  c! p! \
  30.     uint8_t *bytestream;
    1 \6 B$ _1 M* c: P! r
  31.     int bytestream_size;
    ) [* h6 o1 e5 T; U. q4 k9 t& q
  32.     int index;" a: s7 T: {0 a9 N- u' _  P9 x
  33.     uint32_t bits;
    $ i$ n2 t6 q) J8 f7 c, k
  34.     int bits_in_buffer;) W$ T% e4 }- D2 i' v( ?
  35. } get_bits_context;5 X. d* h, B; h! ?$ a% m

  36. % Q6 A5 ^  W! r+ J( P) x
  37. static inline void reload_bits(get_bits_context *gb)0 L5 S1 v2 R# l7 C. e
  38. {. E% M" T& K- }# c+ C/ |
  39.     while (gb->bits_in_buffer <= 24)1 d, _& {3 Q. f; g; p' k
  40.     {, j2 d' I) ]  i: T4 W# R
  41.         if (gb->index < gb->bytestream_size)
    ! ~. P+ W& l0 K- ~' C* Q. }
  42.             gb->bits |= (gb->bytestream[gb->index++] << (24 - gb->bits_in_buffer));' k6 [" L& Z( w; y
  43.         gb->bits_in_buffer += 8;
    5 L( \* N& }& \* j% s" K" I
  44.     }& S7 r9 s. c; r4 v* D2 Y3 j
  45. }/ x5 C* v/ y4 z8 m' u
  46. $ X8 I. |, F0 @6 _( P( B
  47. static void init_get_bits(get_bits_context *gb, uint8_t *bytestream, int size)
    + z0 V- b( h/ p( X+ R' X# _
  48. {
    * J: t1 h; V, T8 c: s
  49.     gb->bytestream = malloc(size);
    ' x# c% x* U% j. y& r, Y
  50.     memcpy(gb->bytestream, bytestream, size);
    & L1 d9 U# z4 `( l( H" @: b
  51.     gb->bytestream_size = size;
    , _( Y3 `) F1 L9 d! P$ [
  52.     gb->index = 0;
    ' e/ [6 l" O7 |) |, y, ^& L, H* }
  53.     gb->bits = 0;/ q, N& y! J) @8 N: j' j. m
  54.     gb->bits_in_buffer = 0;
    # y' Y  e- O+ }0 t! }
  55. 1 p! N) p& m6 F6 s
  56.     reload_bits(gb);. `; U9 a- }5 x2 ]( V( d
  57. }
    % t1 G: s( t7 W& s; Z

  58. - a9 z  Y$ B' G
  59. /* read bits without consuming them from the stream */* r% G4 z( }# Z! f
  60. static int view_bits(get_bits_context *gb, int count)
    % ]2 z# B7 M; s" j, b
  61. {
    1 J' v. M) ^* [, Y4 k
  62.     if (count >= 24)2 b1 _8 }9 f6 w7 F7 a
  63.         return -1;
    + w  q2 t" \9 f) G( q1 `
  64.     if (gb->bits_in_buffer < count)" n% g- @# A' e
  65.         reload_bits(gb);# o; S) G( o4 C& t- c* a% V
  66.     return (gb->bits >> (32 - count));
    ' }' ]2 n, t: U, e4 I5 z3 z
  67. }
    # s6 U- E+ M4 Y4 `8 C, T

  68.   |$ y3 b" z$ M6 v9 J" F. j7 a
  69. /* read and consume bits from the stream */
      ^: K$ z% R- ]6 G
  70. static int read_bits(get_bits_context *gb, int count)
    $ N- T* C8 h% s, F" x
  71. {
    0 N; V4 U6 X' @  Z; |7 \
  72.     int value;
    ; w* t8 S5 C" F# V2 q( d2 u

  73. & z' h$ U8 R: ?5 @
  74.     if (count >= 24)3 O1 y# ]0 u" A# @2 L! z2 D: }( [
  75.         return -1;5 n: `( L# L- c* y, y6 I5 `/ J
  76. - E/ q) k; f0 Y6 K5 M7 J8 y
  77.     value = view_bits(gb, count);, \1 s2 B! W9 N  j% a3 [- H& [
  78.     gb->bits <<= count;1 m3 y, s0 H/ C( i* g# _5 I
  79.     gb->bits_in_buffer -= count;$ `# d3 @- V6 ^4 M! h0 Q
  80. * K# @9 N! j" ]; Q, b7 X$ s
  81.     return value;
    ) `% f3 `/ n% i/ W
  82. }
    ) H/ l2 i5 Z) Q' a4 n! z1 V
  83. $ B( r) C: j, H
  84. static void delete_get_bits(get_bits_context *gb)
    8 E2 M. E5 V) H+ F  B, M+ q( \
  85. {  }# p% ~8 q  h: D) j; b
  86.     free(gb->bytestream);. w$ j* g& Q6 P9 I8 i; M# G2 X7 J
  87. }% |, M3 C# F# a) ^
  88. 0 p" `9 `5 O6 h# d* t+ f
  89. /*********************************************************************/$ l1 T& H& K& v' i" A+ i9 q

  90. " d& e- p! e6 J1 Q/ c+ O$ g, k' }
  91. /* Bit writer stuff *// N4 `3 a  K: R/ g+ {; F+ \
  92. * Y8 }4 I8 A: l7 ]% H( b
  93. #define MAX_PUT_BITS_BYTES 63000. R8 S  ~$ `8 ?( a8 B' f
  94. typedef struct$ V7 ~2 E$ G% Z, Q7 B6 p
  95. {  O5 B/ G& v9 B0 j  Q0 @
  96.     uint8_t bytes[MAX_PUT_BITS_BYTES];( y. a6 W4 O! l6 w
  97.     int byte_index;
    # g9 p4 m* e% z
  98.     uint32_t bit_buffer;  S1 g/ o; N- y! Z+ |3 x# J- H8 J
  99.     int bits_buffered;
    8 A7 N7 Y/ \2 `! L4 _* ?+ \
  100. } put_bits_context;' t" G0 s8 W5 _
  101. - N" O* {' B# T. B# Z4 @2 i
  102. static void reset_put_bits(put_bits_context *pb)
    5 a1 Y0 o# l3 w2 ?1 W+ \1 g, G0 z
  103. {
    4 K; T8 H2 H4 D8 d- m1 `" H
  104.     memset(pb->bytes, 0, MAX_PUT_BITS_BYTES);' r+ S+ E; B/ `  J; {1 V
  105.     pb->byte_index = 0;! _9 O4 Z" J- X, H. Y! S
  106.     pb->bit_buffer = 0;
    8 g) y7 U( q' o3 y/ U# ?4 l
  107.     pb->bits_buffered = 0;
    ( y9 z+ S8 @% `: u+ _/ n7 ~& {
  108. }
    1 s8 Q/ G7 Q+ X& T

  109. - y# J7 ~6 N7 i4 ?3 C! T
  110. static put_bits_context *init_put_bits()9 p: F! ~% \" S
  111. {
    / ~- @3 h; O1 I' _$ ^
  112.     put_bits_context *pb;0 ~; d* W& e7 j3 {

  113. % x. q: T+ C: d' o/ I7 W& {
  114.     pb = malloc(sizeof(put_bits_context));
    4 Y7 T- u  ^, X) Y  p) Z
  115.     reset_put_bits(pb);* a1 S) y: z- n) n& A6 p5 H$ H

  116. 8 d# l9 a; b- v! L: l
  117.     return pb;1 W, C. Y5 U2 D6 e. V9 A& j
  118. }
    / X' f  j$ @9 ~7 p# M# R4 N8 X
  119. 2 f; g1 L  M! r9 e; C/ u; T
  120. static void put_bits(put_bits_context *pb, int bits, int count)$ l" c0 H7 C- f3 |) |
  121. {
    ' P3 ]4 }9 ~0 J" h
  122.     pb->bit_buffer <<= count;
    $ X& e' s" C2 d1 C, k
  123.     pb->bit_buffer |= (bits & (~(0xFFFFFFFF << count)));+ l# h2 J8 n' W; ^( v, z
  124.     pb->bits_buffered += count;
    % P" E" [0 l  E4 |$ W

  125. , Z3 Q) e# j) {8 e* N. m4 A, [
  126.     while (pb->bits_buffered >= 8)
    3 A% q$ ?! P* R
  127.     {
    ( M. ~) v. J* i# H) x
  128.         pb->bytes[pb->byte_index++] = pb->bit_buffer >> (pb->bits_buffered - 8);
    + |" ~  S; p6 ^+ t, O
  129.         pb->bit_buffer &= (~(0xFFFFFFFF << (pb->bits_buffered - 8)));1 P9 I& p8 I# W
  130.         pb->bits_buffered -= 8;
    ; M( D% k! g" F  T: l+ s$ y
  131.     }" t- o: ], r5 Q7 ]
  132. 9 m# W. c+ ]; z& x, A
  133.     if (pb->byte_index >= MAX_PUT_BITS_BYTES)) D/ k6 j1 T3 _/ G* H/ D
  134.     {; {/ Z' r% \5 l8 z5 a! Z% j6 R
  135.         printf("HELP! Bit overflow\n");
    + z0 _8 c6 W6 c) l/ f- V
  136.         exit(1);
    9 z- J3 F) i0 W. O% b8 t( m
  137.     }
    ; ?2 ]1 Y* g- E9 c" a8 s1 E
  138. }! @  ]# C8 v  a; K
  139. : \% h! Y- `: }& z
  140. static void put_bits_flush(put_bits_context *pb)- Z8 a. s5 E0 }  N
  141. {1 L% y, b$ v7 C: j& Z: S) e4 f
  142.     if (pb->bits_buffered > 0)
    4 Q- \, e$ n8 W/ ^- A1 I
  143.         pb->bytes[pb->byte_index++] = pb->bit_buffer << (8 - pb->bits_buffered);
    4 k7 C$ @' F6 Q7 R; x
  144. }' t/ W! [5 i/ ^  U1 s" t3 |8 x
  145. & J0 x0 o4 u/ h) K& K+ w( n
  146. static void delete_put_bits(put_bits_context *pb)
    ) A/ s# Z/ Q% B+ l
  147. {
    8 ?9 F' k" G2 h
  148.     free(pb->bytes);9 D5 M; p3 o0 V* {$ h$ O4 q
  149. }6 x: M& b1 ~, |3 W

  150. 7 e8 n' F' J5 \5 |
  151. /*********************************************************************/: _) z" l; p( U1 g5 G  h
  152. 7 v5 H) j+ G6 Z4 k' O
  153. /* RBT functions */( c  j0 B+ g2 L# |  K

  154. 0 J" T6 N* n9 k/ j& H
  155. #define PALETTE_COUNT 256
    ; c$ q- s! w- P  i' W, V; U+ c
  156. #define RBT_HEADER_SIZE 60
    4 c7 u* G' S( w( B" J" y( |( W8 H
  157. #define UNKNOWN_TABLE_SIZE (1024+512)
    2 M/ A; z9 D* T  K; n& {; S! Z  |
  158. #define SUBTITLE_THRESHOLD 0x70
    ' w  l" D/ i3 n6 Y5 X) f
  159. #define MILLISECONDS_PER_FRAME 100
    1 d' W" Y6 V/ M' R# q7 Y
  160. : U8 \  F9 K4 U7 |6 x
  161. /* VLC table */5 \' }4 l6 Y$ p6 V9 m; s2 P
  162. #define VLC_SIZE 4
    " X0 ~  m$ Y1 P# y" U  I8 f) p
  163. static struct3 c) W1 N# B' G2 W+ j& {/ o; @
  164. {
    ) E5 ^4 L! q1 P8 {0 }8 {; ^/ W
  165.     int count;1 s9 ]6 K" y: N# R8 [
  166.     int value;! s: _. a. A) e; {
  167. } lzs_vlc_table[] =
    9 `9 o( k) C2 p1 E' B7 A
  168. {
    0 d8 I; N- l/ Y: k6 g* _6 ~
  169.     /* code length = 2 bits; value = 2 */
    8 \/ |2 F" {' A/ _+ Y! v+ ~  D
  170.     /* 0000 */ { 2, 2 },* d1 U8 y: \8 G
  171.     /* 0001 */ { 2, 2 },
    7 Q  r0 r, n" F8 J' U' ?
  172.     /* 0010 */ { 2, 2 },2 T! E' R" r2 ?' I
  173.     /* 0011 */ { 2, 2 },
    ! J" z! q7 y  G
  174. , `. z6 j( X- \3 A/ _, ^( A
  175.     /* code length = 2 bits; value = 3 */
    ( |3 i; H) X2 P  J7 _
  176.     /* 0100 */ { 2, 3 },
    + B' W) F& C, G- P  X; e+ Y. w; A* e
  177.     /* 0101 */ { 2, 3 },2 q4 u$ f$ Q5 ~( D- A" ^, U
  178.     /* 0110 */ { 2, 3 },
    ; b; {* w( t; R" F* _, R5 U
  179.     /* 0111 */ { 2, 3 },+ n! V/ b' T- G2 e) @7 i

  180. * x6 s  \, q/ V7 L
  181.     /* code length = 2 bits; value = 4 */
    ! Y& y$ X3 h/ w9 Y
  182.     /* 1000 */ { 2, 4 },# k% a% k- n8 |6 @, X) Y/ c
  183.     /* 1001 */ { 2, 4 },9 t% a, q/ a& p, w! \- f
  184.     /* 1010 */ { 2, 4 },4 f% O1 D6 A& f$ ]9 `( t" c5 w
  185.     /* 1011 */ { 2, 4 },6 u" H, }% @+ O: `; J. N
  186. 6 T/ I- W' u, h) u$ b
  187.     /* code length = 4 bits; value = 5 */6 _" q$ s0 M: \
  188.     /* 1100 */ { 4, 5 },7 `6 [$ q6 g5 t2 f; i: g

  189.   k  T) ~3 E8 B7 J! @
  190.     /* code length = 4 bits; value = 6 */
    4 w2 \# F7 C8 h
  191.     /* 1101 */ { 4, 6 },
    5 ^5 S6 a# J  @
  192. 7 P* }; d" O# ~/ }* A
  193.     /* code length = 4 bits; value = 7 */
    0 S# Q% V6 ^) H! F% C" n
  194.     /* 1110 */ { 4, 7 },/ x( u" M4 V( z, e' R& ^- ?

  195. : A/ f# x" E5 i
  196.     /* special case */) k4 N( g$ _( e, N2 U
  197.     /* 1111 */ { 4, 8 }/ y0 e/ X7 l; D* Y8 I/ ?
  198. };1 h' ^% e3 S3 {1 I

  199. 3 ^8 `# D. R: e2 ~
  200. typedef struct
    * M2 F9 a% s; ~: u/ z& N4 A+ H9 e2 G1 _
  201. {
    , W) D1 ~& B7 F- R2 y' }
  202.     int version;# |; }' I* G( \8 T% j' X  x
  203.     int width;
    5 g6 |) I5 j+ d( [/ F
  204.     int height;+ s. B/ m; G% Y/ f5 `1 ^
  205.     int frame_count;
      v+ m/ u# O4 n) {7 `
  206.     int audio_chunk_size;
    # h- ]- _$ Y8 W& c
  207.     uint8_t palette[PALETTE_COUNT * 3];1 r( ?! R$ G" N9 U
  208.     off_t video_frame_size_table_offset;
    , A; y6 \/ @- d5 H' n' [: A
  209.     uint8_t *video_frame_size_table;
    / w) W5 y8 [" ?- M, V
  210.     off_t frame_size_table_offset;
    + p! i+ f. v3 n* h
  211.     uint8_t *frame_size_table;& _- z5 v$ O' e
  212.     uint8_t *frame_load_buffer;( p# n. h; E9 Z- I+ R
  213.     int dump_frames;: z) U6 u4 y1 V$ M7 l
  214. / j6 Z& h0 \" h* T( ?
  215.     /* subtitle library */9 T0 T9 g1 U9 o7 h
  216.     ASS_Library *ass_lib;
    % N6 t6 ~; E0 Z0 X  x2 M
  217.     ASS_Renderer *ass_renderer;
    # \4 h: S( I" K2 T
  218.     ASS_Track *ass_track;; J/ h1 N5 o0 h: C' }
  219. } rbt_dec_context;
    ( u' y1 r# h$ t$ c- \4 h7 N
  220. . `* f8 m5 ~! B; s1 T+ y9 _
  221. static void dump_pnm_file(char *filename, rbt_dec_context *rbt,1 d; ~7 b: z: H" f% u2 Z* w' K
  222.     uint8_t *image, int width, int height)( z& l) ~! S3 {9 T
  223. {: s6 h- |( ]3 J' Y% a
  224.     FILE *outfile;
    ! n! n0 |3 Y' K: c" ^* q' B
  225.     uint8_t bytes[3];
    / Q& a; x( J8 R$ i
  226.     int p;
    3 |$ |/ p6 b) I& o7 q
  227.     uint8_t pixel;: S5 n: ]: V. E/ \6 w
  228. 7 z& s/ }/ C0 K) Y  _, l8 u" s& l& I
  229.     outfile = fopen(filename, "wb");
    " Z5 A; r$ N3 n% }$ t/ _$ R
  230.     fprintf(outfile, "P6\n%d %d\n255\n", width, height);/ W$ f% O. _4 |1 v
  231.     for (p = 0; p < width * height; p++)! |& }: f5 Y8 ^
  232.     {2 z& L0 w0 |! R7 Y0 I
  233.         pixel = image[p];
    & K) s! }+ G! }6 e4 C5 d* O
  234.         bytes[0] = rbt->palette[pixel*3+0];% E7 p" S* b: n+ m, U
  235.         bytes[1] = rbt->palette[pixel*3+1];
      w' G, d  k* y; b; O$ k/ k
  236.         bytes[2] = rbt->palette[pixel*3+2];
    4 p5 b6 f: S; [# y; P# D
  237.         fwrite(bytes, 3, 1, outfile);
    ; m1 S9 q6 c5 f3 L$ A5 I3 m
  238.     }8 A1 A* O7 n- a4 O
  239.     fclose(outfile);
    & b5 m' ~5 f5 O- J  o
  240. }
      N, l% y4 v7 V% F2 g5 [
  241. 0 o1 C2 @% }3 q  g
  242. static int load_and_copy_rbt_header(rbt_dec_context *rbt, FILE *inrbt_file, FILE *outrbt_file)9 n/ z# B' c! C- G
  243. {
    6 k+ d9 ?8 O& p$ l0 p9 v
  244.     uint8_t header[RBT_HEADER_SIZE];
    . F# B9 c7 T' z$ S
  245.     int palette_data_size;! b8 Y" y* w% }# o5 M
  246.     uint8_t *palette_chunk;
      Z4 V: r. H& |
  247.     int unknown_chunk_size;
      e2 a+ }% P9 u. Z% T& F" w! x. L9 Z
  248.     uint8_t *unknown_chunk;
    & I. ?- P. A. K
  249.     uint8_t unknown_table[UNKNOWN_TABLE_SIZE];
    ' `: M/ Z+ k5 i% H. r/ m5 I
  250.     off_t padding_size;, n7 ^/ g2 ?5 k( s  Y
  251.     uint8_t *padding;
    ) N2 A& O$ H* X7 [
  252.     int i;
    5 R- a1 `; {; b6 x
  253.     int frame_size;3 i# ]5 O' d% `: Y
  254.     int max_frame_size;
    ( S  y. w3 q9 B; o: ]8 g6 \
  255.     int first_palette_index;
    " ?' H# n7 z) u6 v
  256.     int palette_count;8 c+ b  _& I! e( [5 ]1 I
  257.     int palette_type;
    4 z; \$ x5 L0 y: @* {% w  T
  258.     int palette_index;6 z( @2 v$ \' T" g& y
  259. " x" |* H# L& p/ _2 ^. N% M
  260.     fseek(inrbt_file, 0, SEEK_SET);
    6 x4 N( K( {5 h; O( n
  261.     fseek(outrbt_file, 0, SEEK_SET);, j( h' ]. L& I& V  b: @

  262. # M' l- ~: G- X, Z# }* \6 K7 T
  263.     /* load the header */
    7 `; |, n) m+ k3 Y' U( e- d
  264.     if (fread(header, RBT_HEADER_SIZE, 1, inrbt_file) != 1)
    " W4 G6 Y8 N5 G
  265.     {
    ! g0 U  A% w! `6 I6 W* z
  266.         printf("problem reading initial RBT header\n");6 \. z! J! k5 O; c. |; M# J
  267.         return 0;) w+ V5 @9 |8 n, ]3 ?0 m* x
  268.     }
    0 {4 `6 M  c* X! W( G0 H
  269. 1 c7 c% k$ e! a/ Q- E3 N2 @0 a4 O
  270.     /* copy header to the output */
    $ O4 D! C9 q5 s; ^$ z. z
  271.     if (fwrite(header, RBT_HEADER_SIZE, 1, outrbt_file) != 1)% E* r, v% r( I; [
  272.     {
    , T. e9 V, r, @: x) Z4 W4 O8 {
  273.         printf("problem writing initial RBT header\n");9 l9 B8 t) r; W; O
  274.         return 0;, K: j4 b: L8 W- k9 t. w
  275.     }
    ; t) Q0 N1 S8 U( U3 k- T) S4 M

  276. 5 c1 @2 e9 Z6 D2 M. @
  277.     rbt->version = LE_16(&header[6]);( ~; S* U+ I: N0 l) ]' ?
  278.     rbt->audio_chunk_size = LE_16(&header[8]);; f1 ^  @6 {: a
  279.     rbt->frame_count = LE_16(&header[14]);
    2 _4 N3 [9 y/ i0 p1 _" v# L

  280. + a4 u) A  ]$ L; V( M9 e: x
  281.     /* transfer the unknown data, if it's there */1 y& \! J: Z* O) H. |( q1 a
  282.     unknown_chunk_size = LE_16(&header[18]);
    0 S$ |2 e# H) @# I& w( t) O9 K
  283.     if (unknown_chunk_size > 0)
    # q& z8 q- P0 _8 i5 p) j* k7 [
  284.     {
    $ y6 g+ P/ j- K2 D" T( X+ ~
  285.         unknown_chunk = malloc(unknown_chunk_size);
    0 ~. ?) K/ p+ M8 u; n
  286.         if (fread(unknown_chunk, unknown_chunk_size, 1, inrbt_file) != 1)
    . U" F% p* s: d) _6 ~
  287.         {
    . U; B. [( S5 r$ Y4 f  t+ r
  288.             printf("problem reading unknown data\n");5 B: L; B6 r8 c# {+ |
  289.             return 0;* B! d: P0 Y, Y, c
  290.         }
    1 V; i) Z: N: \6 g* g; P
  291.         if (fwrite(unknown_chunk, unknown_chunk_size, 1, outrbt_file) != 1)4 M: k# }# z' }/ j; l" M$ c( I
  292.         {* W9 v# n) {3 U* _
  293.             printf("problem writing unknown data\n");  E0 u1 c0 k' O
  294.             return 0;  m+ q9 I: J/ L5 V, n* Y) c
  295.         }+ v3 ?/ R7 g6 ?% [0 R
  296.         free(unknown_chunk);
    ; i+ [" Z5 P) b; Y+ g
  297.     }
    9 d+ i/ i2 d* e# C

  298. 0 _1 d1 B" ^. R5 `
  299.     /* transfer the palette chunk */
    8 n! ?* e4 B4 l9 _, Z
  300.     palette_data_size = LE_16(&header[16]);% R4 p3 C- j( N" J$ R
  301.     palette_chunk = malloc(palette_data_size);
    ( G- s8 X1 d) ?
  302.     if (fread(palette_chunk, palette_data_size, 1, inrbt_file) != 1)- U) o& c4 g. L8 h+ d3 H2 Q. A: w
  303.     {
    - h& L' X0 o7 a: z9 n. y) x" C
  304.         printf("problem reading palette\n");
    ( R% n" }* v2 V$ @: F
  305.         return 0;* j8 c. z& f% N4 \+ H+ w9 Z0 w
  306.     }2 d6 B6 ]3 S7 J: v8 c
  307.     if (fwrite(palette_chunk, palette_data_size, 1, outrbt_file) != 1)8 {% A1 A3 O7 t8 `
  308.     {; z% b6 K4 \; P0 j6 _) Q
  309.         printf("problem writing palette\n");
    * x. H0 x  g0 K) K# X$ z
  310.         return 0;
    . b4 ^! B- u8 f% Z
  311.     }4 z" R! q6 `3 @+ ]" Z
  312.     /* load the palette into the internal context */" _) P: p5 n: Y( A8 y9 ~7 q0 W* ?
  313.     memset(rbt->palette, 0, PALETTE_COUNT * 3);
    ; T7 q5 V+ j7 Z
  314.     first_palette_index = palette_chunk[25];; d# H) e# k9 L0 V1 @
  315.     palette_count = LE_16(&palette_chunk[29]);
    # z* H" @) O: i% \
  316.     palette_type = palette_chunk[32];
    2 r( q" X7 q* i' a9 n# ]$ }
  317.     palette_index = (palette_type == 0) ? 38 : 37;" x' |+ f, h# L( W( N! P0 e
  318.     for (i = first_palette_index; i < first_palette_index + palette_count; i++)
    / {! C8 q& Q/ j1 ^# H8 H
  319.     {! W0 |+ @- x& ]* ^! I! Y
  320.         rbt->palette[i*3+0] = palette_chunk[palette_index++];
    + `; ]$ g9 D5 z, b5 S
  321.         rbt->palette[i*3+1] = palette_chunk[palette_index++];1 w3 F1 z/ G  s' I" }( U! g- v  n3 i
  322.         rbt->palette[i*3+2] = palette_chunk[palette_index++];* ~% p) X# m! J+ j$ ~& ?; d# c6 @6 W3 p
  323.     }0 N! a2 X. {# `5 z- o
  324.     free(palette_chunk);
    0 A  ]3 z5 Z9 Z! V( \
  325. " b) B; Y5 [5 j1 f4 M
  326.     /* copy the video frame size table (2 bytes per frame), as a placeholder */
    & I5 f2 q5 O: S- o. U9 q% u
  327.     rbt->video_frame_size_table = malloc(rbt->frame_count * sizeof(uint16_t));1 D" C0 X1 j  w$ K
  328.     if (fread(rbt->video_frame_size_table, rbt->frame_count * sizeof(uint16_t), 1, inrbt_file) != 1)
    $ N! u0 l) z8 m
  329.     {& J* `, n! [, }/ p5 s3 }
  330.         printf("problem reading frame table\n");' V$ ^3 m/ j* M4 Y
  331.         return 0;
    ( f5 q9 I* r. H5 u7 o
  332.     }
    4 y( d; O4 o4 C) V- @; n# a* }5 h
  333.     rbt->video_frame_size_table_offset = ftell(outrbt_file);: ?. ?2 I- {5 R7 C
  334.     if (fwrite(rbt->video_frame_size_table, rbt->frame_count * sizeof(uint16_t), 1, outrbt_file) != 1)" Y0 U5 y& l9 C6 q* s2 S! B
  335.     {
    5 ]* C% k. S- _  v, x
  336.         printf("problem writing frame table\n");
    5 e! O3 ~6 Y* @$ Q- W8 p
  337.         return 0;
    ! Z- J: p  I- v; Z
  338.     }/ z) U9 }- ^& V( |
  339. . ^6 T6 O9 N" e! U
  340.     /* copy the frame size table (2 bytes per frame), as a placeholder */+ ^# u% m1 V5 D0 q5 a
  341.     rbt->frame_size_table = malloc(rbt->frame_count * sizeof(uint16_t));
    3 a  ?1 @) x; B$ n) F, b8 f# t! P& g+ g
  342.     if (fread(rbt->frame_size_table, rbt->frame_count * sizeof(uint16_t), 1, inrbt_file) != 1)6 L& |; S# I1 ~3 H, P
  343.     {
    , l7 R8 [7 n/ [0 ]; Z! l5 N- a
  344.         printf("problem reading frame table\n");, C. l( J- x2 r8 {$ c0 s7 L
  345.         return 0;
    ' f. {  ~  k/ A8 R; M2 q. B
  346.     }
    * u( h: A5 l. s7 @( ^) W- O: N6 k
  347.     rbt->frame_size_table_offset = ftell(outrbt_file);
    , v: l+ v  M6 e% F0 i
  348.     if (fwrite(rbt->frame_size_table, rbt->frame_count * sizeof(uint16_t), 1, outrbt_file) != 1); \/ x. T; \. m$ g8 \9 Y0 r! l3 c
  349.     {
    4 r. a0 K( k0 E" @6 {) D4 U
  350.         printf("problem writing frame table\n");
    7 M" M# ^, T# o% Z3 X
  351.         return 0;
    , u* c$ I8 o" T' X' d3 C: M% C
  352.     }
    , S6 n# z6 e' n, |! o% c
  353. ; ?# ?( b/ z2 X
  354.     /* find the max frame size */
    # g. }+ c6 }% h( J
  355.     max_frame_size = 0;
    7 f' A8 d( c: i! Z0 P5 a/ Y
  356.     for (i = 0; i < rbt->frame_count; i++)
    * i$ K3 o/ L& P; z, c+ L9 g
  357.     {2 D+ }3 ]2 [7 I% g1 N
  358.         frame_size = LE_16(&rbt->frame_size_table[i*2]);
    , a2 B0 J" P" @7 G7 s* V
  359.         if (frame_size > max_frame_size)
    # t% [" a* T8 d* r+ U
  360.             max_frame_size = frame_size;+ l( c4 U* s( Z4 D! k, Q
  361.     }
    , {1 [; x. [7 [! H5 |
  362.     rbt->frame_load_buffer = malloc(max_frame_size);3 q! J( ~. p+ k5 w6 L/ d
  363. % ^; S$ L% I5 a) \* y
  364.     /* transfer the unknown table(s) */3 _. A" f  d- }- ~
  365.     if (fread(unknown_table, UNKNOWN_TABLE_SIZE, 1, inrbt_file) != 1)# ^& N# e6 v  q% }! z
  366.     {* L2 \' @1 B( M3 i
  367.         printf("problem reading unknown table\n");
    6 S3 v& I! I8 e7 |- M! Y. I& P
  368.         return 0;
    + r; W7 l, D" t5 y$ s4 Z4 z
  369.     }
    ( q3 K$ }2 h3 O6 X! V& h) _+ z
  370.     if (fwrite(unknown_table, UNKNOWN_TABLE_SIZE, 1, outrbt_file) != 1), C  e7 G7 |# D/ x" ?4 ~
  371.     {5 J" W8 ?4 ~4 \! S- Y
  372.         printf("problem writing unknown table\n");$ r& {2 W, I% a$ I
  373.         return 0;
    / S2 T4 O1 d4 V3 x2 S; y
  374.     }) v7 L, T% z" O# }
  375. " r  e: Q9 x0 B/ R# ^6 R
  376.     /* copy over padding */. v+ f; P8 m; ?1 d
  377.     padding_size = 0x800 - (ftell(inrbt_file) & 0x7FF);; v* _) ?. a  Q; n2 i
  378.     if (padding_size)
    . S( A  s1 T: P
  379.     {5 R0 P: \) q/ y
  380.         padding = malloc(padding_size);, y7 c7 B! b" r* S! c4 K
  381.         if (fread(padding, padding_size, 1, inrbt_file) != 1)
    % U2 D: I6 G" I% t5 j
  382.         {
    3 R# w* U8 G! A3 C8 [1 g
  383.             printf("problem reading padding\n");
    9 _- R+ X) b3 \5 o& G* H
  384.             return 0;. ~8 w4 U% k0 z& ~
  385.         }
    , ?) F" Q7 Q# n+ F+ X! w
  386.         if (fwrite(padding, padding_size, 1, outrbt_file) != 1)! t: s; c: k; O
  387.         {
    - K& A5 W% Y  I1 ]4 ]3 ]5 s/ H% y$ u
  388.             printf("problem writing padding\n");
    . v0 v, V# `1 C- s
  389.             return 0;
    # k5 F. `7 T9 s; Y4 y; _5 J6 x
  390.         }
    ' J$ C. E" q# @; l. M7 D4 T5 ^
  391.         free(padding);
    + z: s8 O% B5 Z$ M4 r  r
  392.     }
    & l; c3 r6 _. j  O
  393. ; _3 b# U  q- t: l, L/ d( ?
  394.     return 1;
    1 f4 A( p0 T% h& B- g
  395. }
    ( O1 m# e1 Q9 K: t4 @8 h# b
  396. & x  w; h9 n; M4 l& b
  397. static int get_lzs_back_ref_length(get_bits_context *gb)* q6 F2 g  @: ?, I9 J
  398. {
    : R' r3 {# w' R% t5 H3 L& ]6 O' e
  399.     int vlc;
    . _1 d6 j. o3 f7 \6 _4 w/ S4 y/ S
  400.     int count;, E4 N, U( s+ y6 @/ }  ]
  401.     int value;
    + N$ r2 K6 i* {# v& a4 _) N) \

  402. 3 k) Y- a& v( X5 w7 L
  403.     vlc = view_bits(gb, VLC_SIZE);( g. A$ g, f. c$ m0 m
  404.     count = lzs_vlc_table[vlc].count;2 }# c& q) _2 `2 Y% V
  405.     value = lzs_vlc_table[vlc].value;8 w( E+ }7 b8 c
  406. 3 h* `4 @. U  N8 y& M; \$ S6 b
  407.     read_bits(gb, count);
    " Q( {7 R+ {/ D6 g* a# E4 |, ^- l
  408.     if (value == 8)
    * V- `3 Y$ b& Z8 i% d7 ]1 e
  409.     {) ^4 n8 K" x% {% t' b7 z4 b3 p
  410.         do; v2 U8 x4 l# Y: Y  E* @8 }) }
  411.         {' g7 y% R1 j5 ~& q/ c: X
  412.             vlc = read_bits(gb, VLC_SIZE);  B7 }; M  M: ?$ ]1 {$ S
  413.             value += vlc;
    2 Q# Z& O! B) P! ^5 U7 J$ j9 [
  414.         }
    , L6 Q' ~# _7 |$ Y6 x
  415.         while (vlc == 0xF);
    3 N- y2 O" R' T$ O  H6 y
  416.     }* O  G3 K+ q( Z( z
  417. ' i: X( ?/ k0 c7 r
  418.     return value;& B0 n& ^" @9 B
  419. }$ W  ]# o* G4 N1 l# `
  420. ; D0 G5 d  }5 }- ?0 d. I2 M, k
  421. static void compress_window(put_bits_context *pb, uint8_t *full_window,
    * B; J1 ^3 O. H- U! M! }- K
  422.     int full_window_stride,
    & v7 p& M* W0 N# i
  423.     int window_top, int window_bottom, int window_left, int window_right)) k+ J) J% ~8 Q/ p1 }' u
  424. {
    * K1 S+ y8 L/ o
  425.     int last_pixel;7 ^  f7 z( k& D
  426.     int run_size;
    + z7 K* @. ]1 W& v9 \$ ^+ {% h, n
  427.     int x;
    ' Q5 l' t+ w' o) k
  428.     int y;( q6 h2 l" m% d" X5 F  y! y
  429.     int start_index;
    7 w1 t8 M- X6 |+ J3 F
  430.     int end_index;
    4 [5 T* S$ N7 P" E
  431.     int encode_last_run;
    9 g& N) E8 q( l9 q# O9 T, B
  432. 6 o+ Z6 d# }5 H
  433.     last_pixel = full_window[0];
    , Z( H) S) [2 x* Z
  434.     run_size = 1;
    2 W) T! ^- q( k% P
  435.     for (y = window_top; y <= window_bottom; y++)
    4 a) T, J* Q3 d9 U4 D
  436.     {
    - B9 t: [* Q1 g) b  [( }3 y' z
  437.         start_index = y * full_window_stride + window_left;1 l- b2 x! j9 [5 Y; v
  438.         if (y == window_top)9 |. r. j7 D, g8 o
  439.             start_index += 1;
    * R& Y  I; k1 A
  440.         end_index = y * full_window_stride + window_right;
    8 r& I: S. Z5 c2 \# b) ~5 L, i4 N
  441.         if (y == window_bottom)& F+ D5 s  v% ]# g  J, B
  442.             encode_last_run = 1;
    # {: {# g* J5 Y+ Z" E+ n. M8 D6 r
  443.         else
    , K! u8 O7 y5 `5 Y. Q1 H
  444.             encode_last_run = 0;
    # g4 X3 }. W0 ?/ V
  445.         for (x = start_index; x < end_index; x++)6 j" L! K# Z( J& ]7 d% C1 @) d# z+ z
  446.         {0 D7 E) o6 R$ n+ J
  447.             if (!encode_last_run && full_window[x] == last_pixel)
    2 x; a9 x+ N) f$ b3 h  t
  448.                 run_size++;
    . s$ Z/ g2 H) G' w% |. H' e
  449.             else
    3 K( X) u) f2 j/ b. b' F6 ?$ g
  450.             {, _0 k5 W- K. K! {6 z) O, h
  451.                 if (run_size == 1); J' T/ j8 o% Z( N& B
  452.                 {) J0 m$ ?! t% j5 n5 _, |
  453.                     /* encode a 0 bit followed by raw pixel byte */& ?+ K% A" H! w# @% ]3 `* e* G, z
  454.                     put_bits(pb, 0, 1);
    + o: Q& j+ K9 P1 N
  455.                     put_bits(pb, last_pixel, 8);7 U, u" G7 R/ s* ^
  456.                 }' B% w0 u( h0 X6 F( j$ D- L+ w4 i# N
  457.                 else if (run_size == 2)
    1 d3 G. M* A: `/ ~5 q2 i: \
  458.                 {6 ], n; b! R. Z8 P2 b
  459.                     /* encode a 0 bit followed by raw pixel byte */
    0 i6 K" W$ m: k$ L' [- W
  460.                     put_bits(pb, 0, 1);4 E. Y, Q+ Q5 r+ ?$ _
  461.                     put_bits(pb, last_pixel, 8);, g8 o0 A: m) E+ U7 M3 d8 `5 w
  462.                     put_bits(pb, 0, 1);7 j5 s9 d& u  a' }
  463.                     put_bits(pb, last_pixel, 8);
    5 y5 _2 h0 p# h6 M' h
  464.                 }
    # v6 E4 e/ [) ~  G7 U! o- s" k
  465.                 else4 R- e1 d/ P2 Q+ O
  466.                 {
    2 ]: c6 z1 w( _
  467.                     /* encode a 0 bit followed by raw pixel byte */+ Q( s/ p" A0 n! ?* _
  468.                     put_bits(pb, 0, 1);" C% j7 z3 @0 H' ~# K! g4 {
  469.                     put_bits(pb, last_pixel, 8);
    ) m3 e" I/ K9 z+ H7 C
  470.                     run_size--;& @2 h9 s% X) [: w, t
  471.                     /* encode a run: a 1 bit, followed by a back reference  V# R: }$ v0 J1 ~8 j( ~
  472.                      * offset (-1), followed by a length */
    $ T% s9 y+ f" Y* T8 l; A. a: z8 P
  473.                     put_bits(pb, 1, 1);' W7 U' n/ X6 q% H# J
  474.                     put_bits(pb, 1, 1);  /* 1 = 7-bit offset */; V/ N. r8 [8 _9 R3 d. @
  475.                     put_bits(pb, 1, 7);
    ' V3 l- I& c/ A' Q1 u- d9 Z
  476.                     if (run_size <= 4)1 l" M4 c( ]' w1 w5 u3 K! N
  477.                     {& O+ P. H" R3 d! a. N4 o! g
  478.                         /* lengths 2, 3, and 4 are 2 bits */
    5 z- n' P! B% p3 @0 N1 V" g
  479.                         put_bits(pb, run_size - 2, 2);
    / a( ]7 k9 v+ ?% E0 [$ R; L
  480.                     }, C- _' M: l+ c) s6 r+ a( o
  481.                     else if (run_size <= 7)
    5 p& ?2 h4 U" H3 U6 [3 E* k+ `* P4 S
  482.                     {$ W! C0 q6 p) ?0 H( X* z! ^0 d! W
  483.                         /* lengths 5, 6, and 7 are 4 bits */4 P5 N/ w8 Q7 @
  484.                         put_bits(pb, run_size + 7, 4);% W/ @6 S0 R  M. O- i
  485.                     }
    . T6 e9 \" u% X+ g" ]9 K
  486.                     else! y8 W: L) V8 W
  487.                     {' y+ ^3 i" P$ O* B
  488.                         /* arbitrary length; start by encoding 0xF which
    . b8 b% y9 r) |
  489.                          * stands in for an initial version of 8 */
    " w5 |) E8 C1 B/ o# o/ J
  490.                         put_bits(pb, 0xF, 4);
    / T. @2 x) D: |9 t# g& S8 j' S3 Z$ U
  491.                         run_size -= 8;
    : A# q( C1 x& d2 `4 d# w* v2 l: \

  492. % B; k8 A4 R+ D. G2 |4 _! p, }1 I' e
  493.                         /* encode blocks of 4 bits until run_size is 0 */5 g9 `; C1 |# Y! |! t3 I: X' ?
  494.                         while (run_size >= 0)" |7 B" v1 @: g
  495.                         {& t% \; _  m: F* C& u
  496.                             if (run_size >= 15)
    : ?- U3 Z, [/ r; L( t7 @, L$ K
  497.                             {! ?/ y! ^$ F4 v/ x+ _7 [4 |( a
  498.                                 put_bits(pb, 0xF, 4);6 D1 M0 `' ?& k$ t" q* |
  499.                                 run_size -= 0xF;2 ?6 d( O+ h; L4 ~4 D+ W6 {! D: ^$ q. f6 H
  500.                             }
    . t/ \  C0 ]5 |# A
  501.                             else
    / h/ z) _9 y: N1 U
  502.                             {
    ; A  R! o6 u1 f# E; w' w  v* H' r
  503.                                 put_bits(pb, run_size, 4);' f2 s( V8 B: F" l3 D
  504.                                 run_size = -1;
    # K1 E) \' e5 L( W4 a3 E
  505.                             }
    & t8 H' y# V' r
  506.                         }
    - R' r0 t( E' d
  507.                     }4 K6 |: h7 O7 K; S# n: M' W% o
  508.                 }
    0 j7 k: N; I2 I

  509. 3 W8 C+ X+ C0 I# M/ w: [
  510.                 last_pixel = full_window[x];
    6 E# {3 k" i' w( g$ W: s, r$ m
  511.                 run_size = 1;6 U! x7 d' G& I% G( A/ X) i

  512. 5 i1 w3 _& ^% V- T& L  W  U
  513.                 /* this single x iteration was only here to close the final run */  X  U# {/ V0 {
  514.                 if (y == window_bottom)
    8 T. q. N: ]. w6 Y$ E+ G  S
  515.                     break;1 _) y5 S3 C5 [0 ?2 g
  516.             }- {, x' d: N* m( D; @6 T8 X+ v
  517.         }
    ( t; k" s$ s1 ^# q/ ^& y6 q
  518.     }
    " J/ s: ~0 p# J3 p. q- h5 y

  519. 5 y* D2 l4 M+ P$ F
  520.     /* close the bitstream by encoding a back reference with length 0 */
    : X3 H) E' X, y( T5 r
  521.     put_bits(pb, 1, 1);  /* back reference run */# }5 Q/ e1 }/ z& e1 W) Q7 u2 v- P7 |
  522.     put_bits(pb, 1, 1);  /* 1 = 7-bit offset */: S; O" t' k* S: F
  523.     put_bits(pb, 0, 7);  /* length 0 */
    - a) h0 |1 R4 C# Q1 a) P
  524. + C; d, |9 Q, x
  525.     put_bits_flush(pb);
    # x% S- `) U& `) l) {0 b2 P
  526. }
    2 S, ~, H' |* P  R, f, I

  527. 0 C& f5 i4 P( r3 S1 S8 B
  528. /* compute Euclidean distance between an RGB color and the desired target */# T2 }$ O; e( {  M- @
  529. static int compute_rgb_distance(int r1, int r2, int g1, int g2, int b1, int b2)% R+ D6 r8 o' x6 O
  530. {3 U: Q+ @7 m  Y' K8 T! }% p. x
  531.     return sqrt((r1 - r2) * (r1 - r2) +/ i) s4 f. W" D' [# W$ c- \9 p
  532.                 (g1 - g2) * (g1 - g2) +" M* T4 I$ d7 B) o
  533.                 (b1 - b2) * (b1 - b2));8 i9 j& C9 n) O  ~7 y0 @
  534. }
    % V/ Z. j' M! V+ s) U0 j

  535. ! {  n# {, B! J" }3 B3 N
  536. static uint8_t find_nearest_color(rbt_dec_context *rbt, int r, int g, int b)
    8 U9 R$ U. X5 h$ t& [& K  n' Y$ V
  537. {9 l* Y6 v1 D; P6 c7 ^3 b! ?9 m
  538.     int i;
    : d% O1 S- [8 ~( A& p) S5 u% `
  539.     int nearest_distance;
    % k2 n1 _( _& ]
  540.     int distance;
    3 {; ~: t+ A% E' q, H5 e! q2 {  m" {
  541.     int rp;1 Q5 O  l2 p8 v; N
  542.     int gp;
    + _5 e* q  {3 J* O' U* o# m
  543.     int bp;
    0 S& l5 R, V$ H. b3 @1 E0 ?
  544.     uint8_t palette_index;, q- x# ^. O: e+ ^) m" ^/ {& j
  545. . y; ^2 S4 a9 ]" g4 L" y( f" a6 a
  546.     nearest_distance = 999999999;4 s; @5 i# X6 J
  547.     palette_index = 0;
    $ J4 B: M$ `2 J% V
  548.     for (i = 0; i < 256; i++)0 e  D6 h  R; ~2 [
  549.     {; I& L/ i: i9 ?& b# F: |
  550.         rp = rbt->palette[i * 3 + 0];3 w! f- a% z2 w, v
  551.         gp = rbt->palette[i * 3 + 1];) B/ B5 E! e) g  A  E7 M( p
  552.         bp = rbt->palette[i * 3 + 2];
    6 K; a  L6 g" l- I4 f
  553.         distance = compute_rgb_distance(r, rp, g, gp, b, bp);
    0 t# w+ e' m+ M, F6 {
  554.         if (distance < nearest_distance)
    9 A* Q7 b3 h' K7 Q3 v2 a% T$ L
  555.         {
    ( h  u; Y1 Z# L& F* X
  556.             nearest_distance = distance;
    5 F& j$ o! H$ M& ?2 X; Z/ w0 C
  557.             palette_index = i;
    ) A2 C3 w& s9 P8 J1 x
  558.         }
    8 G: j" l" s3 O7 Z8 Y
  559.         /* can't get closer than 0; break early */
    . j! T; @8 f( H
  560.         if (distance == 0)/ ?/ y: b; {! i- E, D
  561.             break;6 v8 v+ x1 ~5 `) ?1 \8 r
  562.     }! q4 t9 u: j$ M6 p

  563. 0 @/ `3 A) t& `& c* T' g4 \
  564.     return palette_index;
    - g4 T7 z$ P3 k- ?. `3 Y( y
  565. }8 p  U5 y" `: a" ?/ W6 T0 _& S

  566. ( Q! w( o9 M( [. K$ _* U1 q" H, d
  567. static void subtitle_frame(rbt_dec_context *rbt, uint8_t *frame,) {7 a+ L' v* Z, M
  568.     int width, int height, int timestamp)) F4 `) y. c- ]0 [
  569. {5 X3 d6 p3 m, p1 I
  570.     ASS_Image *subtitles;& s5 _) S/ r7 e+ [6 D" l* N
  571.     int detect_change;! J2 U; f$ j, m' @, x" d3 H9 {
  572.     uint8_t subtitle_pixel;2 O# }5 }, L6 a0 Q* n
  573.     int x, y;: d. F3 ^9 B& P" H, y; H: o
  574.     uint8_t *frame_ptr;& ~* j8 |# O0 w. G; b. ~5 D' `6 r: A/ d. S
  575.     uint8_t *subtitle_ptr;1 u. N% j+ J& Z/ Q
  576. 7 b, X) s( l  j
  577.     /* ask library for the subtitle for this timestamp */
    + M$ b1 e  t# y( g
  578.     subtitles = ass_render_frame(rbt->ass_renderer, rbt->ass_track,
    0 J0 {& R0 y' d6 W1 k6 s$ }* g# _
  579.         timestamp, &detect_change);$ r6 l3 _0 D1 P# @3 [

  580. , D# D; j' m2 H# z; r
  581.     /* render the list of subtitles onto the decoded frame */( @, ?0 G, O9 ~8 g4 h, s
  582.     while (subtitles)
    * }0 M) r0 g( H! x; ^( `3 U- j
  583.     {& [0 J( n/ V! x0 ]9 O
  584.         /* palette components are only 6 bits, so shift an extra 29 |; T7 P1 w$ R( D5 \! r. _; E0 P
  585.          * bits off each component */
    + T- X/ U" b, q& E( X: V" X
  586.         subtitle_pixel = find_nearest_color(rbt,
    & B* E5 g3 A2 O$ G! B4 `6 \
  587.             (subtitles->color >> 10) & 0xFF,
    * U- Q+ T3 L: x% Y1 G
  588.             (subtitles->color >> 18) & 0xFF,
    ) t/ e! c. b1 D/ S3 Q
  589.             (subtitles->color >> 26) & 0xFF);& T, M" o4 p0 \" h: D
  590.         for (y = 0; y < subtitles->h; y++)
    : S$ f' X: A+ i) S% A0 a; A
  591.         {
    ( Q6 p2 t( ~: \% Z) q
  592.             subtitle_ptr = &subtitles->bitmap[y * subtitles->stride];
    . S  N2 k. ^, O1 l8 F% _
  593.             frame_ptr = &frame[(subtitles->dst_y + y) * width + subtitles->dst_x];
    / y- f& J& n' j5 G, S2 m* n
  594.             for (x = 0; x < subtitles->w; x++, frame_ptr++, subtitle_ptr++)7 v. j  \6 y. Z7 {
  595.             {
    ! O9 B  k* _( Y7 s( _7 U' g
  596.                 if (*subtitle_ptr >= SUBTITLE_THRESHOLD)
    2 @& D& {! X. b: G$ o( J
  597.                     *frame_ptr = subtitle_pixel;
    . @# v# w1 n5 g  t
  598.             }
    $ ^  \, q0 c# S$ T8 h3 ^
  599.         }
    1 l( a; l8 ?" a& e0 A- F
  600.         subtitles = subtitles->next;
    % g3 ~& j8 T( O: X% P6 t2 n
  601.     }& v9 m: j3 N  L# {- x
  602. }2 E; ^0 R0 h+ F3 }3 f0 P9 d0 f2 p
  603. 3 a- j/ F# x9 W
  604. static int copy_frames(rbt_dec_context *rbt, FILE *inrbt_file, FILE *outrbt_file,3 _0 \7 S- ^8 \2 X
  605.     int origin_x, int origin_y, int window_width, int window_height)
    8 r3 `! d" l( w8 r* h( H
  606. {
    3 ~( `; {& K, O6 A7 W6 M3 r
  607.     int i;8 T9 U5 N, P: |0 v
  608.     int j;
    + d8 @% Z4 Y4 t* T# ~, R
  609.     int scale;
    : n$ b! x" R# K; X
  610.     int width;- d8 o! a. D7 c
  611.     int height;
    . `* M" M( f1 k/ i- D
  612.     int max_width;6 Y) I- M# ]0 U' E5 P3 S) I
  613.     int max_height;
    6 F: r' x! h7 N* F- I, t
  614.     int frame_x;
    1 _% K6 I. N9 U) D9 T
  615.     int frame_y;) o5 [$ s; d1 h# U" p
  616.     int fragment_count;
    ! U- l$ G1 M, _, {( J
  617.     int decoded_size;# I. h. P0 t. P
  618.     uint8_t *decoded_frame;
    ; G7 O" v0 E: u) O1 ~4 b
  619.     int fragment;) B! {- z  u0 ~% i3 U' t
  620.     int fragment_compressed_size;- \* K& `* I2 Y8 r2 d( }  p2 T. B
  621.     int fragment_decompressed_size;$ z5 A( m! A. s5 Q$ B
  622.     int compression_type;
    ' |: H  x8 I; B. S
  623.     int index;" \" `# q6 q9 {  g. ^
  624.     int out_index;
    ! r) t- V' v: [( |! ]. o( G
  625.     get_bits_context gb;; `* S8 E. B! h* e9 @
  626.     int frame_size;
    + ^7 y( V# O: A& ~9 w" ?
  627.     int video_frame_size;) U9 C5 x6 A6 R- N
  628.     int audio_frame_size;1 I$ @: O9 J3 T* r# y
  629.   [# e8 B, J) E/ H. w
  630.     int back_ref_offset_type;
    ! Z3 }2 A4 I7 f# z7 f: J8 r
  631.     int back_ref_offset;+ I& e& n9 J) R3 N$ T
  632.     int back_ref_length;
    1 J0 x3 X% r* }. H, L& f  K
  633.     int back_ref_start;
    7 o" z4 E4 U5 E( b4 N) G
  634.     int back_ref_end;$ D1 D& s: ?" T2 l( R% i
  635. . F* d" j9 S& m+ L3 |5 T$ N6 u: w, L
  636.     uint8_t *full_window;
    $ _" [" a* f- i9 @7 c
  637.     int full_window_size;( w( F( j0 ?" Q" k* q; k
  638.     int y;
    8 N+ Z# _8 ?& U: u2 X
  639.     int window_top;
    9 H5 J( x5 @2 g2 |% ~
  640.     int window_bottom;; k  e5 `, F( D4 [5 H' G1 [4 y+ p
  641.     int window_left;) T3 a1 v3 @5 b& ~" z& V
  642.     int window_right;" i: C4 m) n# A( [. m4 ~
  643.     int window_size;
    8 \& i# o# k" F% `/ z* r
  644. : i7 |* @8 `: q1 g$ ~
  645.     char filename[30];
    5 q1 J! F$ ~) Y
  646. $ x, B) B, M7 {" A( {
  647.     put_bits_context *pb;
    ! d1 \1 W7 J. O8 P
  648. 2 G) W8 s0 f, M! m( `: r9 C2 v6 A4 v
  649.     full_window_size = window_width * window_height;
    6 e* S! ^& c) @/ u( O4 r2 V
  650.     full_window = malloc(full_window_size);
    8 [! c, r8 o: [+ q4 ^' J# x
  651.     pb = init_put_bits();. J9 V+ I4 \6 x4 H3 c: Q

  652. 8 X3 q6 _# u" d. Z" R# O8 U
  653.     max_width = 0;
    % S& Z& n  [2 E
  654.     max_height = 0;, x) ^8 C0 Q( x# q: q
  655. # n- b' G3 ~0 ^3 t
  656.     for (i = 0; i < rbt->frame_count; i++)
    ) B& q8 D: K# B9 L
  657.     {- W& ^7 {) O6 L& Q" l, W: e
  658.         /* read the entire frame (includes audio and video) */
    % n' l- O5 g, b" j0 l# D
  659.         frame_size = LE_16(&rbt->frame_size_table[i*2]);7 W$ \9 o, O4 {5 V
  660.         video_frame_size = LE_16(&rbt->video_frame_size_table[i*2]);
    / u' f' b6 m1 O: x  e' w3 x
  661.         audio_frame_size = frame_size - video_frame_size;# @  ~$ W+ x; I/ F- `9 {) F6 [% N
  662.         if (fread(rbt->frame_load_buffer, frame_size, 1, inrbt_file) != 1)* \+ a% o6 K, P7 [% M, d6 B
  663.         {
    8 y4 ~" Z" r" n& G3 X
  664.             printf("problem reading frame %d\n", i);
    * |: j3 }+ e2 o, ~* L: K
  665.             return 0;% R9 V( {& Q2 P. P  E
  666.         }
    * b, R8 ^8 Z9 n: K" y. X5 j

  667. 0 q' U5 P+ B( q9 ~' f- V
  668.         scale = rbt->frame_load_buffer[3];) ]/ ~  A( r6 ]( ~5 K& o; A/ J
  669.         width = LE_16(&rbt->frame_load_buffer[4]);
    5 m- f/ ~5 ^( l  Z* i
  670.         if (max_width < width)8 q+ W6 i# C1 m9 g5 r
  671.             max_width = width;/ S2 k0 B' \- `, y' L% B
  672.         if (max_height < height)
    ! n8 J0 {" d1 n/ s
  673.             max_height = height;
    4 u% n2 @4 z  d! N$ L' C; f
  674.         height = LE_16(&rbt->frame_load_buffer[6]);
    / Z2 a, N: C; u# G
  675.         frame_x = LE_16(&rbt->frame_load_buffer[12]);
    : ~) c* H; |0 `& M/ |  \
  676.         frame_y = LE_16(&rbt->frame_load_buffer[14]);& T4 P: F" p, K8 y
  677.         fragment_count = LE_16(&rbt->frame_load_buffer[18]);
    7 i- u* k4 F* P( C  r7 B( I
  678.         decoded_size = width * height;
    & ~9 q$ _" t8 j: S/ Z$ t) T& v
  679. $ }3 p" \( U0 [( `" ~8 f7 }
  680.         printf("processing frame %d: %d%%, %dx%d, origin @ (%d, %d), %d fragments\n", i, scale, width, height, frame_x, frame_y, fragment_count);
    # M! n$ ~- f1 L, K0 o" n) {

  681. 0 E6 {; }- r' t% j( `9 F3 e
  682.         /* decode the frame */
    & j$ @+ J0 O$ z  S7 b" O7 U& T& n
  683.         decoded_frame = malloc(decoded_size);( q, [# n& X/ D# i
  684.         index = 24;
    4 H! k! J' F5 q& Q4 F6 F5 Q4 ^
  685.         out_index = 0;
    # r5 a# P+ U0 V1 o- C
  686.         for (fragment = 0; fragment < fragment_count; fragment++)# b$ h+ v. Y# X* D$ J/ U
  687.         {7 X% \& O9 E+ k( l! G6 u
  688.             fragment_compressed_size = LE_32(&rbt->frame_load_buffer[index]);3 N5 x! g: {/ L$ a& Y9 j+ r+ D
  689.             index += 4;
    . J- D9 t/ Y& }! }( V
  690.             fragment_decompressed_size = LE_32(&rbt->frame_load_buffer[index]);
    ! s1 M6 x5 P3 j# k
  691.             index += 4;6 T1 K8 I/ ]3 \7 T
  692.             compression_type = LE_16(&rbt->frame_load_buffer[index]);
    0 v4 V% \: e8 z; d1 G* V9 k3 c
  693.             index += 2;" z- o# A* \: ^( @  g, R; O

  694. $ U# w! n8 H4 J
  695.             if (compression_type == 0)  b& P1 x& G  g, d
  696.             {
    0 p" u* K8 F) o0 z
  697.                 init_get_bits(&gb, &rbt->frame_load_buffer[index],0 M9 @- q/ n7 w# b
  698.                     fragment_compressed_size);& F( g* x- D* P7 J! b& c

  699. & g+ j, A5 R8 z  c
  700.                 while (out_index < fragment_decompressed_size)
    4 ^. e9 t; E" b  x$ x
  701.                 {7 q6 E; H& C. h6 [2 A
  702.                     if (read_bits(&gb, 1))
    4 O! g3 N- q6 @; {- ~9 N# `+ [+ A$ g6 a
  703.                     {
    7 U) b+ B$ L& N2 N
  704.                         /* decode back reference offset type */& c, @! ?: x, g' k% P
  705.                         back_ref_offset_type = read_bits(&gb, 1);
    , f1 I; g+ q) ?  k

  706. - o* _+ N/ C( r4 H" C; G
  707.                         /* back reference offset is 7 or 11 bits */
    . o0 O3 g1 J1 q, M  z/ ?( _
  708.                         back_ref_offset = read_bits(&gb,7 Y, A* I( q0 T( B
  709.                             (back_ref_offset_type) ? 7 : 11);
    ! O' Y& ~' O1 N4 R$ |+ D' p

  710. ) A1 p( O! P2 u5 l) F' U3 q4 ]& @
  711.                         /* get the length of the back reference */
    9 W& i# ?  {$ I9 S$ i# S- I
  712.                         back_ref_length = get_lzs_back_ref_length(&gb);& {& P, |; F; L1 n
  713.                         back_ref_start = out_index - back_ref_offset;
    1 V: t' n7 d8 `! L# f9 b) H
  714.                         back_ref_end = back_ref_start + back_ref_length;* e8 G- R1 H( _+ g6 c# D6 r

  715. . e3 a9 D6 @: o) W
  716.                         /* copy the back reference, byte by byte */4 ^. M! B! }+ W, H$ E$ ~# o  T$ B
  717.                         for (j = back_ref_start; j < back_ref_end; j++)
    ! X. E, G  C& q* P
  718.                             decoded_frame[out_index++] = decoded_frame[j];
    1 v, ?* r, b1 `' |6 A/ C8 {- l
  719.                     }: u( G; _  e# _/ a; c
  720.                     else
    - v% B8 f0 D, E* H$ Z9 W4 ~
  721.                     {8 r* x0 P/ t: m
  722.                         /* read raw pixel byte */: ?$ l2 \$ t9 f' r& |/ [
  723.                         decoded_frame[out_index++] = read_bits(&gb, 8) & 0xFF;
    " y8 h! }, x4 j- G
  724.                     }, v. z, g1 m/ P" C& E5 V5 {0 \! M
  725.                 }6 y9 j9 l1 g& Q& L1 E6 {. L
  726. + ~# p- |& `$ \
  727.                 delete_get_bits(&gb);- G- d+ Q% K8 I& S
  728.             }- J' m6 t9 G' L" n: ?7 w3 S# c
  729. 8 d; N8 G- _! ]; s
  730.             /* next fragment */( |! D/ ^7 M7 \% c7 |
  731.             index += fragment_compressed_size;
    + g) h* @  B- I+ l0 s  {9 S: i
  732.         }
    0 _" u& P  R2 ?& a3 Q1 V4 E
  733. 0 r+ L" e2 B- _$ c- N& Z
  734.         if (rbt->dump_frames)
    # t9 c3 }/ }& I& j
  735.         {2 `/ `  ~( C$ f( y/ {
  736.             /* dump the original frame */
      Q+ w& j* L+ ^+ e# ~
  737.             sprintf(filename, "original-frame-%03d.pnm", i);
    ) K' `0 E3 R6 c0 y' b# }
  738.             dump_pnm_file(filename, rbt, decoded_frame, width, height);
    ) ~! [; v  l$ g3 n' `
  739.         }
    1 J) d; h5 N5 K  Z  x* n( X

  740. 0 H+ C2 v5 x( h6 B
  741.         /* transfer the image onto the frame window */& V9 Y' ^4 Z! |# j( Y
  742.         memset(full_window, 0xFF, full_window_size);
    + ]! J9 e& r  a
  743.         index = 0;  b* h3 r% o( s$ o( b" l+ D% L
  744.         for (y = 0; y < height; y++)8 s( A* I6 i! @% V$ g  M
  745.         {6 D) E& d1 o' t# a, s2 _
  746.             out_index = window_width * (frame_y + y) + frame_x;: G, f/ |5 g+ h: h
  747.             memcpy(&full_window[out_index], &decoded_frame[index], width);8 C0 Q2 ^9 N+ f
  748.             index += width;/ O9 @% u4 l# q' e, n! ~
  749.         }
    0 q+ H' k; f7 D' X0 G5 U

  750. 4 H( _6 n+ O, K& e( [$ A" K
  751.         /* write the subtitle */
    ( q0 l) F( c. C! B8 ~3 i
  752.         subtitle_frame(rbt, full_window, window_width, window_height,
    : y2 b9 L4 R; ]9 b1 R6 S' @
  753.             i * MILLISECONDS_PER_FRAME);9 n9 q* Z$ K  G) d0 a# w9 A# T

  754. 7 [8 e( O3 B. W) t9 n# z
  755.         /* figure out the smallest change window */
    - x' l2 @( n- p$ `- U
  756.         window_top = frame_y;. E7 d* ?/ S' y7 U3 ^5 D' Z! \& X
  757.         window_bottom = window_height;7 t5 n( w' z! R$ M' i$ `4 S# F
  758.         window_left = 0;$ R8 U6 b5 j! `; w4 m7 S+ l
  759.         window_right = window_width;
    , K- [) g1 h* B" Y$ [1 a4 Y2 j: T
  760.         window_size = (window_right - window_left) * (window_bottom - window_top);9 M5 \3 d/ f0 U+ u
  761. + D+ e  l$ C6 A0 H, ^/ P# A
  762.         /* compress the frame */9 m, a7 Q+ D$ u$ y% ]
  763.         reset_put_bits(pb);
    # K" a% A8 Q6 a- i# j3 X0 c4 V5 N
  764.         compress_window(pb, full_window, window_width, window_top,
    $ u2 b$ `; e: v' C, o6 v1 O
  765.             window_bottom, window_left, window_right);$ d) |" e/ P# e2 x# |; c

  766. + p4 L. d& L7 v, A5 W  |2 d
  767.         if (rbt->dump_frames)
      K# j3 ^) W/ Y$ c' I, {1 {; c) `; ]
  768.         {
    ) Y7 \$ R6 S0 G9 |4 r
  769.             /* dump the frame plotted onto the full window prior to encoding,
    , c$ n" o/ l- d0 F
  770.              * with subtitle */
      p9 `% y  w& ]9 Z! N# h
  771.             sprintf(filename, "pre-encoding-frame-%03d.pnm", i);
    : o( n' U* z! m. O" [6 `/ k& l2 w
  772.             dump_pnm_file(filename, rbt, full_window, window_width, window_height);
    ! J. G* C0 z  w1 x% @. b7 Y
  773.         }6 M0 @- j- i1 V. c, V4 B* }4 r
  774. . o$ z* W/ C5 A# f
  775.         free(decoded_frame);
    ; c  x- V& k% ^5 _- B# y. J0 x2 I

  776. 8 V2 {4 G- F0 |# A: O/ f
  777.         /* update the frame header */' L- I; E+ K* o8 w4 }
  778.         /* width */- b- d1 e8 t# [$ N
  779.         rbt->frame_load_buffer[4] = (window_right - window_left) & 0xFF;
    / D4 y- [" S3 ^' M- Y; c# Z% p: p
  780.         rbt->frame_load_buffer[5] = (window_right - window_left) >> 8;
    2 \: \6 n# h7 M% q: x3 m
  781.         /* height */, b/ v) C, e$ I2 t7 u
  782.         rbt->frame_load_buffer[6] = (window_bottom - window_top) & 0xFF;
    4 P) S/ t7 Q" J6 h5 _
  783.         rbt->frame_load_buffer[7] = (window_bottom - window_top) >> 8;
    1 F' w6 `- ?: M' i/ b6 \9 ]9 l% m5 d( h
  784.         /* origin X */- T6 ^8 z: v# {7 O- {; k
  785.         rbt->frame_load_buffer[12] = window_left & 0xFF;9 X+ {  m7 u8 ?8 b" z
  786.         rbt->frame_load_buffer[13] = window_left >> 8;
    * u( _  H* @( _7 Q: {
  787.         /* origin Y */
    - d6 L+ ]( d# d8 m5 h, w: x! n
  788.         rbt->frame_load_buffer[14] = window_top & 0xFF;
    8 R9 O2 a$ x8 _  w& C
  789.         rbt->frame_load_buffer[15] = window_top >> 8;/ C( k  P- s1 \9 Y9 |
  790.         /* fragment payload size */# N* ~/ h5 F3 O1 \: T$ B
  791.         rbt->frame_load_buffer[16] = (pb->byte_index + 10) & 0xFF;7 C# U# a* a! H8 U
  792.         rbt->frame_load_buffer[17] = (pb->byte_index + 10) >> 8;& ]) |' h* `$ D& G, O
  793.         /* fragment count (1) */
    & p  a5 @0 w' F3 H. p$ \4 [
  794.         rbt->frame_load_buffer[18] = 1;
    2 i$ m8 }9 `* y0 M4 f  J" z0 |
  795.         rbt->frame_load_buffer[19] = 0;
    4 I( f. a. I! ^- u% Y
  796. # w9 U$ W" `4 T$ g4 m
  797.         /* update the fragment header */6 b( O0 q: i8 ~: u
  798.         /* compressed size */! v' i+ B# D4 p( B, v
  799.         rbt->frame_load_buffer[24 + 0] = (pb->byte_index >>  0) & 0xFF;
    7 G, E7 L) F) b1 z; J" O
  800.         rbt->frame_load_buffer[24 + 1] = (pb->byte_index >>  8) & 0xFF;
    & q& R/ {! R. S6 w2 b
  801.         rbt->frame_load_buffer[24 + 2] = (pb->byte_index >> 16) & 0xFF;2 }- q9 H" L7 T( ^
  802.         rbt->frame_load_buffer[24 + 3] = (pb->byte_index >> 24) & 0xFF;4 G; ^( z9 E: G. d# _
  803.         /* decompressed size */
    0 d$ y) b& U' X  \& b. Z! i
  804.         rbt->frame_load_buffer[24 + 4] = (window_size >>  0) & 0xFF;8 f% h* v  c7 O3 d  g" C# B+ Q
  805.         rbt->frame_load_buffer[24 + 5] = (window_size >>  8) & 0xFF;
    7 e- \; S3 ^, U5 {$ W9 w4 O' g- \6 i( \
  806.         rbt->frame_load_buffer[24 + 6] = (window_size >> 16) & 0xFF;9 S" D! [% m' c- P' @
  807.         rbt->frame_load_buffer[24 + 7] = (window_size >> 24) & 0xFF;
    8 m8 \1 e) y0 J, n$ }8 `* a
  808.         /* compression format 0 */4 n& L0 J+ X$ T- s( i
  809.         rbt->frame_load_buffer[24 + 8] = 0;8 @' N8 @' ~  R
  810.         rbt->frame_load_buffer[24 + 9] = 0;
    & V1 Y0 `+ X, \8 f! B( l  Q
  811. 2 ^" _* K) @2 i$ ~/ h" l% K
  812.         /* write the 24-byte frame header and the 10-byte fragment header */6 j, ^, v$ _& X: L/ W7 {8 f
  813.         if (fwrite(rbt->frame_load_buffer, 24 + 10, 1, outrbt_file) != 1)
    : n. l9 t7 }( ~* j( b  O) a* _
  814.         {
    3 A+ t$ U* }. q) t- f3 {
  815.             printf("problem writing frame %d\n", i);
    4 ?1 p8 x) t1 T4 Q+ R  q
  816.             return 0;: H' w1 Y* ^0 \+ g5 h( i
  817.         }
    & Y6 X& f9 G* I( r1 k
  818. 1 u% L( L& e- {+ M; \6 K
  819.         /* write the new compressed frame data */
    9 P+ r- L6 Z6 r9 O2 N& m
  820.         if (fwrite(pb->bytes, pb->byte_index, 1, outrbt_file) != 1)
    . k2 n/ X1 M9 i
  821.         {
    , f' s. n3 F7 s$ A: x! f% u
  822.             printf("problem writing frame %d\n", i);
    ) K( W7 m" A% A+ i- h
  823.             return 0;- i" O# F+ Q) W! G$ S
  824.         }5 O/ O$ A8 l8 V2 @& d

  825. ' j1 b+ W! i5 u# U
  826.         /* write the audio data */! U1 v4 v$ w3 z8 d* I
  827.         if (fwrite(&rbt->frame_load_buffer[video_frame_size], frame_size - video_frame_size, 1, outrbt_file) != 1)
    ' W: |+ M- u5 |+ h  y8 q# F9 ~
  828.         {" M( b2 g* {9 O2 z  R, ], @& F+ C
  829.             printf("problem writing frame %d\n", i);8 D1 a& i2 t* q
  830.             return 0;: ], m+ ]: g2 g& o# a( i) p0 D; W/ v
  831.         }
    " Y3 l9 t' @! k1 S
  832. % N; u( `( o+ Q- w! Y( l
  833.         /* update the table entries */
    ! F2 e- [8 [* ~- y3 {1 D) k
  834.         video_frame_size = pb->byte_index + 24 + 10;
    ! I3 J( |* \+ T% R, o
  835.         frame_size = video_frame_size + audio_frame_size;
    0 u! ^! c  `* S. ?
  836.         rbt->frame_size_table[i*2+0] = frame_size & 0xFF;0 f; y0 q+ D. O( L# ]6 R9 Q
  837.         rbt->frame_size_table[i*2+1] = frame_size >> 8;
    . |, H2 n$ c  b5 Z+ N: o
  838.         rbt->video_frame_size_table[i*2+0] = video_frame_size & 0xFF;
    # D4 T. y2 E* T2 H4 t
  839.         rbt->video_frame_size_table[i*2+1] = video_frame_size >> 8;
    : @/ M7 w1 l* x, W2 _5 V
  840.     }
    , y& R& t1 N# {: n  _
  841. 4 V8 d# z7 }6 t" v+ K, u
  842.     printf("maximum dimensions seen are %dx%d\n", max_width, max_height);
    7 [, ~, a3 ^2 t- X& g& p& E
  843. 6 b9 {6 h3 F8 k0 k& w) D1 q
  844.     delete_put_bits(pb);
    0 @" h7 H; ^: C7 I2 v2 g
  845.     free(full_window);
    / d; D* a* b$ v. V  u! k/ F

  846. 5 _4 U8 P2 V- a
  847.     return 1;4 Y8 d$ V+ `6 g
  848. }
    2 j8 S$ n, e- ~) u: r% ^

  849. 1 {3 y/ T- d# V. p1 b: z- E8 i
  850. int main(int argc, char *argv[])/ e* c+ o$ `! v5 f8 S
  851. {8 ^) y) c! K* J. I+ q7 ~
  852.     char *subtitle_filename;# y% @# n2 k/ G- O* Q$ h  T
  853.     FILE *subtitle_file;
    $ s( [- x- ]9 _* c0 w
  854.     char *inrbt_filename;
    4 \6 t" _% }1 T3 c9 Y
  855.     FILE *inrbt_file;
    ! R  X- ?( w2 x4 w+ L
  856.     char *outrbt_filename;+ Q4 r( P5 f7 @# ^4 s' x# N
  857.     FILE *outrbt_file;
    % j8 v( H$ C' l2 B. e5 Z
  858.     rbt_dec_context rbt;
    & w. I8 ]/ O3 F# M7 @: M) b
  859.     int origin_x;
    : f; ~& K% ^$ I) L, Z/ Z( p0 @3 j& \
  860.     int origin_y;
    ' f2 N# e5 D  b& P# ]
  861.     int window_width;9 |) H3 q, L: r7 ]+ \
  862.     int window_height;
    # h0 k$ z2 U7 L
  863. ; u9 P$ @, t2 _0 N3 V
  864.     /* testing the bit functions */) H; i: r: r4 q3 P( e& v
  865. #if 00 K/ ^6 M  I8 i- Z( [
  866.     int i;3 ~0 I1 N  A9 `9 J
  867.     uint8_t bytestream[] = { 0x55, 0xAA, 0x00, 0xAA, 0x55, 0x77, 0xFF, 0x1B, 0x70, 0x8F };- |" G% K7 B) P$ W
  868.     int bytestream_size = 10;
    * O( {2 z6 j& t) l  z" Y
  869.     get_bits_context gb;
    % t# q7 E6 [8 j: i4 _" R1 z! G
  870.     put_bits_context *pb;1 C' Q1 \  _; }( n; w
  871.     int bits;
    5 y& j/ o1 h, u" R* d$ Y

  872. / v# O' {3 Z; n; M$ L
  873.     init_get_bits(&gb, bytestream, bytestream_size);2 P9 {2 f# V  ]
  874.     pb = init_put_bits();
    0 U/ n5 I6 Q" {% L( K& x5 Q

  875. * O5 j$ w5 }; ^9 N
  876.     for (i = 1; i <= 12; i++)
      z) J% n- [6 \4 T* d; J
  877.     {1 t; ^  L' w; v) [/ P8 D
  878.         bits = view_bits(&gb, i);) Z, C$ Q" z5 }( m# W
  879.         printf("view %d bits: %d\n", i, bits);
    5 ^% G8 \# m9 E  y; E* M
  880.         printf("read %d bits: %d\n", i, read_bits(&gb, i));$ S% D# ]5 S/ X  C' R" ^" k
  881.         put_bits(pb, bits, i);
    % E& ?* f: Y, m1 q
  882.     }
    / Q# K/ g( v! S( e3 z2 [8 P
  883.     put_bits_flush(pb);
      n9 K3 w- ~' ]4 h! H  X

  884. , ]. _) s0 v* A
  885.     printf("original bytestream:\n");- [7 t9 f" k  K: u' N0 i
  886.     for (i = 0; i < bytestream_size; i++)9 L3 @0 W- k6 F9 w
  887.         printf(" %02X", bytestream[i]);' J4 i: ^2 x, ?. y) g
  888.     printf("\nnewbytestream:\n");
    4 o/ D0 D* O- h% O1 a4 X, Y
  889.     for (i = 0; i < pb->byte_index; i++)# h1 k$ T4 X, L' P
  890.         printf(" %02X", pb->bytes[i]);2 `- E+ v% _0 a1 L
  891.     printf("\n");) _1 J: P: g: b

  892. 9 A) y3 q3 I2 L: E$ U* C) J
  893.     delete_get_bits(&gb);+ |  V9 f2 K2 w, ]2 Z
  894.     free(pb);) r* D7 X9 h+ J0 F
  895. #endif  f$ ?7 E2 A+ x, S

  896. * [. N6 _0 _9 q+ p9 B( A- J
  897.     /* validate the number of arguments */. f1 x3 _8 X( M- v  p7 B
  898.     if (argc != 8 && argc != 9)
    & }$ T; w  e  Z0 A2 b) ]* m
  899.     {
    3 q" s, U* [% A1 [! t0 e6 y  S
  900.         printf("USAGE: subtitle-rbt <subtitles.ass> <in.rbt> <out.rbt> <origin X> <origin Y> <width> <height> [dump_frames]\n");
    , s( F8 C: S( H/ t0 V% P5 T5 m2 a# v7 a+ p
  901.         return 1;
    - c! s* r% U! k
  902.     }# |3 K. S, ~+ T3 }
  903.     subtitle_filename = argv[1];
    1 p6 c4 P1 ?: C! I9 \2 `7 @* k
  904.     inrbt_filename = argv[2];
    * c& e# |8 _# A+ J' G; p) E
  905.     outrbt_filename = argv[3];
    6 S* @  O# f) f/ J4 J
  906.     origin_x = atoi(argv[4]);
    - u. ?; J: ^% b  L( s8 y, q4 G
  907.     origin_y = atoi(argv[5]);7 N# o% a! _  t
  908.     window_width = atoi(argv[6]);
    # P# \- d8 K, Z* Q* A2 a
  909.     window_height = atoi(argv[7]);
    $ O4 p& m+ K8 u5 k
  910.     rbt.dump_frames = 0;
    9 q+ r9 l6 P0 r& F
  911.     if (argc == 9)
    ; J# c4 F1 ^, f0 y3 X. x- K
  912.         rbt.dump_frames = 1;. M' K# u5 p; s2 _
  913. $ E; U: o8 w- ]5 g
  914.     /* verify that the specified input files are valid */
    * I: {1 a9 w; i8 ^: T- F% N% M# V
  915.     subtitle_file = fopen(subtitle_filename, "r");2 z8 O% ~. g5 K& E
  916.     if (!subtitle_file)
    1 P8 {0 U$ h- `2 l/ |# e4 H
  917.     {
    9 c4 N/ I8 `9 }  @4 X# ]4 e
  918.         perror(subtitle_filename);
    ) B! l+ s0 _( a
  919.         return 1;
    8 d$ a. t5 x7 S
  920.     }9 \: f' Y; b- U! w# @5 H, W
  921.     fclose(subtitle_file);
    2 c9 b1 g5 o. _2 H6 }$ P( L
  922.     inrbt_file = fopen(inrbt_filename, "rb");! C8 X2 r' q( E% J
  923.     if (!inrbt_file)- x& U' T/ L9 D3 \
  924.     {
    0 v; d- D! A; e$ p
  925.         perror(inrbt_filename);
    3 |! @( z9 U2 \
  926.         return 1;
    : \* R" k4 F9 \$ \0 p. k/ F
  927.     }8 F, X4 W+ h/ ?- t# S$ d' _
  928. ! r9 Y2 X' t* x; j8 v  h4 p
  929.     /* initialize the subtitle support */8 j3 K. u" T# n* U; _8 A3 L, l
  930.     rbt.ass_lib = ass_library_init();
    7 ?! _+ D9 l; z+ z' r1 C
  931.     rbt.ass_renderer = ass_renderer_init(rbt.ass_lib);
    " t9 P. e7 R8 r% X1 g
  932.     rbt.ass_track = ass_read_file(rbt.ass_lib, subtitle_filename, "UTF-8");6 s6 t$ K. w+ F2 h  s; R* e/ h5 g
  933.     ass_set_frame_size(rbt.ass_renderer, window_width, window_height);) \5 }' i( J6 Z4 ^' L+ l( B: R3 f
  934.     ass_set_fonts(rbt.ass_renderer, NULL, NULL, 1, NULL, 1);
    ( [( v9 C3 t6 `0 G

  935.   Z# A( ~5 ?4 r' ]$ c
  936.     /* open the output file */$ ], a1 |. ~. R! Q( A1 V% a. ?
  937.     outrbt_file = fopen(outrbt_filename, "wb");( z! E! i3 I) {9 ]2 X
  938.     if (!outrbt_file)
    3 |+ ~* V8 C6 N, d" ^" }
  939.     {4 c1 m6 Q) p; ~! ^7 X* M4 s( i& \. H* N
  940.         perror(outrbt_filename);" f$ u& m2 w+ Q* r* i$ b
  941.         return 1;- x5 C0 p, [5 q/ L! q+ d9 D7 ?) i
  942.     }
    + O) E( e$ E9 S, m. H( A$ [
  943. 5 a! u' v9 v6 |8 \7 K
  944.     /* transfer header from input to output */$ X% y6 ~1 `6 j9 y1 ], E
  945.     if (!load_and_copy_rbt_header(&rbt, inrbt_file, outrbt_file))7 m* y2 R; T) t5 ^! G, M
  946.         return 1;: H9 R1 H' [: Z7 A5 m

  947. 6 q2 t" s( X2 [
  948.     /* rewrite the frames */. }* B- d$ P  P) ]/ t9 d
  949.     if (!copy_frames(&rbt, inrbt_file, outrbt_file, origin_x, origin_y,9 j1 b8 Y: l  G
  950.         window_width, window_height))
    4 `1 M" j- g) W2 q5 g$ K
  951.         return 1;+ i. {6 y: T, b0 s, j8 W) H- y- e
  952. ! F, v, _" A4 F; ^+ h9 k$ d
  953.     /* write the modified frame size tables back to the file */
    . r5 ^2 R8 v# ^6 n  h7 s
  954.     fseek(outrbt_file, rbt.video_frame_size_table_offset, SEEK_SET);
    9 Y- Z5 H+ x6 R5 S2 u, U- ~# i
  955.     fwrite(rbt.video_frame_size_table, rbt.frame_count * sizeof(uint16_t), 1, outrbt_file);
    8 q' E% N$ p7 z6 c
  956.     fseek(outrbt_file, rbt.frame_size_table_offset, SEEK_SET);
    % x$ O4 h# I( r7 m$ g, b1 H5 w
  957.     fwrite(rbt.frame_size_table, rbt.frame_count * sizeof(uint16_t), 1, outrbt_file);6 }5 D5 \% v" F/ j2 v3 L: z

  958. / S* y, m8 d. q# {
  959.     /* finished with files */5 ]9 j# ^% o2 q6 x* x
  960.     fclose(inrbt_file);
    6 }- |0 b  U# `3 _$ I
  961.     fclose(outrbt_file);
      `1 s; I. H: i7 Z4 m  z

  962. + \- q* x6 I$ e7 K1 m
  963.     /* clean up subtitle library */; Q$ n1 {8 C, l
  964.     ass_free_track(rbt.ass_track);2 L  }  X& N* |6 L: Q, O" C
  965.     ass_renderer_done(rbt.ass_renderer);7 m: T  G" a4 f/ m( \' H
  966.     ass_library_done(rbt.ass_lib);9 J  z, c3 `5 ~; L3 s
  967. 7 ]3 q" j" E. P
  968.     /* clean up */& e: L5 [+ ?" e; U! @
  969.     free(rbt.frame_load_buffer);
    5 V# B) W/ B9 Q/ }7 u5 Q6 t- z1 A
  970.     free(rbt.video_frame_size_table);9 Y' M9 V) v* X: i. L7 Y
  971.     free(rbt.frame_size_table);
    ( A. E, v1 P! ^, Z' @* `8 F9 v
  972. 7 o. X! T- f1 ?1 Q2 j: P
  973.     return 0;
    7 r' O  x; S( A/ {  ]0 L# j& Q
  974. }
复制代码

: ^: k- z4 F8 M' E' |: T. v1 w, @! Z
) L4 {1 @- l" c' C

4 I* |+ Y9 O' L4 [* c' T
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 很美好很美好 很差劲很差劲
回复

使用道具 举报

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

使用道具 举报

板凳
 楼主| 发表于 2009-11-19 11:38 | 只看该作者
引用第1楼soring123于2009-11-19 11:09发表的  :( y+ ~0 n- N9 l( O- |; I" |) A
这游戏有字幕吗?

0 n  ~5 X. ?7 J好像没有字幕,我说的是给视频外挂字幕方式的汉化。2 T4 P: C! L- R: l7 |2 d
就像syberia2汉化版下面那行字一样。
回复 支持 反对

使用道具 举报

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

使用道具 举报

5#
 楼主| 发表于 2009-11-19 17:39 | 只看该作者
引用第3楼soring123于2009-11-19 17:07发表的  :
/ Y% W6 S( l. m- }; }0 H我记得是没字幕的 比较麻烦 都是视频的

3 [/ k& |7 V0 ?/ }+ n给视频外挂字幕方式汉化也许能行。
7 j2 W3 _: ~7 H! A3 J- P要结合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日,是全球华人共同的冒险解谜类游戏家园。我们致力于提供各类冒险游戏资讯供大家学习交流。本站所有资源均不用于商业用途。

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