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

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

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

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

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

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

本帖最后由 shane007 于 2021-1-2 13:56 编辑
# A! b0 N/ j# _# k
  ~$ z# F' E' P/ D" P最近找到了一些和幽魂系列Phantasmagoria 有关的资料,
. P7 {" ~/ J5 Q7 @2 V& I* ~0 _也许将来可以用于汉化。5 O8 ~7 b: d* ]* U- W

; j' c0 ]% z( [3 ]# ^! H和日文版有关的信息. b+ Z$ \/ O& l% f* c5 U* c8 d
http://anthonylarme.tripod.com/phantas/phintgtp.html
, g5 m* g0 }0 f+ d+ D" y8 v7 A- Q
1 {; o6 M& Q; \6 a相关工具4 l! g+ T; u0 t: R0 m# b; N
http://anthonylarme.tripod.com/phantas/phcheats.html; f- A1 O) p; t  C
-----------------------------------------------------------------------
- K& T% D/ L* i* Q# J2 x2012/1/2  更新
5 F, l! p% ^* k; M关于幽魂游戏的字幕1 i! ]) e6 s# X
Phantasmagoria subtitles function discovered - ScummVM :: Forums
' P+ c! j) A4 K; C5 ~1 H0 X
% }; x; R& u: b$ @  b( a2 {1 oVMD文件
6 ^7 q' X4 r- I) B; u+ iSubtitling Sierra VMD Files | Breaking Eggs And Making Omelettes (multimedia.cx)VMD - MultimediaWiki
' Z. f: ?5 ]  C, v! R) Y: e2 l  e9 f& Q
字幕0 I& L1 w# u! A8 O
Subtitling Sierra RBT Files | Breaking Eggs And Making Omelettes (multimedia.cx)
5 b6 M& j6 a) {' C1 ^9 ^/ ~# W% h0 B
FFmpeg/subtitle-rbt.c at feature/VMD_encoder · multimediamike/FFmpeg · GitHub& x7 S: y+ f4 ?& o- t2 S
  1. /*
    : Y- @6 x) X, a4 F  c0 k
  2. * subtitle-rbt.c
    9 \# ]1 m& |* w0 W9 j
  3. *  by Mike Melanson (mike -at- multimedia.cx)2 D. f4 N2 q  M& ^9 ^6 q* u
  4. *6 n" n. h% x  K+ @1 q
  5. * build with this command:
    ' y- O6 j2 x& E' C% P
  6. *   gcc -g -Wall subtitle-rbt.c -o subtitle-rbt -lm -lass5 V! K$ P% A8 i- J* o5 ], @% J
  7. */3 J1 S& {3 `: p- Y# T
  8. 1 b7 w: J$ p5 @2 a$ ^0 l
  9. #include <inttypes.h>8 S  Y# b2 N2 C
  10. #include <math.h>/ g! G( \0 i# g# i
  11. #include <stdio.h>
    # k8 l* s  D5 @% F
  12. #include <stdlib.h>
    - k8 `4 n6 \' I8 F, ]$ R8 C( Q0 ?8 n
  13. #include <string.h>
    & h! c5 K0 E4 E" R
  14. 2 @- U" D( F9 C! j0 o" p
  15. #include <ass/ass.h>' n  U/ K4 l$ b  w+ y7 `  i- x

  16. 4 C. R  d# a  J) [
  17. #define LE_16(x) ((((uint8_t*)(x))[1] <<  8) | ((uint8_t*)(x))[0])
    ! G+ F) M& A, j( p9 d$ h

  18. - w7 H3 R" j4 i5 k6 M, G- \7 f
  19. #define LE_32(x) (((uint32_t)(((uint8_t*)(x))[3]) << 24) |  \
    5 K+ t1 C( R( |' P: ~
  20.                              (((uint8_t*)(x))[2]  << 16) |  \
    " [: u" U+ E2 Z8 ]8 `- Z" v  u
  21.                              (((uint8_t*)(x))[1]  <<  8) |  \
    # S1 c0 T1 \: ~1 c/ Q' R6 y
  22.                               ((uint8_t*)(x))[0])& h+ @9 O) m( z5 s5 N( w  _, }

  23. 7 N% G6 y6 r7 v1 h
  24. /*********************************************************************/' E) N+ [$ h0 n1 V  O$ y0 ~1 o, l1 d6 Y
  25. ( a; V/ ?" V, ?) \
  26. /* Bit reader stuff */
    / g; T: W! P4 l1 T: j' V

  27. # E# p1 p$ @5 e. B4 f( D6 V- L
  28. typedef struct
    4 ~9 [7 x! D$ g( r- A) R
  29. {7 h, `: ?8 N; @
  30.     uint8_t *bytestream;
    ' o1 T3 d9 j: E. [% ?7 g
  31.     int bytestream_size;
    ' r% T% c& O2 y" H) H
  32.     int index;# O7 \( B; p4 `  s9 t4 R
  33.     uint32_t bits;
    % R/ S9 u& D, g& [
  34.     int bits_in_buffer;9 a3 s2 @+ X; ~$ s+ k' C
  35. } get_bits_context;+ w+ e+ g* i& P+ g, g: b2 g( M: g' N) H
  36. # U" P, ^& T) g+ `* e# h. c
  37. static inline void reload_bits(get_bits_context *gb)8 N: h, ?1 C* a
  38. {
    7 ^' u7 a; f" H. O- A+ l& y
  39.     while (gb->bits_in_buffer <= 24)
    ' q' v; W0 }3 x0 A' ~
  40.     {6 G" i8 ]; O; E. {
  41.         if (gb->index < gb->bytestream_size)
    - D; l# H0 ~# a  [$ _: D. t$ G
  42.             gb->bits |= (gb->bytestream[gb->index++] << (24 - gb->bits_in_buffer));
    6 D( {( J) r. Q# ^. L
  43.         gb->bits_in_buffer += 8;
      N; F3 _' u: [) X$ _" c5 @4 Y" I
  44.     }' r! V: W! Y. s6 I2 l: i% {
  45. }
    4 Z2 n. E! Y6 |# V+ G

  46. 8 o. K, T1 p5 ?/ I, x/ m
  47. static void init_get_bits(get_bits_context *gb, uint8_t *bytestream, int size)
    ' |3 Q, Q& p  G: C
  48. {
    / ~0 w, _4 `$ Y0 [# r, W$ M1 |* k
  49.     gb->bytestream = malloc(size);
    0 A9 M8 n  q1 M
  50.     memcpy(gb->bytestream, bytestream, size);
    6 K2 {0 ?8 O  D. X9 W
  51.     gb->bytestream_size = size;3 E' D5 {7 O6 K) [. v% W- h( I
  52.     gb->index = 0;
    , n2 e: T5 L# P5 ~
  53.     gb->bits = 0;1 G; J" K: v& f
  54.     gb->bits_in_buffer = 0;  b: U. d: c( Z0 W% y4 C$ K& R

  55. + b" [8 |- k* ~4 q: R
  56.     reload_bits(gb);4 P% h" L% |8 |) D: ~
  57. }
    8 u0 J1 h4 n/ Q! U& H9 V) T
  58. 0 u% ]: K# {2 a6 A. R
  59. /* read bits without consuming them from the stream */$ D9 b7 h2 _" Z- I, e: N- Z5 z" d% n
  60. static int view_bits(get_bits_context *gb, int count)# p& ]/ U& u6 }% E2 o
  61. {0 F4 h1 H0 Q8 j0 E- L
  62.     if (count >= 24)- q% H4 n4 Q, Z1 F9 N
  63.         return -1;0 ^3 R) }7 f8 d7 r6 H4 t
  64.     if (gb->bits_in_buffer < count)4 _7 |) h! W/ O: I: D# F5 P3 ^
  65.         reload_bits(gb);0 a; `" Z( Q5 C9 j& K' v" |
  66.     return (gb->bits >> (32 - count));
    " R1 {7 Y% j( U4 f+ q* c' z
  67. }
    . I0 j2 D8 }& b- x' u  l1 l
  68. 1 j, z- p# z2 s/ T/ r& `
  69. /* read and consume bits from the stream */
    $ q1 _: X# ], `% r+ |
  70. static int read_bits(get_bits_context *gb, int count)
    - h. b! h& v* D' T
  71. {/ C( Y, ~7 G7 n* O1 j. J! x  W
  72.     int value;
    6 R" Z. V/ i9 M& c3 f% R8 Q

  73. ( [3 B5 v/ V% ?1 W1 t- F$ z% a
  74.     if (count >= 24): |( C* y; P  J% Z& P
  75.         return -1;$ |+ {7 u2 L+ p: V. C

  76. 6 F  p- e5 N" H1 J. O
  77.     value = view_bits(gb, count);
    $ J! [1 j6 j' ^/ U- C, W
  78.     gb->bits <<= count;
    5 T' |% l8 S* h0 I1 W
  79.     gb->bits_in_buffer -= count;5 f. |( h7 t! g
  80.   p3 J0 {/ h& K# A' B+ a# k# {" ]
  81.     return value;- r+ S' x0 B" R" x: m' o: c
  82. }8 @# h$ ]# r! b+ m7 \

  83. % P; }# K, B! v
  84. static void delete_get_bits(get_bits_context *gb)
    4 l5 ?) E) d: z! p! X
  85. {
    # p. i6 U, `+ N, M' p5 H! Y
  86.     free(gb->bytestream);
    ; t+ S% i, ?& `6 I: r
  87. }
    6 h0 ]1 @2 s, C6 A3 u

  88. 1 ]$ i8 D5 P: r$ i  i
  89. /*********************************************************************/8 e5 S6 X0 C6 e- Q* e
  90. * |  a4 @5 q$ i! n' U
  91. /* Bit writer stuff */
    3 S" Y: \& Y8 I: O6 }6 f
  92. 5 q9 @5 x0 N1 ]
  93. #define MAX_PUT_BITS_BYTES 63000
    , N& `' s/ T  k. \
  94. typedef struct
    ) m! z. B: i8 n
  95. {4 c4 r) _: j: K- _$ q
  96.     uint8_t bytes[MAX_PUT_BITS_BYTES];8 ~, D: t/ B9 c! q3 x  a
  97.     int byte_index;2 O5 ~, ^! Q( `! t$ S1 m
  98.     uint32_t bit_buffer;
    4 Q3 ?7 Z! I) k$ ], d9 B
  99.     int bits_buffered;$ g$ U. c; D: M( F6 n0 Y
  100. } put_bits_context;
    ! ]* p# A* f* [2 m
  101. 1 z2 F5 O7 d. S* N' P* Z
  102. static void reset_put_bits(put_bits_context *pb)/ n( j8 p8 F: B( a+ h
  103. {
    ; P4 l5 v: X) P
  104.     memset(pb->bytes, 0, MAX_PUT_BITS_BYTES);
    - T* |6 _# s" }2 @
  105.     pb->byte_index = 0;* [1 v0 _1 ]6 b  P+ T3 ]$ I" T5 L
  106.     pb->bit_buffer = 0;
    ! X$ `  S9 e5 _
  107.     pb->bits_buffered = 0;
    1 _( z* u+ k# g& e
  108. }
    1 Y4 r2 J2 G1 M& Q$ M) |
  109. % C& g- Z/ x( `  }0 l) z$ G$ ?5 z
  110. static put_bits_context *init_put_bits()3 H( I" z4 b" c8 v3 k4 J1 l
  111. {
    ( \& j! x! z; j6 x; e: y1 L0 W3 s5 z
  112.     put_bits_context *pb;
    ' G/ c0 ]( H- T# ~
  113. 0 }/ I; a/ t& r$ W1 m" ^
  114.     pb = malloc(sizeof(put_bits_context));9 m0 @* K1 z2 P  N3 k' f
  115.     reset_put_bits(pb);
    - m  f+ L. g3 l  e" X0 g) [2 i

  116. % t8 c$ @  v5 f; D( G' u
  117.     return pb;
      @  u  m3 G4 {
  118. }1 F9 x" ]9 P# r" O

  119. 8 t& _7 L2 n( Z& o
  120. static void put_bits(put_bits_context *pb, int bits, int count)
    ; M+ [$ j7 G7 C( U" K6 E
  121. {; N9 h) {( X! d4 f. d
  122.     pb->bit_buffer <<= count;
    $ P9 ?1 ^# P* J; y& z. U
  123.     pb->bit_buffer |= (bits & (~(0xFFFFFFFF << count)));6 T& d8 F8 K) U7 X. I% Y) h6 j, l
  124.     pb->bits_buffered += count;
    # V3 _- Z8 i0 S6 A( V7 H. Q

  125. + J9 i. r. _2 Y, Z% a; m) ^2 J
  126.     while (pb->bits_buffered >= 8)
    5 L# v9 ]% O- u  X
  127.     {
    $ \& H( q1 B9 K4 S0 M0 ^! n
  128.         pb->bytes[pb->byte_index++] = pb->bit_buffer >> (pb->bits_buffered - 8);
    ! e. N& f: u* y7 _' \
  129.         pb->bit_buffer &= (~(0xFFFFFFFF << (pb->bits_buffered - 8)));" R& F) }( h% {  c
  130.         pb->bits_buffered -= 8;1 a6 B& X9 \8 q) l+ B: |
  131.     }. ], E8 ~& h9 x& ^: i1 x7 p1 G
  132. / @9 t1 H) t. g# B2 I
  133.     if (pb->byte_index >= MAX_PUT_BITS_BYTES)% m8 r' m' e& C- ~0 Q
  134.     {
    / Q1 a/ L( `- }
  135.         printf("HELP! Bit overflow\n");3 K/ j; x9 Q6 |/ [
  136.         exit(1);* k+ D1 K; S, T0 [$ y- ?9 N
  137.     }: r# o7 W) [& n
  138. }
    9 L7 v8 s) x7 b3 C
  139. 3 @% a5 ^/ {0 ^0 _1 m3 i! j5 v  l" c
  140. static void put_bits_flush(put_bits_context *pb)# D$ f4 t6 {; X  @6 B7 X* R
  141. {7 I' @5 o1 T; ~2 w6 z# N
  142.     if (pb->bits_buffered > 0)' N& C5 k8 o0 [3 @
  143.         pb->bytes[pb->byte_index++] = pb->bit_buffer << (8 - pb->bits_buffered);+ B. H7 B) _- f5 O% [
  144. }
    " s" a3 O+ m% P! X- n+ n
  145. " H, i9 `6 u; _4 }; o" T
  146. static void delete_put_bits(put_bits_context *pb)
    5 i! x+ t& S) |2 C1 l
  147. {' x# D# P- f! ~9 C* W( g3 r
  148.     free(pb->bytes);
    ' h4 y! @+ {- u) I+ T
  149. }
    0 L$ t8 R6 q& B& \, J

  150. 0 K3 N1 h0 G6 P% I9 S$ U
  151. /*********************************************************************/
    7 o- X% E& z, a  N7 Y+ E& f
  152. % ^% N( B6 [9 `6 L8 M  \! D
  153. /* RBT functions */7 y* {: T- K' ^; }. T1 M# R
  154. 2 J: K4 E( h$ S' d6 G  [, W2 m, Z
  155. #define PALETTE_COUNT 256
    8 A# \1 S" o; ~0 N
  156. #define RBT_HEADER_SIZE 60
    : i. X/ x% Q3 c( U: z
  157. #define UNKNOWN_TABLE_SIZE (1024+512)7 b0 U% o: j" o
  158. #define SUBTITLE_THRESHOLD 0x708 X9 {8 e% {5 G4 C0 x0 N- m1 i
  159. #define MILLISECONDS_PER_FRAME 100
    5 s. d$ a* P7 I" I  x

  160. , @1 |4 ^6 \( d3 i1 U6 p4 R9 U
  161. /* VLC table */
    8 k, r& u9 l* ^; `+ u: W
  162. #define VLC_SIZE 41 z! C4 x8 p0 X+ W$ K2 s. f4 z5 B8 {* R
  163. static struct+ c7 V2 J+ S3 V& z$ N9 Q
  164. {
    4 l- F+ P* a- U2 s" l
  165.     int count;
    $ M& w4 q& T8 e" ]
  166.     int value;
    ; m; M+ R" u1 W, ~
  167. } lzs_vlc_table[] =
    ' i, L) }+ v  K8 x6 w' Y9 o" C5 X
  168. {
    5 k+ t$ _1 I6 b* u8 B2 y
  169.     /* code length = 2 bits; value = 2 */* W7 i5 d: ?! W
  170.     /* 0000 */ { 2, 2 },
    4 l8 p6 G2 M% h
  171.     /* 0001 */ { 2, 2 },
    . S4 C* E) E' v; \8 e
  172.     /* 0010 */ { 2, 2 },
    # L' v- _$ C  o# G" D
  173.     /* 0011 */ { 2, 2 },
    9 P- }, B9 [% j0 h' b+ c
  174. 5 B: }( [, q, r$ X
  175.     /* code length = 2 bits; value = 3 */  r1 ]+ r% Y1 ^
  176.     /* 0100 */ { 2, 3 },/ `7 X" Y; q5 p
  177.     /* 0101 */ { 2, 3 },8 ^# P- W& u! Z0 T  T& f' ]
  178.     /* 0110 */ { 2, 3 }," o; }6 y* K* c; V8 W' Y) H
  179.     /* 0111 */ { 2, 3 },, M4 |3 u% w" W8 A: W  i' Z/ k  I

  180. * ]% o1 u+ _0 ?2 K3 ^, O. n* ^
  181.     /* code length = 2 bits; value = 4 */+ O4 G( N, O, {
  182.     /* 1000 */ { 2, 4 },
    9 I& G2 t; R* Y, D
  183.     /* 1001 */ { 2, 4 },: W  M, U' v8 f, g' z- i0 i! H
  184.     /* 1010 */ { 2, 4 },
    2 a/ w' x/ S4 \1 e
  185.     /* 1011 */ { 2, 4 },8 K( j" H4 {, [1 Q/ L# S% c8 A. G
  186.   i* y) X, X4 X' ~
  187.     /* code length = 4 bits; value = 5 */1 p5 x" g0 z% \0 P1 o9 a! L
  188.     /* 1100 */ { 4, 5 },
      h8 s. [4 o& I$ y. |! l1 X1 j1 b

  189. . w1 \! ?; w1 Q2 A! S
  190.     /* code length = 4 bits; value = 6 */4 ^; W6 o3 Z" ~9 H3 C
  191.     /* 1101 */ { 4, 6 },9 t& u2 J9 Y1 Y2 T6 L% g
  192. 0 ~( A' ~/ p, k0 f+ ~7 H
  193.     /* code length = 4 bits; value = 7 */4 B/ |! D$ I2 w! M, ]7 j  T9 l
  194.     /* 1110 */ { 4, 7 },
    0 t  S8 \+ z" W" l! |( f' o" \
  195. " d7 F' ]: H$ r
  196.     /* special case */) {4 h, \+ [8 z6 O: g5 ~% Y
  197.     /* 1111 */ { 4, 8 }
    ! C$ _4 B' X# p2 i% z/ I  v# u
  198. };
    : Y8 w3 W8 z' R. v4 T5 g1 R# S' b0 j
  199. 3 U# I; f2 F0 j& A8 d
  200. typedef struct) J, B- E+ k  S6 v& l
  201. {
    ( P1 T# E- g5 f. Z' e
  202.     int version;
    - |3 h9 m* B9 l: O( T4 z+ e
  203.     int width;) V0 R: N6 \) z* ?
  204.     int height;
    5 u' c' V- c! d8 m
  205.     int frame_count;: Q* |/ e# R6 u; F
  206.     int audio_chunk_size;; ]# g4 N$ ]2 j  Q3 a1 Q
  207.     uint8_t palette[PALETTE_COUNT * 3];3 l  o3 D' I9 ]/ H
  208.     off_t video_frame_size_table_offset;
    9 [: G. g, O9 y4 H+ A3 [% T
  209.     uint8_t *video_frame_size_table;
    , l5 }" B0 P& R3 ^4 v# ]4 w% i
  210.     off_t frame_size_table_offset;7 N2 ~0 _+ t, G" L; W) A
  211.     uint8_t *frame_size_table;& P- A- y! p, Y7 e
  212.     uint8_t *frame_load_buffer;
    8 U1 X+ v2 o1 y; N0 V" D9 g* W
  213.     int dump_frames;
    ( }1 R# ]: K1 R

  214. 4 {, }: P- k+ Z# W7 Z
  215.     /* subtitle library */2 c  |* d9 T' c5 q+ r7 d
  216.     ASS_Library *ass_lib;
    0 J- y# q1 O9 |
  217.     ASS_Renderer *ass_renderer;
    9 Q. T. T. M9 S7 {: m: j' Y
  218.     ASS_Track *ass_track;! B2 l4 S$ I- y  g; {; H
  219. } rbt_dec_context;' [- T  c. d4 i; r
  220. ! K: b! X0 _. U  g" n
  221. static void dump_pnm_file(char *filename, rbt_dec_context *rbt,4 ]" O3 s! z' _- G7 Y( z* U
  222.     uint8_t *image, int width, int height)' b  f5 ~1 [5 b0 w( r1 }
  223. {) R0 A: x4 P4 [2 A' t  c2 t
  224.     FILE *outfile;' X3 R( S3 m0 o  G6 q/ x
  225.     uint8_t bytes[3];
    6 b3 o- D" `8 U; `) S# U
  226.     int p;! Y" G0 M) w3 \7 o" C$ d
  227.     uint8_t pixel;
    4 D2 N& M# H7 V3 ]5 u! h; m
  228. 7 L2 F# i- {8 P, i
  229.     outfile = fopen(filename, "wb");
    4 U3 v9 v# Z/ D; R- R/ R4 N- s
  230.     fprintf(outfile, "P6\n%d %d\n255\n", width, height);! e4 {3 e0 ?+ ]5 U9 ^
  231.     for (p = 0; p < width * height; p++)
    % O1 I1 i5 s5 t. L2 C4 ?- ]
  232.     {- C( m! q$ j: M# C8 [" V+ I
  233.         pixel = image[p];
    4 V% \# K! H& j
  234.         bytes[0] = rbt->palette[pixel*3+0];
    % O9 W9 B$ V2 ^0 E$ F
  235.         bytes[1] = rbt->palette[pixel*3+1];
    ' M6 t4 ?+ i0 h! G# C
  236.         bytes[2] = rbt->palette[pixel*3+2];( }1 v# F$ M8 }+ O- |- G9 {5 k& |
  237.         fwrite(bytes, 3, 1, outfile);
    , C, A' c3 u! [9 n: s9 |7 L5 ]. o
  238.     }
    7 y$ F' ~* ?3 Y' M3 W7 Y9 ~
  239.     fclose(outfile);
      D; B2 `5 f+ ]) T
  240. }
    " P/ Y& `: w* w7 d

  241. + f: h9 c0 J% X
  242. static int load_and_copy_rbt_header(rbt_dec_context *rbt, FILE *inrbt_file, FILE *outrbt_file)
    $ ~- Q  ^$ V; V/ w4 M
  243. {, X& A9 U, o# P0 P
  244.     uint8_t header[RBT_HEADER_SIZE];
    ) n+ Y' o* }$ {" }) o( M7 a8 a
  245.     int palette_data_size;  n  q# W5 [% C7 w9 D1 t
  246.     uint8_t *palette_chunk;3 M7 o0 A. [3 I# C0 D/ y% p
  247.     int unknown_chunk_size;' M) G! b/ M. ^5 ^
  248.     uint8_t *unknown_chunk;# S$ U% B( j8 t, n4 f0 ~: C" v
  249.     uint8_t unknown_table[UNKNOWN_TABLE_SIZE];+ y5 O+ m  M- W( Y* b
  250.     off_t padding_size;$ u; u" C1 X- m7 K
  251.     uint8_t *padding;0 w6 [9 L! o% i* y0 H! \
  252.     int i;
    1 l% y. ?: E0 ~; R1 x2 m
  253.     int frame_size;2 r+ f( |7 O; D# ^2 p
  254.     int max_frame_size;% W  F* `* B; v1 d2 v' ?# w- i0 g
  255.     int first_palette_index;
    # g$ w) ~( G, W# u$ H
  256.     int palette_count;/ x4 {# q5 _- h8 m1 y
  257.     int palette_type;4 ]5 x  R7 W0 C+ y/ J
  258.     int palette_index;
    # g3 M$ {+ h0 l. T

  259. 9 \1 ^+ @- W8 y1 N
  260.     fseek(inrbt_file, 0, SEEK_SET);8 W  G* z( m3 _  Q
  261.     fseek(outrbt_file, 0, SEEK_SET);) E/ H- |0 o) n4 O  R, @
  262. : E* O/ F( J' g, B# `2 v
  263.     /* load the header */# g' R7 g; `; i0 ~! g
  264.     if (fread(header, RBT_HEADER_SIZE, 1, inrbt_file) != 1)6 x; b: {: c, B+ A
  265.     {. T: o* p! |. k! s
  266.         printf("problem reading initial RBT header\n");
    ; m) m) w( S( I7 }, h
  267.         return 0;) ~! p1 r. H  i3 E
  268.     }
    ' A8 @1 S+ T" v3 ^# W& O( V+ m9 A- I
  269. : Y9 X) T# M2 W4 T
  270.     /* copy header to the output */2 u- e& f5 t9 c9 V0 ?3 K. i
  271.     if (fwrite(header, RBT_HEADER_SIZE, 1, outrbt_file) != 1)6 V/ _& N3 v) M* S1 f; K
  272.     {% {, J% {7 v* A) X- t
  273.         printf("problem writing initial RBT header\n");" W7 B, s1 F) c, u3 e& k, B! q
  274.         return 0;- i, ^5 K% [0 C5 e$ W
  275.     }6 T, |$ X( l! Z5 \

  276. , G  e9 a" G, f2 M9 K
  277.     rbt->version = LE_16(&header[6]);
    ( c0 @3 q8 C: P/ f
  278.     rbt->audio_chunk_size = LE_16(&header[8]);
    * f$ o' u3 C: l& s7 r' a
  279.     rbt->frame_count = LE_16(&header[14]);
    & p6 l- ~' P' V8 s& w

  280. " \0 i2 _" t+ t/ O
  281.     /* transfer the unknown data, if it's there */6 n, l9 X; c2 A; Z' I6 X
  282.     unknown_chunk_size = LE_16(&header[18]);% H3 U9 O" N  x2 S! B- U9 O
  283.     if (unknown_chunk_size > 0)7 @. n" [7 `' y$ b7 J# }! {
  284.     {
    - G# ~9 R* q& h3 n2 F, M- t
  285.         unknown_chunk = malloc(unknown_chunk_size);/ b1 V: h+ ?7 U# P: ^" Q: O  ]/ c
  286.         if (fread(unknown_chunk, unknown_chunk_size, 1, inrbt_file) != 1)% X  c# T0 v$ Y5 O6 i! J9 |" L
  287.         {1 s( c9 q6 ^* ]6 Z$ D: @6 H+ @0 C
  288.             printf("problem reading unknown data\n");$ D$ b6 R+ |& j9 l( x1 v/ J* M
  289.             return 0;
    6 x5 U* J2 j4 V
  290.         }
    % n2 C2 Z" C8 V1 p
  291.         if (fwrite(unknown_chunk, unknown_chunk_size, 1, outrbt_file) != 1)7 Q- d1 `" \3 s6 `7 Q) G8 Z2 b
  292.         {
    * e" q0 P' i$ K$ T+ o
  293.             printf("problem writing unknown data\n");0 ?# x' n8 w4 a7 H
  294.             return 0;
    0 N9 e$ S! g: P- P$ h8 g. T4 \8 n# `  U8 n
  295.         }
    , ^9 j4 T& a# `' `" [1 q) }' s$ M
  296.         free(unknown_chunk);* u. R4 M8 |$ [+ B, ?/ \
  297.     }/ }+ k  |7 x% Z5 R2 E! a: }
  298. + E' V% e' W, [& W
  299.     /* transfer the palette chunk */. m2 W# ]* s# }+ a
  300.     palette_data_size = LE_16(&header[16]);
    + J5 U9 P% H# C6 H$ m! K
  301.     palette_chunk = malloc(palette_data_size);
    9 a; s1 H! s2 S' W( k
  302.     if (fread(palette_chunk, palette_data_size, 1, inrbt_file) != 1)$ g6 Z. |  e9 }4 \/ V& ~
  303.     {2 I" [0 V0 V" I7 M. e, T" d
  304.         printf("problem reading palette\n");3 g+ x: r) W2 ~( V; Y
  305.         return 0;" R/ L! `; ]" X' z: l
  306.     }, J3 u" ~0 g* g4 l9 Z
  307.     if (fwrite(palette_chunk, palette_data_size, 1, outrbt_file) != 1)- Q* P& Y0 p9 b. W0 G1 [
  308.     {8 u7 C5 a  v( D+ e5 J2 l3 N5 A" o
  309.         printf("problem writing palette\n");) a* T3 p8 t+ l* i3 j
  310.         return 0;8 F% K0 s0 X! ~% p+ i
  311.     }
    # F) O- L, {. P" v  h$ |( r/ b
  312.     /* load the palette into the internal context */3 q& e3 R3 \  V' J
  313.     memset(rbt->palette, 0, PALETTE_COUNT * 3);1 R4 |6 p9 U6 e1 P' R# `& u: B
  314.     first_palette_index = palette_chunk[25];( }2 c  e( q( h
  315.     palette_count = LE_16(&palette_chunk[29]);
    3 \1 x+ C- f  M6 ?" U6 E" [4 v
  316.     palette_type = palette_chunk[32];
    * ?2 n9 k" Y+ L% ^/ O& ]6 L
  317.     palette_index = (palette_type == 0) ? 38 : 37;
    1 F; j  V! j1 [
  318.     for (i = first_palette_index; i < first_palette_index + palette_count; i++)
    2 x/ ^4 j5 }8 f" i6 y0 ?$ j' t
  319.     {- e% C8 J0 T' i/ P9 ]
  320.         rbt->palette[i*3+0] = palette_chunk[palette_index++];
    + M& d" k' s( Y8 r
  321.         rbt->palette[i*3+1] = palette_chunk[palette_index++];% d: r" ~3 x' g. a8 L& ~& U3 |
  322.         rbt->palette[i*3+2] = palette_chunk[palette_index++];
    $ Q* X$ p' ~/ `9 L5 V: R0 y
  323.     }  v. t- h. X" `. ^0 J
  324.     free(palette_chunk);
    ) y; \3 R8 [$ }; N4 M9 B2 C$ f
  325. . ^4 N% W3 ]6 K& W! {" `
  326.     /* copy the video frame size table (2 bytes per frame), as a placeholder */+ `- c' V3 |7 E
  327.     rbt->video_frame_size_table = malloc(rbt->frame_count * sizeof(uint16_t));
    $ O1 T8 S: Q8 w4 g0 ~4 f: V, d
  328.     if (fread(rbt->video_frame_size_table, rbt->frame_count * sizeof(uint16_t), 1, inrbt_file) != 1)  E7 `) Q1 J/ j9 y3 Y( W# [
  329.     {
    + P- O5 f2 F  j. }6 [6 d5 I
  330.         printf("problem reading frame table\n");, a# a8 Y8 P( p% q- ~
  331.         return 0;
    $ E* I; L% O) t9 l6 A& R
  332.     }
    1 a1 S" L/ M" w- W" \7 r1 q3 J
  333.     rbt->video_frame_size_table_offset = ftell(outrbt_file);
    5 {8 a  y, m4 {$ F/ Z& s
  334.     if (fwrite(rbt->video_frame_size_table, rbt->frame_count * sizeof(uint16_t), 1, outrbt_file) != 1)/ C0 u  c2 ?7 Y0 m' l& O
  335.     {0 _) x( V9 q8 Y% D$ F
  336.         printf("problem writing frame table\n");
    4 T* F. O4 x% l/ M3 W" Z. X
  337.         return 0;
    / I* L! l+ k% ^6 ~2 c
  338.     }
    6 N  a1 m8 z3 ?+ s2 d: H

  339. 7 b. N4 U7 y/ J( m+ J7 b
  340.     /* copy the frame size table (2 bytes per frame), as a placeholder */
    / w9 Y7 L& k! s; u
  341.     rbt->frame_size_table = malloc(rbt->frame_count * sizeof(uint16_t));/ M& [1 l4 ?, U) h' g
  342.     if (fread(rbt->frame_size_table, rbt->frame_count * sizeof(uint16_t), 1, inrbt_file) != 1)
    ' N+ a2 J& J1 }% G* U
  343.     {
    / K! o9 Q2 j) l' h
  344.         printf("problem reading frame table\n");
    6 v# P$ E' P. c& J5 [8 X5 g
  345.         return 0;3 w- e  P$ X/ N( A: R
  346.     }$ R+ w4 n$ R0 ?' n0 g
  347.     rbt->frame_size_table_offset = ftell(outrbt_file);
    2 R5 R& l- E7 W  T5 ?* y. d
  348.     if (fwrite(rbt->frame_size_table, rbt->frame_count * sizeof(uint16_t), 1, outrbt_file) != 1)  a$ R# U. i0 Y5 F$ c' O* H  H
  349.     {. w* V8 v# }+ I
  350.         printf("problem writing frame table\n");
    1 B7 V( k) n/ `9 `4 M4 ?1 L
  351.         return 0;
    9 E5 O: a2 G4 I0 g
  352.     }
    2 ^. i' _6 a* Y: u* b7 C
  353. ( r0 |: E# A2 _5 ]# ?
  354.     /* find the max frame size */
    9 x; E% ~+ z2 q* @9 |9 I
  355.     max_frame_size = 0;9 }  \0 j% m6 G3 L7 }. ]
  356.     for (i = 0; i < rbt->frame_count; i++)
    ) c& [( {" @, {' o. o% N: |/ h
  357.     {; r0 x2 U! }% @' z2 z
  358.         frame_size = LE_16(&rbt->frame_size_table[i*2]);
    5 o* v6 E4 w( C; q* |% Q+ D
  359.         if (frame_size > max_frame_size)9 z! X- L  ^% h  ?1 v0 y6 \$ z
  360.             max_frame_size = frame_size;
    ; f. F8 P; g9 `
  361.     }
    2 }. e$ T- |0 \( _$ X
  362.     rbt->frame_load_buffer = malloc(max_frame_size);3 e! f9 q+ F, [; K5 M

  363. ; Y; ^+ Q" m2 s
  364.     /* transfer the unknown table(s) */
      W; C  f7 @0 Z; X7 v3 j7 K
  365.     if (fread(unknown_table, UNKNOWN_TABLE_SIZE, 1, inrbt_file) != 1)# [+ u8 v7 Z5 {
  366.     {
    4 e2 w5 O  l# R+ N
  367.         printf("problem reading unknown table\n");+ A" ?% G8 l7 ^9 L
  368.         return 0;" s. F2 h: z+ b
  369.     }
    & B; C% w9 [  ^! |+ `5 v4 p" D
  370.     if (fwrite(unknown_table, UNKNOWN_TABLE_SIZE, 1, outrbt_file) != 1)4 V. G& [. p! U# ^
  371.     {
    ! B5 N$ Q; s& p4 D
  372.         printf("problem writing unknown table\n");
    6 @2 _  }, u/ l2 G' p8 }; c8 t
  373.         return 0;
    3 P* f' U+ B& |; J1 ]$ h
  374.     }: L1 o* G, P7 s. K5 J" J

  375. ) q# O0 N) a3 g7 ~# _9 u, f
  376.     /* copy over padding */- f3 ~( f& E" Y* n: S% K% B
  377.     padding_size = 0x800 - (ftell(inrbt_file) & 0x7FF);$ V- ]  I: q/ z1 X! F7 }% W. Z- x
  378.     if (padding_size)7 ?# p* o! P# \3 [3 r5 i. J' @) j
  379.     {
    ; g2 e' G1 g# l! [3 x! b
  380.         padding = malloc(padding_size);( ?0 o5 o, W' f- Z  O1 f; C% z
  381.         if (fread(padding, padding_size, 1, inrbt_file) != 1)( _( m1 r1 V' q" Y7 X
  382.         {
    . l, F/ O7 b% D. \+ N! B* q: E* y, q
  383.             printf("problem reading padding\n");4 K+ e/ Q8 x9 m/ l
  384.             return 0;! J6 }* {) e9 l+ x& g  h9 K
  385.         }
    5 Y$ X; ?8 Z3 S) ^  ?( {3 Q1 A
  386.         if (fwrite(padding, padding_size, 1, outrbt_file) != 1)
    $ D. x* \% l* G  B3 g  A
  387.         {% r; e3 `' o7 D+ @6 R' {+ U
  388.             printf("problem writing padding\n");9 m2 {! _  K; E$ ]
  389.             return 0;
    4 a# g* a" T' S% J# N  D9 J9 j4 V" w; h
  390.         }/ H) z; w2 Q/ h/ G
  391.         free(padding);4 r9 c  l- H. m/ ~
  392.     }
    ; P4 i) C2 n' ?3 z* c1 i
  393. $ K' @% N+ v$ q
  394.     return 1;8 P. K1 M/ k$ m& E" B6 L
  395. }, ^9 C6 [, Y1 y% _: y
  396. 0 x& M' X# U$ I
  397. static int get_lzs_back_ref_length(get_bits_context *gb)
    - _6 F" l: O4 Z3 i, b* Z
  398. {
    ' n; E. ~7 e' F4 ?! d
  399.     int vlc;
    + ~9 Q% }0 ^! y' O  }1 N
  400.     int count;6 o# N& W, ^  q, \; J/ `$ R- {5 F
  401.     int value;
    + t1 w- N5 S# `0 O5 P3 Y+ Y
  402. 7 a4 W, v5 k3 K
  403.     vlc = view_bits(gb, VLC_SIZE);- w; C+ p' a' Z) S  z/ ^1 \
  404.     count = lzs_vlc_table[vlc].count;5 Y" K$ [" [% F* ~1 N3 H$ l# V
  405.     value = lzs_vlc_table[vlc].value;
    . n9 H3 ], E/ g( e; x

  406. : A9 M  [' @- i6 Q% Q; y& U5 J
  407.     read_bits(gb, count);
    ! P. ~2 Q5 {/ }. k6 v
  408.     if (value == 8)
    ( o% r% h- R7 l# j
  409.     {
    9 U6 ]5 _* F  {: n# V# E0 m1 u
  410.         do; e. {5 F) f3 f9 ~* f
  411.         {% w# W8 c+ M* B1 Z3 o/ t0 l
  412.             vlc = read_bits(gb, VLC_SIZE);% O; ?2 n9 }# X+ I
  413.             value += vlc;
    ( X% k7 D: O- r/ e7 V1 o8 L- y4 x* T
  414.         }
    - m) R/ U/ ]' `9 e
  415.         while (vlc == 0xF);
    3 M0 Z. o% i0 C0 g
  416.     }  I# t$ v+ a, Z1 P5 v$ _

  417. 1 h  [/ a" o1 O
  418.     return value;
    5 P" a- T* f8 ]
  419. }! A+ R/ d7 y. s- r

  420. ( ]% y8 v6 [! Y2 ]
  421. static void compress_window(put_bits_context *pb, uint8_t *full_window,
    ' m; Z, r/ K3 O# b6 f+ Y. q
  422.     int full_window_stride,
    % w$ z4 r# z) W+ K  X8 P3 ^* `& E
  423.     int window_top, int window_bottom, int window_left, int window_right)5 U* W8 e' b" V6 x
  424. {. o5 S$ Z+ i3 ^5 x* A1 N. X
  425.     int last_pixel;
    1 U/ ?- @1 `8 d! Z( U5 I9 M8 P
  426.     int run_size;
    : y% o5 @+ D' k. M
  427.     int x;
    3 J' k- h  [# X+ a
  428.     int y;9 V* p) m" O. Y% }% O2 Z/ ^1 y
  429.     int start_index;$ ?6 {1 p2 a/ ^3 i( p9 E' u  w
  430.     int end_index;* `$ g- V  V( c3 r
  431.     int encode_last_run;
    ' z0 X* I- z) z$ A1 q; E0 l

  432. " O9 P$ R8 A3 c% a
  433.     last_pixel = full_window[0];2 S+ a) M: _" h# X8 q: O
  434.     run_size = 1;0 \; h4 g7 b4 I
  435.     for (y = window_top; y <= window_bottom; y++)
    ; N3 m) q% c. ^: q
  436.     {% o7 C8 J, y. J: R  v" \7 R; e' Z- B
  437.         start_index = y * full_window_stride + window_left;
    $ e1 H; v" p$ V# a1 t  h7 ?
  438.         if (y == window_top)% G2 ]" [# H0 m
  439.             start_index += 1;
    , g1 _5 Z8 H. ~  @4 r/ k
  440.         end_index = y * full_window_stride + window_right;8 k; V9 [$ t9 e4 {8 l, r% y  h$ @
  441.         if (y == window_bottom)
    & v/ f$ H& `+ g) {) o" F1 G$ C& u
  442.             encode_last_run = 1;  [3 E$ _1 w) @) S7 S
  443.         else$ p7 d, F9 l7 O- K" A1 N* _
  444.             encode_last_run = 0;
    , E5 L0 l; u( Q. R2 v+ G
  445.         for (x = start_index; x < end_index; x++)& _) X$ q; ?- p
  446.         {
    % O) o3 s' M% V$ c+ i
  447.             if (!encode_last_run && full_window[x] == last_pixel)/ h/ D& ^9 a/ r" z2 s
  448.                 run_size++;5 i+ F8 |  k  R
  449.             else
    % H( N. R& F. c6 I: D  ?! _4 d
  450.             {
    ( {. k1 F+ x5 w" d8 O* t4 u
  451.                 if (run_size == 1)
    % O" p; F8 }1 F' m+ r
  452.                 {
    $ r- p0 }7 ]- F9 X. v! S' @% A( s
  453.                     /* encode a 0 bit followed by raw pixel byte */
    - V9 U, g1 H$ n3 M9 j8 B* w/ d
  454.                     put_bits(pb, 0, 1);6 M, X) F* F$ p+ r* w0 O
  455.                     put_bits(pb, last_pixel, 8);/ M0 B* C  w: t- l* R- U$ o* {
  456.                 }( U- S" U) H4 y) m) u* g1 {( [; C& r  }
  457.                 else if (run_size == 2)
    9 H( h" {0 K8 N& U' ], q+ h
  458.                 {
    6 o5 I0 |" X- n1 P% B  D
  459.                     /* encode a 0 bit followed by raw pixel byte */
    % h+ L3 n: X( Y6 y
  460.                     put_bits(pb, 0, 1);
    # ~; |. B7 _1 F0 z
  461.                     put_bits(pb, last_pixel, 8);1 I3 n- z/ o$ |9 a9 y7 p
  462.                     put_bits(pb, 0, 1);
    ) i0 `( M( I$ {$ _- O# X) U0 I
  463.                     put_bits(pb, last_pixel, 8);; e; P$ |# E  y' k
  464.                 }# K$ f* y! T5 e
  465.                 else
    ) y3 }3 }5 m) z3 U' }1 J
  466.                 {: b) }# i) o% A6 R# Y! a
  467.                     /* encode a 0 bit followed by raw pixel byte */
    * L/ X, B/ ~9 i" U% N0 r8 l9 d) B9 `  t
  468.                     put_bits(pb, 0, 1);4 |0 k1 H6 n/ z' Q
  469.                     put_bits(pb, last_pixel, 8);
    ; t0 X8 P+ S- U9 h$ _+ `) K
  470.                     run_size--;
    : i: b* _& B+ _" ]; C+ C
  471.                     /* encode a run: a 1 bit, followed by a back reference6 R+ P& Y* P  Z3 H. G3 ^- u7 J
  472.                      * offset (-1), followed by a length */1 s6 D/ U$ e8 M3 V  d: z9 K
  473.                     put_bits(pb, 1, 1);
    1 f& W" u$ T, s2 C% |  n
  474.                     put_bits(pb, 1, 1);  /* 1 = 7-bit offset */, m3 b9 Y3 B  O0 ?5 g# u
  475.                     put_bits(pb, 1, 7);
    , k6 u9 o" o! z& R/ E* v
  476.                     if (run_size <= 4)% B5 a/ G0 T$ `7 R
  477.                     {4 I# c- I3 O# W/ t- I6 S
  478.                         /* lengths 2, 3, and 4 are 2 bits */
    , S. y) o4 ]" i8 F1 z4 g
  479.                         put_bits(pb, run_size - 2, 2);" s9 d( W2 ]8 B2 \
  480.                     }% ^# Q3 s  T8 r; s
  481.                     else if (run_size <= 7)
    ; Z7 ~7 m* e2 p8 i
  482.                     {0 C8 V+ P4 a( S( K
  483.                         /* lengths 5, 6, and 7 are 4 bits */( _& t' i6 s- @3 f% j1 p8 N8 F
  484.                         put_bits(pb, run_size + 7, 4);
    7 {* H9 \, |2 C6 d
  485.                     }4 G5 B9 H) K* G# }6 L$ Z7 [' d+ J
  486.                     else* Y, q" m# C+ j" w7 o. X8 ^
  487.                     {' a( F' k/ l9 a4 _# z. `" \5 E
  488.                         /* arbitrary length; start by encoding 0xF which
    # f1 X8 ^3 x* T7 [& a2 \
  489.                          * stands in for an initial version of 8 */
    / D. p4 I# [$ P3 R/ ?3 ]- S- I
  490.                         put_bits(pb, 0xF, 4);# i7 U6 f& t  f+ q6 ?3 I1 A
  491.                         run_size -= 8;& z2 `' U+ B2 v, W* l8 m/ Z

  492. + F% n1 U- l- `0 B3 O( y
  493.                         /* encode blocks of 4 bits until run_size is 0 */2 L* g; O1 e! E) Z$ b" V
  494.                         while (run_size >= 0)
    ( [# M8 E. j. i/ a$ c/ X* x
  495.                         {
    1 [& m: y- i/ O$ b: X
  496.                             if (run_size >= 15)
    " J6 h; }+ h% L% @- N  j
  497.                             {4 a* J' Q* c/ @, G- p. V
  498.                                 put_bits(pb, 0xF, 4);& e: ?$ `" b5 P! a
  499.                                 run_size -= 0xF;
    % a' m/ Z3 n0 l- i9 U% F0 v! |
  500.                             }/ x9 W+ a5 N8 C8 Q+ [; @3 |
  501.                             else$ F* A* G$ ?* ]& H: R* o1 M
  502.                             {
      f# C" L+ ~$ f  L/ H% g2 m: b
  503.                                 put_bits(pb, run_size, 4);
    0 C$ H( a1 B$ g9 E
  504.                                 run_size = -1;, d; H( Q* l* B$ i
  505.                             }4 ?9 T$ n2 b. G
  506.                         }
    2 R) Q9 S, {; @3 {7 A2 p
  507.                     }, E5 o! q) F/ |+ p' \
  508.                 }
    ' |+ I- H8 ]$ O' H, ?2 L

  509. 2 Z2 M; D; I  Y# ~" X9 U
  510.                 last_pixel = full_window[x];
    / O& ^4 y# x* i4 Y5 ]. N; M1 e+ y
  511.                 run_size = 1;! y3 m& H0 |3 G; }; A. R. k$ y* E! j
  512. # e: c% s; W6 Q
  513.                 /* this single x iteration was only here to close the final run */! }, m$ q* s2 v" ?% v( H, E. ?
  514.                 if (y == window_bottom)6 S  k- D" G4 L. d! K
  515.                     break;3 d. U) b( R" P6 I& K
  516.             }9 C; B* v" p6 ?" D; a$ z
  517.         }
    ; q7 H  H5 w5 u
  518.     }
    ' P. \. E. m6 r+ {

  519. 2 s5 I7 \& m7 ~' K( X! @0 b
  520.     /* close the bitstream by encoding a back reference with length 0 */
    ) J0 K1 x/ w, `% _$ s6 v" w8 i$ O
  521.     put_bits(pb, 1, 1);  /* back reference run */; g; F; [- J$ a* Q5 {
  522.     put_bits(pb, 1, 1);  /* 1 = 7-bit offset */0 w$ t8 @; r; \
  523.     put_bits(pb, 0, 7);  /* length 0 */# q& J$ c! U( g" I

  524. ; H$ Q5 U6 v" o2 i
  525.     put_bits_flush(pb);& t- M+ v. [% T+ D, w- m
  526. }  w- h( Z) E+ V$ d* |
  527. % ?. b# E6 ~+ e" Z5 N5 J
  528. /* compute Euclidean distance between an RGB color and the desired target */
    0 H) S* a- k, o( e$ M; f
  529. static int compute_rgb_distance(int r1, int r2, int g1, int g2, int b1, int b2)
    $ _) B! B8 ~2 n' B$ R/ E
  530. {
    1 E* b$ C, N- d; t, i3 m$ [/ H
  531.     return sqrt((r1 - r2) * (r1 - r2) +
    . K& f& \3 q7 Y' x1 {# R( r
  532.                 (g1 - g2) * (g1 - g2) +
    : g. {3 B0 C5 }8 M" Q
  533.                 (b1 - b2) * (b1 - b2));
    7 Y. Y$ k+ r4 T- E/ l6 T5 d
  534. }
    + Q/ ]8 n- q- I* f
  535. 0 k) z4 h/ B1 \5 M& U
  536. static uint8_t find_nearest_color(rbt_dec_context *rbt, int r, int g, int b)
    / K5 o! z- N/ @7 H  R# g
  537. {
    9 G0 o8 J2 D" L5 v
  538.     int i;
    " n3 T* l8 W$ j7 |% e
  539.     int nearest_distance;
    2 S$ x4 S: i+ S- S. k  W' W/ c3 b
  540.     int distance;
    * U6 {* o; b& R
  541.     int rp;
    - J% f5 Z8 c  A5 }
  542.     int gp;
    4 a! u  H* t3 ^" l
  543.     int bp;
    6 b) g: h& N0 k- U7 u  b9 ]# u
  544.     uint8_t palette_index;) m6 u& j; S/ S; N  K/ u

  545. ! o7 P3 @0 _$ B  |2 R1 l
  546.     nearest_distance = 999999999;' }" {& D/ N1 m- R' [
  547.     palette_index = 0;6 \/ L+ d4 F5 r' N& C
  548.     for (i = 0; i < 256; i++)
    + J- f. n9 J' ^4 c( I
  549.     {
    ) c7 r: b4 P, |! G# A) w  D. u1 [
  550.         rp = rbt->palette[i * 3 + 0];6 ]! s4 t+ ^( `5 b1 ~( H! _% Q; F9 D' F
  551.         gp = rbt->palette[i * 3 + 1];
    9 w4 S. t1 w; A+ q% k+ f7 @) A
  552.         bp = rbt->palette[i * 3 + 2];7 @( E9 y) j  [, p4 s% B+ P# o
  553.         distance = compute_rgb_distance(r, rp, g, gp, b, bp);
    * d2 I2 Z( `* \: K  Z
  554.         if (distance < nearest_distance); t% q$ p( N7 S* ^; l8 S1 N
  555.         {+ m5 z  V4 x" Z0 `  E9 H
  556.             nearest_distance = distance;/ v9 Z/ P8 u# f2 d4 \
  557.             palette_index = i;4 k+ ?8 ~1 W$ h9 d
  558.         }
    9 W6 W5 G& L& N1 G; A7 u  D
  559.         /* can't get closer than 0; break early */
    + P& n5 s4 e* A* T' I2 g
  560.         if (distance == 0)- e8 C3 x5 D& c$ ]- m0 g; Z8 t2 B/ L
  561.             break;
    + ~. a: O* O6 q# |/ E
  562.     }* d/ x# a: Z. U. F. _  F

  563. , L  I( v1 \( s- d
  564.     return palette_index;
    ; C4 o' q/ z. t# e7 [' @) p
  565. }
    $ h) d, u2 P& X0 R
  566. ! [& e% ~8 z; M/ j, T2 v& w
  567. static void subtitle_frame(rbt_dec_context *rbt, uint8_t *frame,
    5 r# P: n- I1 x7 c
  568.     int width, int height, int timestamp)0 `8 t% j6 }0 K2 T
  569. {
    # W- s; R4 z4 V) D
  570.     ASS_Image *subtitles;2 E* U3 S; K- b* N* ^
  571.     int detect_change;# Z0 u% N# J- Y% U* ]8 P! m3 _+ D
  572.     uint8_t subtitle_pixel;: K1 [$ p7 F/ _
  573.     int x, y;
    % R. ~, S. i% i+ Y. x- F( ]
  574.     uint8_t *frame_ptr;
    & `4 k$ A+ C. a0 E& B
  575.     uint8_t *subtitle_ptr;! I$ i2 K! k: y5 C9 A7 \& q
  576. 4 q2 `" Z' F' F4 _, v3 Z' X
  577.     /* ask library for the subtitle for this timestamp */
      x+ @7 V- N8 \, M/ e
  578.     subtitles = ass_render_frame(rbt->ass_renderer, rbt->ass_track,7 Y3 E! s' ?% d( I- E; a# z
  579.         timestamp, &detect_change);5 `- {* I5 @- W5 ^
  580. 3 N; _3 `3 m! G$ f: b
  581.     /* render the list of subtitles onto the decoded frame */
      Q' x0 q/ k* J& P' D
  582.     while (subtitles)/ s3 k4 W. G" a& G; A
  583.     {, S# u+ ~: |& ^7 ?6 O  k! f
  584.         /* palette components are only 6 bits, so shift an extra 28 j* B# _; F; g. m0 e  q& ?
  585.          * bits off each component */
    ) h0 I' g! P! C6 n
  586.         subtitle_pixel = find_nearest_color(rbt,
    7 X$ G& K/ c3 U; q( P
  587.             (subtitles->color >> 10) & 0xFF,
    & S! S; \) W, V- C$ F4 _" G
  588.             (subtitles->color >> 18) & 0xFF,
    # C; y. V; ~" i4 X# t4 w
  589.             (subtitles->color >> 26) & 0xFF);$ J* _) m/ t/ S! l2 I% n
  590.         for (y = 0; y < subtitles->h; y++)
    - {# J) D' n- }: U" |
  591.         {4 o5 a7 x+ N5 E( G3 {
  592.             subtitle_ptr = &subtitles->bitmap[y * subtitles->stride];
    3 ^- s) i8 Y  d. o/ N$ F7 m
  593.             frame_ptr = &frame[(subtitles->dst_y + y) * width + subtitles->dst_x];
    2 A+ X5 A5 C4 Y0 G" c4 z2 \! }+ g
  594.             for (x = 0; x < subtitles->w; x++, frame_ptr++, subtitle_ptr++)# V- [4 _5 J/ q( z. Q* a
  595.             {
    3 A7 S( j/ T! |* E0 Z2 r
  596.                 if (*subtitle_ptr >= SUBTITLE_THRESHOLD)2 F+ ^, Z. ~  R1 F  B0 V# C; M4 k
  597.                     *frame_ptr = subtitle_pixel;
    / R* T7 A; r- t
  598.             }4 ^  q# s6 o$ W- g2 L
  599.         }9 U! \& C+ Z- J7 U( m7 R
  600.         subtitles = subtitles->next;
    5 p9 N. e* ?2 ~. M0 n4 G$ z
  601.     }, Y, d. v5 C% y1 {# F9 F
  602. }2 O$ L/ R1 N- x0 D' a" E* b
  603. * a5 }  X( d! s6 x) ~
  604. static int copy_frames(rbt_dec_context *rbt, FILE *inrbt_file, FILE *outrbt_file,3 k5 l% p$ h: T' Q, l
  605.     int origin_x, int origin_y, int window_width, int window_height)
    0 w( T, g; S5 C% A5 N. X( s
  606. {; B* M& G9 G- o
  607.     int i;
    0 R. Y% Z7 x, h$ i1 U9 p
  608.     int j;4 w* C2 e$ S* q. s* V
  609.     int scale;
    2 G: N6 x( H* h/ E' h/ z! z  t% C
  610.     int width;
    : R6 M  s2 X! L: Q3 m
  611.     int height;) N7 w8 y8 p, l) {$ J
  612.     int max_width;
    2 S! ], f! c5 Z
  613.     int max_height;6 @: t/ p/ P# L: d
  614.     int frame_x;
    : U, c. L3 M2 M' q7 b: q
  615.     int frame_y;4 D& ]' C7 w* K1 @8 f! ~
  616.     int fragment_count;) z; s& I' C. Q& H( b5 |
  617.     int decoded_size;
    1 k- e' x5 u- ~6 q, f& m. P: |
  618.     uint8_t *decoded_frame;
    ! B' n, u, V- g0 K) p6 l! I( [7 @5 L+ d
  619.     int fragment;; H! S4 N. \% X* [& b
  620.     int fragment_compressed_size;* Q; c& J( c& \/ u! |1 ~
  621.     int fragment_decompressed_size;
    : \& v5 m" |/ K% l3 n7 b
  622.     int compression_type;
    5 A2 [- c7 I& k! I- @
  623.     int index;$ L6 q- h$ ?4 _$ T. H6 v! A* ]
  624.     int out_index;5 `1 R/ ]. V! e$ c* Z  P
  625.     get_bits_context gb;" T: e9 h/ B( b% W! S
  626.     int frame_size;
    ! ?8 Z) J5 l. \
  627.     int video_frame_size;7 t6 t8 A0 `5 |
  628.     int audio_frame_size;
    / |7 u: C  M* F5 ^/ o2 f
  629. 1 l! Z+ G% E! A- f
  630.     int back_ref_offset_type;
    . U5 K6 N  g% |1 n
  631.     int back_ref_offset;6 P" C/ Z. i0 H7 }& U
  632.     int back_ref_length;
    ! B" F* |& X( d+ Z5 w
  633.     int back_ref_start;
    5 w; E$ {* |9 t$ B5 [6 N! @; o/ P
  634.     int back_ref_end;
    : e1 s! d: J9 l6 w" n/ p

  635. : ?6 N! D& p- S* _1 `- e
  636.     uint8_t *full_window;
    6 b) `# A- t' y; O  c" B$ e. h3 X: W9 Y
  637.     int full_window_size;* H0 M2 }$ R6 v  N; H! @
  638.     int y;& v# |+ j6 e4 b2 E! u! r
  639.     int window_top;0 g5 p+ Y/ V/ X5 B8 _% D, g
  640.     int window_bottom;
    , Q9 c/ y( i/ V5 z
  641.     int window_left;/ l  q) T$ [. h+ \0 R9 o
  642.     int window_right;, ]: T/ W" M) K% H% @2 J' T
  643.     int window_size;( ?4 d& X" {/ H, }
  644. 2 S9 e& z# n. ]+ _% J) C; f
  645.     char filename[30];* l! C( D' [$ ]. q( q) ]- Z9 u

  646. 8 ^" K8 f0 _& d4 E. M2 L1 P* w+ ]! {
  647.     put_bits_context *pb;( j: F4 b) a  Z$ M# q

  648. 0 [3 w0 e- }$ M; C* v: p
  649.     full_window_size = window_width * window_height;
    0 @& o! l9 j1 Q$ _( m& i% r1 T5 B
  650.     full_window = malloc(full_window_size);
    1 t  F) D; b/ ]" F7 S
  651.     pb = init_put_bits();% T+ g* C# I) H% w, J7 y
  652. . z6 d2 ^4 ^& B  c
  653.     max_width = 0;
    $ P  I/ p. b- t( ?0 P4 D  i
  654.     max_height = 0;: K& j! P# h: I

  655. 3 g& P+ M+ V& x* {) T
  656.     for (i = 0; i < rbt->frame_count; i++)3 [. Z8 i# z. M+ u, \1 V+ r  A: g
  657.     {) i) e7 ]9 k: b
  658.         /* read the entire frame (includes audio and video) */' a7 T( G6 U8 e  V4 J% I: u& m
  659.         frame_size = LE_16(&rbt->frame_size_table[i*2]);
    7 i, F/ Y2 a8 E4 f- }/ U! {8 ^$ Z4 z
  660.         video_frame_size = LE_16(&rbt->video_frame_size_table[i*2]);
    ( c* r/ ^" D% ^: f
  661.         audio_frame_size = frame_size - video_frame_size;
    5 Q, }% y8 p% z- K
  662.         if (fread(rbt->frame_load_buffer, frame_size, 1, inrbt_file) != 1)* J  Q+ x6 r) ~' O& S
  663.         {
    9 }7 n' Q0 ^2 @  \4 @7 ?; U
  664.             printf("problem reading frame %d\n", i);
    : g  u2 p& B1 Z+ S
  665.             return 0;. |0 F' ~- m1 `$ u
  666.         }$ c$ X7 N" G0 [' {. T/ T3 X6 }
  667. " P6 ^1 g" {! M6 A: R
  668.         scale = rbt->frame_load_buffer[3];
    & O3 c. U# z4 ?- u
  669.         width = LE_16(&rbt->frame_load_buffer[4]);* F0 j5 K8 {  h3 W
  670.         if (max_width < width)
    5 c& S9 {/ M6 t/ C4 z
  671.             max_width = width;5 x3 s; }* H; ?9 k5 |
  672.         if (max_height < height)
    # O3 c) \) f( @" S# V
  673.             max_height = height;
    # [7 J6 H+ F' k+ k
  674.         height = LE_16(&rbt->frame_load_buffer[6]);
    3 V5 @5 [! K+ J- K! \7 y
  675.         frame_x = LE_16(&rbt->frame_load_buffer[12]);
    7 e. E8 q. F1 |
  676.         frame_y = LE_16(&rbt->frame_load_buffer[14]);" m. e4 E# k$ N
  677.         fragment_count = LE_16(&rbt->frame_load_buffer[18]);9 H5 H8 N9 c. l( W; Y0 M
  678.         decoded_size = width * height;4 c7 v: M8 |4 c$ [+ r' o$ Z) d5 T
  679. 5 a7 x( M/ _+ h  o4 O% N1 P. F9 u
  680.         printf("processing frame %d: %d%%, %dx%d, origin @ (%d, %d), %d fragments\n", i, scale, width, height, frame_x, frame_y, fragment_count);; D' G& U& P, f4 g4 N1 k1 B
  681. 2 R4 d: d+ I) h) V2 W! n8 M
  682.         /* decode the frame */' J$ c4 N# u& F# O
  683.         decoded_frame = malloc(decoded_size);
    $ g; l. ~  f, Y  k9 @' {# T2 A
  684.         index = 24;
    + r# G) b% B# S
  685.         out_index = 0;
    ; J9 r% ~/ u* X# M$ a
  686.         for (fragment = 0; fragment < fragment_count; fragment++)  b& b2 s- H$ p, Z
  687.         {
    9 t& R  y% G2 ~  {% t
  688.             fragment_compressed_size = LE_32(&rbt->frame_load_buffer[index]);
    2 u2 h0 T* J& E# y1 Y+ g/ q# N
  689.             index += 4;
    & E/ ]: m1 L% ~5 r$ B4 H
  690.             fragment_decompressed_size = LE_32(&rbt->frame_load_buffer[index]);
    # Q3 U0 l4 x2 p: x" |
  691.             index += 4;
    * D- ~. b8 j# u* @
  692.             compression_type = LE_16(&rbt->frame_load_buffer[index]);4 b0 I8 W& w2 y  r1 v
  693.             index += 2;6 T) l5 x9 t( H+ p$ }
  694. 0 G: ]4 h- n& D5 l# f
  695.             if (compression_type == 0)
    8 A) g/ y# |" }  W1 ~- y
  696.             {7 f' K0 e1 m3 h( Q6 [( i
  697.                 init_get_bits(&gb, &rbt->frame_load_buffer[index],
    + L/ Q9 `9 h( j) L
  698.                     fragment_compressed_size);
    $ a5 T6 f* q3 ~/ K# S

  699. : P; F/ F- D" s: w
  700.                 while (out_index < fragment_decompressed_size)  Y+ X# ~, T* S+ U% b
  701.                 {5 ]' Z) M# q+ X; D1 r7 J( u, M$ v
  702.                     if (read_bits(&gb, 1))
    7 A/ C! g4 }# ?) ~) g2 g! \% ?" w
  703.                     {% U4 \  g1 `+ @! {- }
  704.                         /* decode back reference offset type */
    3 `- Q, ~% v0 @
  705.                         back_ref_offset_type = read_bits(&gb, 1);+ K, g3 H5 {' d+ D

  706. : L9 }* l" Q% k$ d
  707.                         /* back reference offset is 7 or 11 bits */
    4 I3 T- t" c$ }) G6 E
  708.                         back_ref_offset = read_bits(&gb,6 n! Z/ Y) j9 r) e. G
  709.                             (back_ref_offset_type) ? 7 : 11);
    6 z! M$ L  K# a. Z* S0 B! q( ~
  710. 2 O% q7 m4 _4 w1 y# [
  711.                         /* get the length of the back reference */6 p5 e  p: n1 }+ U. o
  712.                         back_ref_length = get_lzs_back_ref_length(&gb);; h; X! f! ]7 \5 y
  713.                         back_ref_start = out_index - back_ref_offset;
    % q$ i' U$ k) Z* w
  714.                         back_ref_end = back_ref_start + back_ref_length;
    " u8 v) x. |, @! t! P0 {) I) S- c

  715. 6 g3 I% _) {% o6 Q
  716.                         /* copy the back reference, byte by byte */
    6 T* O: T1 V# Q; d, Q, i9 Q
  717.                         for (j = back_ref_start; j < back_ref_end; j++)
    5 _( z  H, V3 ~- L0 v8 y5 a
  718.                             decoded_frame[out_index++] = decoded_frame[j];% {3 c, y* n6 h- p  r( z
  719.                     }/ f, k% p, }3 \# g0 b9 p$ B
  720.                     else
    ; ~! k- f/ w, O/ o7 o- y
  721.                     {. e/ R2 t8 W: T9 H4 N/ v) b1 F
  722.                         /* read raw pixel byte */( V+ ^) O) Z' S* k+ N3 i. D
  723.                         decoded_frame[out_index++] = read_bits(&gb, 8) & 0xFF;
    & L! U4 _  Y$ B' I7 \
  724.                     }" ]: B1 W9 O! F5 P. ~5 F* b! j
  725.                 }
    8 R! D4 u5 X' @( n6 d

  726. 3 t; A- D9 O+ ~: y
  727.                 delete_get_bits(&gb);  w+ ^( E) u# o
  728.             }! k! A( _+ Z3 J

  729. * `9 ]4 k' Z+ U, E. d" @/ f
  730.             /* next fragment */' F2 _8 l$ V9 M1 G
  731.             index += fragment_compressed_size;
    ' s$ C$ M. k: a  m
  732.         }
    . x" C, }$ \9 i7 D

  733. 0 H! J! y/ D# A( Q  K- o
  734.         if (rbt->dump_frames)
    " z2 O$ L7 ~+ i9 ]! e
  735.         {; ?+ z4 F7 S4 c% ^1 v: K& Q1 G+ J
  736.             /* dump the original frame */
    5 I! v# m) _' l6 M
  737.             sprintf(filename, "original-frame-%03d.pnm", i);
    ( m6 V& G9 ^- |. M+ }
  738.             dump_pnm_file(filename, rbt, decoded_frame, width, height);
    ; F" i- u* h: d% I
  739.         }
    , J" p: k! O5 Z- U, u6 ?; K$ u1 k+ j. }
  740. 2 h9 k) c' {: A. _3 Y' S
  741.         /* transfer the image onto the frame window */
    ; J1 q. i& s. z, M" D& C+ v
  742.         memset(full_window, 0xFF, full_window_size);
    $ N0 V6 g% g- y' a
  743.         index = 0;- S* j& c% T/ F/ R, c& \
  744.         for (y = 0; y < height; y++)6 k+ X! f5 p* q3 w2 P+ M8 e$ }0 v
  745.         {/ K5 I! B' ?9 O, m. h- _8 t
  746.             out_index = window_width * (frame_y + y) + frame_x;
    & \* Q" H+ a9 C% Y8 X
  747.             memcpy(&full_window[out_index], &decoded_frame[index], width);
    , E, b2 L( S. t! T' v
  748.             index += width;# i9 y. [" I$ T0 Y
  749.         }9 _9 O1 y- p) A2 S! r! S6 ?1 F& D

  750. 5 B9 R. D6 `  H( k" l
  751.         /* write the subtitle */4 Y1 w9 E! e1 A+ S
  752.         subtitle_frame(rbt, full_window, window_width, window_height,( h- W3 \1 B! q0 }9 E
  753.             i * MILLISECONDS_PER_FRAME);# ]+ [+ Y. F( s- C# l1 _
  754. " g1 y) k/ X. P1 F: P2 v8 {, e! p
  755.         /* figure out the smallest change window */
      I: U. g3 g" ^6 ?
  756.         window_top = frame_y;
      X6 [  I6 L6 R* S
  757.         window_bottom = window_height;( K% z' p& m7 B% J
  758.         window_left = 0;( w. C: m) e' F! W: `* ^; t
  759.         window_right = window_width;9 h$ X( C9 X" J
  760.         window_size = (window_right - window_left) * (window_bottom - window_top);$ d  W# c: ^8 i, p. N2 v! R; R* D
  761. , Z0 f5 n. z( {: X, @1 \; J7 O
  762.         /* compress the frame */8 a# @5 r$ U, H* R+ E# X7 q
  763.         reset_put_bits(pb);7 C2 r5 n' F- v9 L9 G+ R' X: g, s
  764.         compress_window(pb, full_window, window_width, window_top,
    5 q7 n& e. ]  ^+ N7 ~
  765.             window_bottom, window_left, window_right);
    $ U$ S) q3 ^$ G$ \
  766. ) W2 H+ w3 u7 |/ ]/ S7 A
  767.         if (rbt->dump_frames)
    ) W% ~, Y( I# k
  768.         {
    9 h& d, p  D& H0 u7 j
  769.             /* dump the frame plotted onto the full window prior to encoding,8 {5 _9 }) v) p
  770.              * with subtitle */( A% O2 i# e4 [* B' b$ L) v
  771.             sprintf(filename, "pre-encoding-frame-%03d.pnm", i);
    % O& r& H; Q0 o" e
  772.             dump_pnm_file(filename, rbt, full_window, window_width, window_height);
    ) a0 i( l+ X8 Z% G* v+ Z: I
  773.         }
    , R! h' E' V# F  o, z
  774. 7 ?) K/ y4 H: t2 x! F
  775.         free(decoded_frame);# M# i6 D0 _/ `6 ?5 N: k6 z

  776. + s5 @) m: Y' i
  777.         /* update the frame header */1 G1 y. v. P3 c: }
  778.         /* width */' t9 l% K9 O9 S" @. }$ P6 O
  779.         rbt->frame_load_buffer[4] = (window_right - window_left) & 0xFF;& h6 ~  t: n8 O: N2 A, }* ]
  780.         rbt->frame_load_buffer[5] = (window_right - window_left) >> 8;
    2 A. T. T" H: D/ q# ], g) y; l
  781.         /* height */0 d/ ?( j. P$ x, ]5 D( U; V& D
  782.         rbt->frame_load_buffer[6] = (window_bottom - window_top) & 0xFF;
    ! [$ I8 m6 C1 y) ^4 J4 J; E* I' p# ^
  783.         rbt->frame_load_buffer[7] = (window_bottom - window_top) >> 8;
    * d* t( L- K" j- i! @# h
  784.         /* origin X */
    " z# a, U! r' f% A; m
  785.         rbt->frame_load_buffer[12] = window_left & 0xFF;" X* L% x+ `7 v7 M
  786.         rbt->frame_load_buffer[13] = window_left >> 8;+ Z  ]' @1 x6 ~, Q0 |& K- D
  787.         /* origin Y */
    + \. n: x, I9 s3 R- w  s4 C: h
  788.         rbt->frame_load_buffer[14] = window_top & 0xFF;
    * K# B: t* g% |+ h% }3 Y) z
  789.         rbt->frame_load_buffer[15] = window_top >> 8;
    + @" D$ I1 @2 _( g1 A9 X) \
  790.         /* fragment payload size */0 L/ ~8 u8 P% W; Q' k
  791.         rbt->frame_load_buffer[16] = (pb->byte_index + 10) & 0xFF;
    4 J  q+ Y1 ?# u9 j  C3 R; {4 }
  792.         rbt->frame_load_buffer[17] = (pb->byte_index + 10) >> 8;5 a+ l5 u% C1 k- X% r- X
  793.         /* fragment count (1) */( [& L2 E7 q. M1 P# w7 {
  794.         rbt->frame_load_buffer[18] = 1;9 N9 t0 ?. w" p
  795.         rbt->frame_load_buffer[19] = 0;  J% b6 b. E! N8 ]! z

  796. $ B; @. k/ S+ k+ N
  797.         /* update the fragment header */- D( ]: w- ]( c" T# M
  798.         /* compressed size */
    % o; u7 k+ d  U/ f$ O
  799.         rbt->frame_load_buffer[24 + 0] = (pb->byte_index >>  0) & 0xFF;+ ^- ^( Q' R) Z. W, {) {
  800.         rbt->frame_load_buffer[24 + 1] = (pb->byte_index >>  8) & 0xFF;  b; i/ G( z3 N2 ]+ Z2 ]- K1 q
  801.         rbt->frame_load_buffer[24 + 2] = (pb->byte_index >> 16) & 0xFF;/ i) b0 Q( S7 @0 D8 l+ z
  802.         rbt->frame_load_buffer[24 + 3] = (pb->byte_index >> 24) & 0xFF;8 a! @" g6 G% [9 i, t  W
  803.         /* decompressed size */
    7 I" _- X; T7 E  o/ F1 @
  804.         rbt->frame_load_buffer[24 + 4] = (window_size >>  0) & 0xFF;
    + F5 X! J  |% r, O5 Q$ I
  805.         rbt->frame_load_buffer[24 + 5] = (window_size >>  8) & 0xFF;% |4 L; o1 a* @) {1 [3 A7 O9 v
  806.         rbt->frame_load_buffer[24 + 6] = (window_size >> 16) & 0xFF;
    ( a+ Q# q' {" u" j# W9 Z7 S/ e3 O
  807.         rbt->frame_load_buffer[24 + 7] = (window_size >> 24) & 0xFF;
    % _/ k9 m4 x# L, D
  808.         /* compression format 0 *// A$ Q- l$ ?& N: Y, Z
  809.         rbt->frame_load_buffer[24 + 8] = 0;& N9 U; J' R; {, D8 a9 d
  810.         rbt->frame_load_buffer[24 + 9] = 0;/ n4 h7 F* V! E

  811. $ o6 I$ m  F6 C# V' ]
  812.         /* write the 24-byte frame header and the 10-byte fragment header */: K" J0 {- J9 Y* h7 ?; i
  813.         if (fwrite(rbt->frame_load_buffer, 24 + 10, 1, outrbt_file) != 1)
    ( r7 D- B5 F# c% W* W* _: q( h
  814.         {# e8 k8 N$ l2 r5 H" a9 |
  815.             printf("problem writing frame %d\n", i);4 F8 v' ~0 ?. N! P/ P; s
  816.             return 0;
    " Z/ s5 I1 E7 [1 [
  817.         }: j& L) t( C" k: Z( E
  818.   P0 y- {: ]0 u- e3 P7 r3 O9 h
  819.         /* write the new compressed frame data */% J) t# ~, b" x, F
  820.         if (fwrite(pb->bytes, pb->byte_index, 1, outrbt_file) != 1)
    & G* D. a5 M6 L* E: }
  821.         {; e$ R4 ~! L; f" F# {0 [! E- a
  822.             printf("problem writing frame %d\n", i);8 V) c2 t+ }& Y( D0 o
  823.             return 0;: d5 ~3 n  H& p! G6 [
  824.         }
    / `" [$ I' w, e& n

  825. " P4 B% E2 |1 R& w0 o4 O$ N8 w
  826.         /* write the audio data */
    * j% w! Q% Z5 E( D! Y3 d7 u0 m
  827.         if (fwrite(&rbt->frame_load_buffer[video_frame_size], frame_size - video_frame_size, 1, outrbt_file) != 1)
    + ?) C/ f7 S5 \; f/ w( w( \% q8 j& f
  828.         {- {2 P9 b, w6 m2 h: I
  829.             printf("problem writing frame %d\n", i);
    1 D9 Q( ~0 O! O& y
  830.             return 0;
    ' b% W! f! q4 ?; F  N
  831.         }% C5 z+ a, L, _
  832. % _$ [# G8 Z% j' h9 N
  833.         /* update the table entries */
      r" q; C$ y) U, G0 g) U1 f3 @
  834.         video_frame_size = pb->byte_index + 24 + 10;" R. I/ x1 U, `7 l$ l
  835.         frame_size = video_frame_size + audio_frame_size;
    2 y4 }. o& b  O: c
  836.         rbt->frame_size_table[i*2+0] = frame_size & 0xFF;
    $ ]3 R: V4 j9 L* }3 @- w" m) g
  837.         rbt->frame_size_table[i*2+1] = frame_size >> 8;
    0 o3 T7 E$ ^; D- b
  838.         rbt->video_frame_size_table[i*2+0] = video_frame_size & 0xFF;
    4 w3 z8 S9 |( W/ `$ c6 E
  839.         rbt->video_frame_size_table[i*2+1] = video_frame_size >> 8;. s. ?+ o* K- Q/ G% D. `
  840.     }) D, d% o3 r8 O
  841. 8 h6 q$ C) {9 |# ?" }& ~
  842.     printf("maximum dimensions seen are %dx%d\n", max_width, max_height);
      n) Q7 O  M3 Y2 G
  843. ' x, |+ \% j; B' s6 v# f
  844.     delete_put_bits(pb);
    0 z( ?8 A* w7 @7 r  k3 E" |; @
  845.     free(full_window);+ S  g8 Q5 n+ r0 s, w' Y
  846. - U$ L. [2 s7 m' ]
  847.     return 1;0 y8 `" Z: A! x8 u9 V0 h
  848. }
    - [. L# p/ l$ K. p

  849. " ]+ u; q" @) A2 V% c9 p& ]" S9 A
  850. int main(int argc, char *argv[])
    - ~. f7 X' q+ x( N+ o
  851. {7 ~- T* p$ d: l, L
  852.     char *subtitle_filename;& D2 f. d5 ]7 J$ G/ f# [
  853.     FILE *subtitle_file;6 Z4 M' m5 R' n$ [$ y* z
  854.     char *inrbt_filename;
    1 o! T6 b$ K6 k, p% p: v
  855.     FILE *inrbt_file;
    0 c, g: p  J! R0 d6 g' ~
  856.     char *outrbt_filename;
    ) O0 D0 j3 i8 M7 C; D6 l
  857.     FILE *outrbt_file;2 h) ~5 E- s/ H5 c& o
  858.     rbt_dec_context rbt;
    ; ]6 `5 B/ E7 h9 L. G
  859.     int origin_x;1 v& L3 ~) V3 E9 u. S/ h
  860.     int origin_y;* Q  }" N+ ]1 \. E- x. z) A1 F
  861.     int window_width;
    / q+ ]8 x) R' a7 P$ Q# b/ C
  862.     int window_height;& T/ |  U! j  @2 Q
  863. / q! f5 N( C* Q) \% F  y
  864.     /* testing the bit functions */1 f4 ~: j0 ]  t* T
  865. #if 0
    $ z( v" C; D  D: e4 b8 B
  866.     int i;
    5 l8 {6 w0 ~) L/ [
  867.     uint8_t bytestream[] = { 0x55, 0xAA, 0x00, 0xAA, 0x55, 0x77, 0xFF, 0x1B, 0x70, 0x8F };
    # Y) F* {2 a: `" m
  868.     int bytestream_size = 10;, N8 M3 b1 @9 A
  869.     get_bits_context gb;
    4 m& J1 {/ `9 ?& n
  870.     put_bits_context *pb;
    0 _$ e. h0 t/ S
  871.     int bits;
    " N% y* Z! d" k) k  k" L2 N5 p

  872. , U9 W1 }2 b- \1 D
  873.     init_get_bits(&gb, bytestream, bytestream_size);0 n* M7 Q8 D- c# y! t
  874.     pb = init_put_bits();* p2 R. E3 A1 T1 J1 V7 b

  875. ) s  w$ ^7 d1 z
  876.     for (i = 1; i <= 12; i++)! N+ V' a5 G! |3 d' u, T, R
  877.     {
    4 y( ]: D. d# w  Z) K8 W9 a
  878.         bits = view_bits(&gb, i);" s% S2 J+ b8 v8 L, [5 e
  879.         printf("view %d bits: %d\n", i, bits);( J! @$ M9 C" |0 R6 ^1 Z1 t# d! [
  880.         printf("read %d bits: %d\n", i, read_bits(&gb, i));
    - L; J' U+ t8 o8 Y; U
  881.         put_bits(pb, bits, i);
    ( [. x: Z; t& Z) x1 S, p; r# A, }8 F0 O
  882.     }
    8 t% B5 k. \# Z: V8 D5 R1 d
  883.     put_bits_flush(pb);4 q( ~9 X+ z9 b" `0 @; b, H5 H

  884. * S4 F1 B+ O- @/ x2 {4 h
  885.     printf("original bytestream:\n");, E( x$ A/ O. J. `6 O+ ?
  886.     for (i = 0; i < bytestream_size; i++)6 K  l- i8 B' d8 E& r* T
  887.         printf(" %02X", bytestream[i]);
    6 m4 V9 w; l4 ~) r: m( X- A
  888.     printf("\nnewbytestream:\n");; N! V/ X4 {+ O" K$ }# A0 h' r
  889.     for (i = 0; i < pb->byte_index; i++)
    ' y: T$ b: n# r7 M8 H
  890.         printf(" %02X", pb->bytes[i]);  }+ V8 b8 E0 T/ B! l
  891.     printf("\n");" Y5 g& D. r! S7 U3 |) D+ O: O; U

  892. $ W& }# q, L! s& |& s' l
  893.     delete_get_bits(&gb);
    8 f$ o7 W. o+ v, I; n% U
  894.     free(pb);
    9 h, L3 c2 c: @' u3 s8 y7 t, `
  895. #endif( j1 W( H% [' E" c9 E7 i; O3 [3 s

  896.   ^8 S1 S% n: _- U% f1 M4 k7 Q
  897.     /* validate the number of arguments */
    # h- f' f9 O/ M$ e) W; A5 n/ y2 R
  898.     if (argc != 8 && argc != 9)
    " V& ?) @* Z: l% a( E
  899.     {
    ; t% [. N$ I, w: C
  900.         printf("USAGE: subtitle-rbt <subtitles.ass> <in.rbt> <out.rbt> <origin X> <origin Y> <width> <height> [dump_frames]\n");. b/ Q0 [/ D% w  M
  901.         return 1;
    : [* }5 D& v3 g" t
  902.     }% k5 R1 O- N! ?6 d/ _5 l* H+ c
  903.     subtitle_filename = argv[1];2 S) P  I. k$ Y2 {" V0 S
  904.     inrbt_filename = argv[2];
      h4 X9 [0 b% F! M% C* j$ p
  905.     outrbt_filename = argv[3];6 R% y& {9 f* p6 k" ]4 S0 D
  906.     origin_x = atoi(argv[4]);  G) m) g+ F; ~; y
  907.     origin_y = atoi(argv[5]);4 q% @; U( U+ \8 H; _; U# T* _
  908.     window_width = atoi(argv[6]);3 b( k* M* T8 u3 f
  909.     window_height = atoi(argv[7]);) U- R' b: A5 q! Y2 [; o
  910.     rbt.dump_frames = 0;4 H. f/ _, X! K0 G. w  @
  911.     if (argc == 9)1 o! C5 R6 Q) i: r3 u8 r0 c
  912.         rbt.dump_frames = 1;
    ; C) ~8 b6 F, p8 q1 f; s/ |% r
  913.   E* g1 n4 ?3 G
  914.     /* verify that the specified input files are valid */
    6 K! Z3 g- M$ {- d( L
  915.     subtitle_file = fopen(subtitle_filename, "r");! O8 O* A, q2 `" u1 |  h6 N2 q+ t3 t
  916.     if (!subtitle_file)
    , B' Y4 ~4 @4 p0 s. Q" E7 T
  917.     {
    : a3 p5 Z* o& K) a! u
  918.         perror(subtitle_filename);
    . q% v3 n% o" L+ g# g5 g' `
  919.         return 1;
    ) X" J$ G( C2 D, R7 M
  920.     }
    $ W$ R1 ~; Q5 L& N  J" l' X
  921.     fclose(subtitle_file);% _+ l9 X/ g: z8 a& A
  922.     inrbt_file = fopen(inrbt_filename, "rb");
    1 w& Z2 W4 ?4 O0 E* F& P: m  h
  923.     if (!inrbt_file)
    ) u" x3 p0 B! M. w9 U
  924.     {: z5 E1 O5 W4 Y0 W( i0 h
  925.         perror(inrbt_filename);
    1 w3 v, P' O- b; i* o
  926.         return 1;
    ) S! i. t$ k$ M! c
  927.     }
    ! n' Q6 o5 m6 _9 V/ J+ p. k% U

  928. 3 i1 |9 {! b( C
  929.     /* initialize the subtitle support */
    # L1 o) B& D9 I+ b! c
  930.     rbt.ass_lib = ass_library_init();2 q1 a* @( {$ y8 Z" x) W
  931.     rbt.ass_renderer = ass_renderer_init(rbt.ass_lib);
    - H) M) c/ R; B0 q7 c
  932.     rbt.ass_track = ass_read_file(rbt.ass_lib, subtitle_filename, "UTF-8");3 |4 y$ q+ q9 b" c5 v; b! j, D
  933.     ass_set_frame_size(rbt.ass_renderer, window_width, window_height);; {  ]9 I3 l7 d" H& v
  934.     ass_set_fonts(rbt.ass_renderer, NULL, NULL, 1, NULL, 1);
    ' q- H7 F" O  e' N! @2 u- K0 U# ]

  935. 9 {9 p+ V0 {7 c, F% }
  936.     /* open the output file */
    " j; A$ J5 p. w$ ]) t& ?- g
  937.     outrbt_file = fopen(outrbt_filename, "wb");9 y  o  |$ X( a' [5 T" w
  938.     if (!outrbt_file)
    / j) i4 k- Y' N; D
  939.     {
    # K: A9 i& V) K- y! z# z0 T
  940.         perror(outrbt_filename);
      E  q) n5 L* o3 ]/ \8 U" g: g
  941.         return 1;
    / y" P$ V* N( y& ~% t
  942.     }
    7 s* @4 c! _- G- n6 H5 u$ s; ]
  943. ) h( D0 n- N& b- v: B
  944.     /* transfer header from input to output */5 p+ Y8 ~* h7 S0 q  }
  945.     if (!load_and_copy_rbt_header(&rbt, inrbt_file, outrbt_file))
    1 d( @$ L0 q, E, T4 s" M
  946.         return 1;
    7 X, p8 w# s2 R- Z; h
  947. / [9 B7 P7 Y/ X0 B, y# U
  948.     /* rewrite the frames */+ `# O! t- F- {( b- I# e3 B8 }$ r- e
  949.     if (!copy_frames(&rbt, inrbt_file, outrbt_file, origin_x, origin_y,
    - M3 |% X7 g9 c9 W: G6 s
  950.         window_width, window_height)); }, N& e# @) L- S/ i3 s
  951.         return 1;
    * _/ e9 P' A+ n7 o) q5 d* h6 v# n
  952. 5 d/ P. g' u' Z5 m) `: d: _  h
  953.     /* write the modified frame size tables back to the file */  z% `6 O, G- {/ x
  954.     fseek(outrbt_file, rbt.video_frame_size_table_offset, SEEK_SET);3 ?, ]2 o# z" |# y" v/ z
  955.     fwrite(rbt.video_frame_size_table, rbt.frame_count * sizeof(uint16_t), 1, outrbt_file);
    ; Y8 n" ~( J3 t4 u. s/ h
  956.     fseek(outrbt_file, rbt.frame_size_table_offset, SEEK_SET);0 _5 c$ a8 s: V+ R, A
  957.     fwrite(rbt.frame_size_table, rbt.frame_count * sizeof(uint16_t), 1, outrbt_file);
    ' h! R4 m% b( B9 N6 e

  958. 9 N. {$ s) P' N5 R
  959.     /* finished with files */( K" X4 I, A3 Y; g
  960.     fclose(inrbt_file);
    " E8 R: m8 V) ]0 t
  961.     fclose(outrbt_file);  @) W* K8 T' l/ X1 n8 a
  962. % A, v8 y! a2 @' O9 }
  963.     /* clean up subtitle library */1 v8 A& d6 Z- Q+ Y
  964.     ass_free_track(rbt.ass_track);
    8 K6 ^  p" N* u% m3 ]
  965.     ass_renderer_done(rbt.ass_renderer);  U5 a! V) G9 R$ s% D: O, p# o3 I
  966.     ass_library_done(rbt.ass_lib);
    % H, ?2 j; N, U: C, E
  967. $ d9 A! o$ l  p& ^  @& Y0 u
  968.     /* clean up */8 [7 C7 h0 s* l* ?
  969.     free(rbt.frame_load_buffer);2 D2 z  v# N4 _' x0 M/ i
  970.     free(rbt.video_frame_size_table);( ~* _& s5 }- J0 {; V
  971.     free(rbt.frame_size_table);
    5 j) h* S3 T& r5 ^
  972. ! B5 E+ a8 o; K9 ]% ^* f1 R
  973.     return 0;& _$ p- b8 `; }' a' J9 ?( Z
  974. }
复制代码
  O& Q/ }1 r% s) u5 E: c; y) K
( h  I5 w5 \) w/ D

9 ?8 ?) Y  N7 T2 {3 I: v1 e
) U" N- j3 J/ G8 Y4 d; X
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 很美好很美好 很差劲很差劲
回复

使用道具 举报

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

使用道具 举报

板凳
 楼主| 发表于 2009-11-19 11:38 | 只看该作者
引用第1楼soring123于2009-11-19 11:09发表的  :$ E; Y2 n( z8 U( I; Y
这游戏有字幕吗?

, L. s4 Y+ x5 @2 E5 }好像没有字幕,我说的是给视频外挂字幕方式的汉化。7 B% ?* s& w; T' }0 x1 v
就像syberia2汉化版下面那行字一样。
回复 支持 反对

使用道具 举报

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

使用道具 举报

5#
 楼主| 发表于 2009-11-19 17:39 | 只看该作者
引用第3楼soring123于2009-11-19 17:07发表的  :
5 M* \+ {6 J$ ]* \7 l我记得是没字幕的 比较麻烦 都是视频的

, J' J* F5 x. Q) V6 T给视频外挂字幕方式汉化也许能行。
9 J; m5 N0 W0 f5 x' f3 {要结合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日,是全球华人共同的冒险解谜类游戏家园。我们致力于提供各类冒险游戏资讯供大家学习交流。本站所有资源均不用于商业用途。

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