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

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

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

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

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

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

本帖最后由 shane007 于 2021-1-2 13:56 编辑 ! P' G* G8 o8 Q1 c

) e2 }& X5 [8 A; s最近找到了一些和幽魂系列Phantasmagoria 有关的资料,/ w* S2 v, u0 f  y9 q( N) J
也许将来可以用于汉化。/ N+ _# a% H, P0 T5 z# {( T, F

/ V0 Q* x. g1 e+ G和日文版有关的信息& n9 Y+ C( T8 |1 N. C
http://anthonylarme.tripod.com/phantas/phintgtp.html
" B/ C/ Q6 n* z  j* T3 h" J* ?8 G+ D0 j5 U: V  r( C" S- f
相关工具& w$ ]4 }& n2 d
http://anthonylarme.tripod.com/phantas/phcheats.html
' h3 @$ \) m5 F-----------------------------------------------------------------------3 `4 h' S' n) X& \/ _$ j
2012/1/2  更新
$ \) f: _1 H1 A关于幽魂游戏的字幕
$ E7 J" J0 b" ?& R8 bPhantasmagoria subtitles function discovered - ScummVM :: Forums
0 @7 W3 k4 b# C- A! t8 F8 J: h1 _9 x4 F" N3 q, n! h1 }" v* F
VMD文件/ T4 t( A; V- h3 o, Z  {. J
Subtitling Sierra VMD Files | Breaking Eggs And Making Omelettes (multimedia.cx)VMD - MultimediaWiki# R9 ~8 g5 B& v& O" C( a
# ?6 o3 c  i3 V( |! L6 |8 E
字幕$ {4 d3 J' a" ?' ~
Subtitling Sierra RBT Files | Breaking Eggs And Making Omelettes (multimedia.cx)
0 `5 M& Q. a8 _* d# b
, H' R' c2 n5 f7 s1 u8 ]3 i# BFFmpeg/subtitle-rbt.c at feature/VMD_encoder · multimediamike/FFmpeg · GitHub, \# h# Q( X7 M1 t
  1. /*
    , b# g' O0 ?) p+ n: c
  2. * subtitle-rbt.c
    9 B" W- _, R& l) ?: z. C
  3. *  by Mike Melanson (mike -at- multimedia.cx)
    , k* V9 f1 W; M# k/ m# u
  4. *
    - l) T) q! f3 g- q6 F! }
  5. * build with this command:# N5 a6 I- e% x% ~( R) [
  6. *   gcc -g -Wall subtitle-rbt.c -o subtitle-rbt -lm -lass/ ~) Y. c/ w/ j6 ~/ s1 Q! J6 K
  7. */
    7 @% a% N' a: f8 ]8 D

  8. ' n$ r0 C. D( q/ w
  9. #include <inttypes.h>
    $ ~, z: H4 S" O% g5 p
  10. #include <math.h>( j8 {3 h/ p$ L6 z) M
  11. #include <stdio.h>
    ! h0 u+ E3 n- p+ A: J$ {( N2 c
  12. #include <stdlib.h>9 L" K- \' d5 o/ n  G0 |
  13. #include <string.h>
    " s; `2 f) Z- E, Y

  14. . s4 C) \0 T( o6 M+ @
  15. #include <ass/ass.h>
    0 X0 O* h, f  g8 P4 O2 d
  16. 2 K4 J; G$ V* @) W0 d' I
  17. #define LE_16(x) ((((uint8_t*)(x))[1] <<  8) | ((uint8_t*)(x))[0])6 v' H7 j. `9 S8 @5 p2 {

  18. % o1 s* d5 {' w+ t2 J" C$ ~0 s
  19. #define LE_32(x) (((uint32_t)(((uint8_t*)(x))[3]) << 24) |  \) M0 A+ r" o: m$ Y- Y: [+ H
  20.                              (((uint8_t*)(x))[2]  << 16) |  \
    * p" e* u3 o3 ^  V1 P% X& Z+ X
  21.                              (((uint8_t*)(x))[1]  <<  8) |  \% l% g  y2 i4 @
  22.                               ((uint8_t*)(x))[0])
    . \8 D. G. S7 ]0 B/ F) r
  23. ; S: f+ P; s2 V9 F5 D
  24. /*********************************************************************/" s4 G5 y: O, Y2 m, z' Y

  25. / ~7 A& N* E2 A& b4 x
  26. /* Bit reader stuff */( v# n8 C/ ^) E2 G( k) Q

  27. 6 f1 R9 U% V$ U
  28. typedef struct
    + Q1 `; v- Q9 G' o
  29. {! S; c: R0 ]; v
  30.     uint8_t *bytestream;
    8 A1 B& s4 ~+ \2 \
  31.     int bytestream_size;7 p. h- k3 A6 a: U1 ^) c7 k) D
  32.     int index;5 [9 ?1 k( E; T9 W: S; v2 Q) d' Q
  33.     uint32_t bits;- G! U' ~1 q/ O1 S
  34.     int bits_in_buffer;
    ' O  g* N! `$ M+ q7 @
  35. } get_bits_context;0 ]/ \7 s4 V0 r

  36. + _7 r2 Z: @/ ~) @+ ]
  37. static inline void reload_bits(get_bits_context *gb)
    ' y$ J! N+ E! \2 a; y' [
  38. {0 G# }$ h5 V/ ~" A- L9 N
  39.     while (gb->bits_in_buffer <= 24). ]' O0 U. A; u. O8 S/ |
  40.     {
    $ t! R4 [* T7 L' b3 _
  41.         if (gb->index < gb->bytestream_size)) x, `9 T0 w. j+ |% f
  42.             gb->bits |= (gb->bytestream[gb->index++] << (24 - gb->bits_in_buffer));. x2 D- u2 i- F/ B  W" o1 ~! P& a2 u7 e
  43.         gb->bits_in_buffer += 8;
    # ?' L. H3 n; }7 x# x; E
  44.     }
    9 U1 z( V5 z" }# X
  45. }5 P* T/ V1 Q3 ]2 ]8 y# r

  46. 9 E# e/ ], W4 y2 a
  47. static void init_get_bits(get_bits_context *gb, uint8_t *bytestream, int size)
    6 ^/ z1 K. u+ J
  48. {; l. r; [. |" q$ y  Z' v8 m. \
  49.     gb->bytestream = malloc(size);; T4 y4 f( H- A/ @5 O! Z" s
  50.     memcpy(gb->bytestream, bytestream, size);0 s+ f9 f8 D8 U# A' m
  51.     gb->bytestream_size = size;5 a2 w7 @4 q$ T0 t$ D+ ]
  52.     gb->index = 0;
    # W1 Q8 s& K% }5 v
  53.     gb->bits = 0;
    9 B8 p3 n% D. ^0 l1 P- R6 h
  54.     gb->bits_in_buffer = 0;
    7 c0 _+ _$ F  }. h8 u. Q
  55. 2 Z& O; a2 {- t( A6 |# t
  56.     reload_bits(gb);
    : S9 F% c- t' k' z
  57. }; ^3 \7 [) ?/ _
  58. 6 J2 N2 S. g$ T6 P8 Z+ X
  59. /* read bits without consuming them from the stream */
    , p1 k& z* h* I! L8 |% J0 T
  60. static int view_bits(get_bits_context *gb, int count)5 S% d" w) R5 X1 g0 j5 C, p) n
  61. {1 x; Q2 V7 X( z# R: s0 s
  62.     if (count >= 24)- }% i  w: E- J3 |3 a
  63.         return -1;
    / l" r1 I2 o. n2 ?, ~1 M
  64.     if (gb->bits_in_buffer < count)7 R; m) J5 _  ?, [
  65.         reload_bits(gb);) {6 X* @; _6 f5 K# o( T, A
  66.     return (gb->bits >> (32 - count));
    8 Z( v( R5 Z# A" h* _
  67. }9 m) Q0 D1 Z6 z" v6 D& p
  68. ) Q  L- }" r5 k+ k8 V) ?1 B
  69. /* read and consume bits from the stream */7 E* ]6 N- I+ ~) x
  70. static int read_bits(get_bits_context *gb, int count)
    7 L7 Y$ R: N% ^6 U) j4 V
  71. {% u  [* j- t, ~% x- m
  72.     int value;: C: G" m! \: v$ F/ A# k1 ^, a- x

  73. / L6 [4 v0 y7 O! D9 U
  74.     if (count >= 24)% I3 R4 q& u" C7 [0 d- J$ U" F6 `
  75.         return -1;
    $ u6 R* [5 q* U" P/ Q: z

  76. - x! j& X9 q$ o, s) A2 n+ h8 D
  77.     value = view_bits(gb, count);
    4 H/ [, v, ^$ R! L. ~4 w! z! |
  78.     gb->bits <<= count;2 }% E& t6 D+ J1 J  a; j
  79.     gb->bits_in_buffer -= count;
    3 i) x, t  |" o4 T, E+ D/ S6 W) J

  80. % Q4 C7 @* u1 a( p$ ]! D4 P
  81.     return value;
    9 w3 u, [& {+ {6 c0 Z0 Y
  82. }/ E& Q$ i$ O& ?9 u1 r% [. v/ `
  83. * k5 c3 @& F) }8 ?7 v
  84. static void delete_get_bits(get_bits_context *gb)7 o( F- a+ m0 N$ L/ E! c6 G+ g) a
  85. {( J0 u2 p+ f3 k- C1 v3 C, T
  86.     free(gb->bytestream);
    " ^2 o$ h0 Q$ q
  87. }
    ( e' ^2 w* T5 X, W9 O0 w

  88. % {" ^, w# D$ W7 ~+ n" O
  89. /*********************************************************************// U7 [3 V0 _9 C

  90. / ?: f3 I: d" G3 P2 h! `  u
  91. /* Bit writer stuff */
    " {7 x/ [' e1 B. ~

  92. " J* }; V8 u. l: `, S, q* P
  93. #define MAX_PUT_BITS_BYTES 63000+ b9 J6 ?% B5 }: m# D4 d; b! s
  94. typedef struct2 j3 }! s0 w5 Y! b9 C) M
  95. {
    % ]* \0 M+ [2 y
  96.     uint8_t bytes[MAX_PUT_BITS_BYTES];% L: f0 u2 ?1 M( A5 U. \! V
  97.     int byte_index;" a" Q/ |* Y& b- `; W! D( M
  98.     uint32_t bit_buffer;' L, X1 R8 A# f) t; v
  99.     int bits_buffered;
    6 c* ]8 m$ G9 z6 S2 L
  100. } put_bits_context;& A9 n. @1 ?) _- l. @. ]; o2 }" v
  101. 7 G. ~# o7 n1 ?  F
  102. static void reset_put_bits(put_bits_context *pb)% r; f! ]9 N* p3 Y, l( ~% h
  103. {
    % Q0 D  r0 o; X; f) z$ B& y
  104.     memset(pb->bytes, 0, MAX_PUT_BITS_BYTES);. F: c/ y2 i5 M7 r; q. J
  105.     pb->byte_index = 0;3 e4 t* f. p. t! E
  106.     pb->bit_buffer = 0;
    ; {; x0 K/ ~, k9 s, l* P; y# d5 M5 }
  107.     pb->bits_buffered = 0;
    # ]. G2 v6 U$ C$ k) r+ B
  108. }
    ) J& Z( G1 A* v4 E; ]
  109. 2 c7 J" P  p+ c: j: Y5 L
  110. static put_bits_context *init_put_bits()& k: P, k+ F% ]8 X' c7 q9 \
  111. {# V* N& s2 D+ L9 v7 D
  112.     put_bits_context *pb;$ Q0 p  v: Y* W1 }9 n$ B# o+ Q& ]
  113. 6 [& Y; |% W) B9 {. n5 O
  114.     pb = malloc(sizeof(put_bits_context));
    , O4 I2 ~& C  L; K( w/ }9 i
  115.     reset_put_bits(pb);
    * q( e: A3 e* U4 l; y0 E
  116. , {2 ]# h8 |5 M& V' x5 T+ k
  117.     return pb;2 x+ q: z6 b* `$ X* ~0 g/ i# v
  118. }- n0 B& M0 h+ l! E
  119. " u4 U5 s& |2 |
  120. static void put_bits(put_bits_context *pb, int bits, int count)
    # `: S  ]5 s5 w: ~! S
  121. {3 m3 y4 ~/ c: |5 Y
  122.     pb->bit_buffer <<= count;
    " H9 W, Y3 W/ J
  123.     pb->bit_buffer |= (bits & (~(0xFFFFFFFF << count)));: j- U' B6 S( o; b4 x
  124.     pb->bits_buffered += count;
    3 P3 k& W6 t% @, Z; C% \% z

  125. 4 Z+ D3 }4 a& U. Y
  126.     while (pb->bits_buffered >= 8)$ D2 ~! {! K2 J/ }: T3 m
  127.     {& m+ ]5 S, _4 q: j
  128.         pb->bytes[pb->byte_index++] = pb->bit_buffer >> (pb->bits_buffered - 8);
    ( p+ Z+ ]. U/ I) a
  129.         pb->bit_buffer &= (~(0xFFFFFFFF << (pb->bits_buffered - 8)));
    ) D" w0 o9 N- f/ V. u" ?
  130.         pb->bits_buffered -= 8;
    # M$ v8 A+ x# n4 T
  131.     }" V* a. i8 O8 T8 O# e
  132. # T: f8 L' o( t2 _, v) v1 q
  133.     if (pb->byte_index >= MAX_PUT_BITS_BYTES). j9 q* N. A0 ^4 a
  134.     {& X4 w% F& ~% ^
  135.         printf("HELP! Bit overflow\n");6 b" q5 y2 A5 G& {
  136.         exit(1);
    6 K$ x) B9 T: {2 ?9 a8 D
  137.     }$ ?0 Z  U3 P+ b6 H- s, ?
  138. }4 G: }* `- W; b& I: k
  139. 6 O8 {9 Y4 r2 D: M1 W
  140. static void put_bits_flush(put_bits_context *pb)4 M  s3 v: A  J- f# T. B
  141. {
    / [! @3 [9 V: ~$ u- P2 T  G2 r
  142.     if (pb->bits_buffered > 0)
    " _7 K. ?; ?. V& [
  143.         pb->bytes[pb->byte_index++] = pb->bit_buffer << (8 - pb->bits_buffered);
    / `. m0 f) g. N# ^5 z* g
  144. }
    " q  L& ~$ o1 t8 [
  145. 9 a3 O  f+ `/ z7 F/ t3 B- c
  146. static void delete_put_bits(put_bits_context *pb)
    3 V3 v, m  b4 B9 C% u( v* d
  147. {
    ) z* _- H! h- I" n) M- U3 i
  148.     free(pb->bytes);
      @) \$ G+ n  F8 _
  149. }
    9 E/ p9 z8 h( G. Q% S0 b

  150. $ w% f8 N1 ^- c: D$ R9 `$ B
  151. /*********************************************************************/
    8 F1 U) H7 D  N% D2 f
  152. ) w. U4 p6 T( b+ s% `4 s: W' K
  153. /* RBT functions */2 Q& _5 K4 `/ q2 x8 S* l
  154. ( M/ f" E3 W7 Q. i
  155. #define PALETTE_COUNT 256
    / J# o  V& t3 F  `, j
  156. #define RBT_HEADER_SIZE 60$ W+ ~# ?% y3 A, E* \" t! W/ g
  157. #define UNKNOWN_TABLE_SIZE (1024+512)
    1 v( ]8 m- }0 y% U' m6 V! M& U
  158. #define SUBTITLE_THRESHOLD 0x704 z" x# g5 i7 p8 V/ q& J
  159. #define MILLISECONDS_PER_FRAME 100& M2 u3 o3 w6 U9 U
  160. " M* |+ b1 Z( N5 u% t, H1 R' |
  161. /* VLC table */5 V  e  |; _# X! S9 U+ ?
  162. #define VLC_SIZE 4
    . ?- j( M. o+ k3 X
  163. static struct0 z) s. C2 W; x# ]4 v# G
  164. {
    9 Z) Z; ?! H& w. D. O
  165.     int count;; G, O4 {, T. d/ D* @9 l. P, ?
  166.     int value;5 w3 j: n2 c* Y$ {6 ^, T; F$ [3 I
  167. } lzs_vlc_table[] =/ X. d; K9 O! b) b2 W( E
  168. {, `! X5 D8 Q4 v/ c$ m
  169.     /* code length = 2 bits; value = 2 */& N' r+ C8 e5 G0 }2 Y
  170.     /* 0000 */ { 2, 2 },
    " s6 \" J5 j+ e  I2 d4 E9 o
  171.     /* 0001 */ { 2, 2 },
    8 `: x" z- F* Z; W6 m
  172.     /* 0010 */ { 2, 2 },8 C6 q( A3 }+ s% v! s6 L3 b" X
  173.     /* 0011 */ { 2, 2 },/ R9 [* y* ~" x# i4 `0 R8 I
  174. ' y5 n! n4 u/ y& ?: L$ s
  175.     /* code length = 2 bits; value = 3 */9 R' }6 X) k- N2 q7 @2 l' W4 S' r
  176.     /* 0100 */ { 2, 3 },
    5 V5 G4 \3 E: F' D, `6 ?* m. L
  177.     /* 0101 */ { 2, 3 },
    1 N9 m3 j6 {1 t
  178.     /* 0110 */ { 2, 3 },
    $ @# ]$ L( |7 f3 e) g0 v) s; d
  179.     /* 0111 */ { 2, 3 }," f- |$ W- Y/ D, S3 X3 A8 r" L

  180. 7 ^& h+ S/ q0 o, m# N" S$ G
  181.     /* code length = 2 bits; value = 4 *// W# Z( W% e" s2 t5 Y# K5 O+ p, x" i# z
  182.     /* 1000 */ { 2, 4 },8 H4 R# U( s1 s6 C! n6 M
  183.     /* 1001 */ { 2, 4 }," C5 }" N8 z5 \, U' x1 M3 ?: t
  184.     /* 1010 */ { 2, 4 },
    5 c8 b  k4 W/ S; o
  185.     /* 1011 */ { 2, 4 },2 ]& R  z: _9 Y

  186. 9 {: p8 A; A7 D! e
  187.     /* code length = 4 bits; value = 5 */% D7 \) U. v/ G  H0 s+ }* s
  188.     /* 1100 */ { 4, 5 },
    4 O. @4 q/ g8 S5 V1 f

  189. * ^2 M3 Y7 u2 j
  190.     /* code length = 4 bits; value = 6 */& B6 p) W0 u6 b
  191.     /* 1101 */ { 4, 6 },
    6 A8 a- u, z' L/ a" U
  192.   y* C0 D2 X/ `6 w* b/ v' ]
  193.     /* code length = 4 bits; value = 7 */
    - ?7 i7 O5 |' [: w) g
  194.     /* 1110 */ { 4, 7 },5 ]; |7 B) L& m+ Q
  195. * z7 l/ b: p8 S- D) \
  196.     /* special case */5 A( e. O) [6 m! E5 }$ b
  197.     /* 1111 */ { 4, 8 }
    ( |/ ?& n, K' x$ L$ Z. r" {$ b
  198. };  f. ?, T: a$ a
  199. 6 J4 n$ d9 A6 X/ X, f5 n, z7 ^" M
  200. typedef struct
    5 V8 d' z) y- {- }& C
  201. {
    + d/ P: R# J: Q4 t# `
  202.     int version;% s; S! s# R* b$ o. |
  203.     int width;& P& Y+ [* _; J. C
  204.     int height;
    ! r- M1 b! x  R, |$ V8 X0 h
  205.     int frame_count;1 I$ L# V2 w4 n3 V: V! h2 w% ]1 I: T4 }
  206.     int audio_chunk_size;
    7 ^, F$ U& b( v2 y1 {& k  a& G
  207.     uint8_t palette[PALETTE_COUNT * 3];, f# u  Z% m1 q* K( X
  208.     off_t video_frame_size_table_offset;
    2 j. R$ t, W7 f6 Z" }2 U  o9 D
  209.     uint8_t *video_frame_size_table;" r4 M) v& w+ Y3 L% Y5 j2 p8 ~
  210.     off_t frame_size_table_offset;
    1 y2 C0 b8 Q6 G! p2 L
  211.     uint8_t *frame_size_table;
    7 l$ T5 i7 N# l* G/ g; Z8 c
  212.     uint8_t *frame_load_buffer;1 v5 M# a1 r# w$ M& x; {! ^" a* _& o
  213.     int dump_frames;
    " j5 l! s1 t5 n3 q

  214. 0 n, Z; w5 L; Z2 a, T0 e8 a% c2 `4 T
  215.     /* subtitle library */
    / x* A5 `1 }8 v' [
  216.     ASS_Library *ass_lib;
    1 \) F( M. L0 o+ L8 [6 w6 a$ G
  217.     ASS_Renderer *ass_renderer;
    # D/ {) @, z3 q' @
  218.     ASS_Track *ass_track;( n0 R- A' j# _: a/ ^6 m& K7 ^
  219. } rbt_dec_context;
    ) ~' B4 v- i* y$ P4 h3 K, g
  220. " j) h3 b3 }/ z- L3 Y
  221. static void dump_pnm_file(char *filename, rbt_dec_context *rbt,
    ( h. _1 t' G/ I7 S: g
  222.     uint8_t *image, int width, int height)
    0 a- ^$ c6 K% T& v" V+ ~* W: K
  223. {
    1 X3 {+ C6 N; `
  224.     FILE *outfile;0 ?) v( u- r8 j, G8 K9 @. ?+ k$ [9 u
  225.     uint8_t bytes[3];3 p- E8 X, Q1 {2 y! Y8 Y& v
  226.     int p;
    % |6 R' E! N. u1 `8 L8 m$ M- ?) ^" @
  227.     uint8_t pixel;* o: K- K9 y( ^0 a% A5 v
  228. ' ?& E3 h( G7 ?( D" Z* Z- _. T6 \
  229.     outfile = fopen(filename, "wb");! t! L" A& v* o* ^  R
  230.     fprintf(outfile, "P6\n%d %d\n255\n", width, height);: v1 a2 E7 T5 H" Q, W
  231.     for (p = 0; p < width * height; p++)
    ! i( ^: G" {% D% c0 S
  232.     {" }( G6 Q3 i" F- K9 d4 c9 L
  233.         pixel = image[p];
    # f, V- n; ^" O5 m
  234.         bytes[0] = rbt->palette[pixel*3+0];& D9 A' ^# Y. G
  235.         bytes[1] = rbt->palette[pixel*3+1];
    5 H0 ]( [8 ~- U+ J! g
  236.         bytes[2] = rbt->palette[pixel*3+2];+ j! U* F2 \4 _5 T& {9 r
  237.         fwrite(bytes, 3, 1, outfile);
    6 n- N+ J+ p" B. H8 k' C
  238.     }) A+ w9 l& b9 _6 }$ Q
  239.     fclose(outfile);6 `2 ?2 Q4 ~' d0 |1 C& L8 y' q
  240. }1 E1 p. |7 h7 ~" S) ^+ O8 }$ l2 d
  241. ' ?' J4 G! ^. _3 v
  242. static int load_and_copy_rbt_header(rbt_dec_context *rbt, FILE *inrbt_file, FILE *outrbt_file)1 p2 x2 \% N. W4 ]! v7 h
  243. {
    ; _0 c! A8 b6 E
  244.     uint8_t header[RBT_HEADER_SIZE];
    , Y5 c: J/ L; t* q7 e' o
  245.     int palette_data_size;2 P( }0 I* c. \- Z% W
  246.     uint8_t *palette_chunk;; y* |7 I  N8 a# Y& _' y
  247.     int unknown_chunk_size;2 }/ W, |% |4 d7 F% g, I
  248.     uint8_t *unknown_chunk;& u/ H0 l; k9 r" ~
  249.     uint8_t unknown_table[UNKNOWN_TABLE_SIZE];
    / `) s6 w! W$ F; y
  250.     off_t padding_size;
    0 k% T* K! j8 H1 A; N5 k1 T
  251.     uint8_t *padding;
    6 [) S* n0 F! B% a0 `! L) P9 \
  252.     int i;* N5 w% L. U3 G2 g% o0 v, O0 F6 H
  253.     int frame_size;9 s9 ^7 W0 x, r( _7 F: L, O
  254.     int max_frame_size;) j. j2 T# s/ B  T' ~5 s
  255.     int first_palette_index;3 Z3 p! L9 k1 z! ^9 b. O
  256.     int palette_count;; N; S6 Z6 l& X1 j& o& D
  257.     int palette_type;
    ) v! \! F# n1 \+ @! R
  258.     int palette_index;5 @( z7 |3 B. d+ ^7 m6 Y6 J. t" `4 g

  259. 5 ]1 T2 k8 l9 U8 |/ C
  260.     fseek(inrbt_file, 0, SEEK_SET);
    , [7 T. `6 O/ q6 p: B, e
  261.     fseek(outrbt_file, 0, SEEK_SET);
      Y" ~- a8 a6 w5 b, Q
  262. % a3 x( d$ U+ v
  263.     /* load the header */
    3 g% _8 r% k; g: ^3 y+ k: E
  264.     if (fread(header, RBT_HEADER_SIZE, 1, inrbt_file) != 1)0 w* W; h; ^) g8 Q4 e
  265.     {
    & E+ W* N( j% }
  266.         printf("problem reading initial RBT header\n");' G" U  O) k0 f- e/ c1 d( A
  267.         return 0;
    * R$ P; \$ b3 s
  268.     }  w2 G, n9 u0 b2 g+ D

  269. * l; C+ Y  I7 l9 k
  270.     /* copy header to the output */
      M/ J/ D& A  c# R3 C
  271.     if (fwrite(header, RBT_HEADER_SIZE, 1, outrbt_file) != 1)+ c% z& w7 f) H8 S* x- Z- m0 k' {
  272.     {; Q1 f3 O' n& `/ R, u5 Y
  273.         printf("problem writing initial RBT header\n");
    4 S# A) n% y, V$ f. I2 H+ b5 ^  C. _
  274.         return 0;6 Q7 V$ w5 h; I; Y: S; i
  275.     }/ T1 K$ y: B% {3 u, O, \8 o
  276. . Q: k+ M8 X3 {( t( T' ]! b" {) \# k
  277.     rbt->version = LE_16(&header[6]);
    9 E, X( S$ N( X* e: U4 i
  278.     rbt->audio_chunk_size = LE_16(&header[8]);
    6 ~/ K/ u, q3 P
  279.     rbt->frame_count = LE_16(&header[14]);
    . m$ j# K, c/ K3 A0 \: K$ q

  280. 4 q/ R, Q" L* q5 Y$ d9 K, W
  281.     /* transfer the unknown data, if it's there */1 l: s: j- M. e7 s! }% B
  282.     unknown_chunk_size = LE_16(&header[18]);  T% y, x9 e5 g! `! ~# j8 t
  283.     if (unknown_chunk_size > 0)
    % M+ M3 `$ ]. R' Q4 R; ~
  284.     {
      G; a0 n* h; D
  285.         unknown_chunk = malloc(unknown_chunk_size);& ~8 G1 b0 W' d4 M5 t7 R
  286.         if (fread(unknown_chunk, unknown_chunk_size, 1, inrbt_file) != 1)8 ]  |; J' a" `1 C9 @
  287.         {
    1 x; c, V: z4 \$ O
  288.             printf("problem reading unknown data\n");2 f$ G; C/ E# y$ U2 h* |, Z
  289.             return 0;; l4 M% B3 ^" R( W8 Y+ C' g: Y
  290.         }
    ! V0 }- ]( y% k
  291.         if (fwrite(unknown_chunk, unknown_chunk_size, 1, outrbt_file) != 1)  D7 N9 R* Q- m' p5 Y, \* S; A, \/ E
  292.         {
    : x/ m0 ]! @* D- W& O. r7 d/ ?) b
  293.             printf("problem writing unknown data\n");$ t% P& ?4 G6 g4 y* ~3 J* \2 q  R
  294.             return 0;
    : H! z% W6 z% E
  295.         }, |1 b: }1 o) M: {, M5 d# K% J
  296.         free(unknown_chunk);) m$ O1 ?4 ~# N
  297.     }) W) Z* i& n1 L, V. S4 y5 `

  298. & W/ I) [! N& f9 E' U
  299.     /* transfer the palette chunk */
    ! X! W! t. r) Z
  300.     palette_data_size = LE_16(&header[16]);
    / ?; _( n& j4 ?% d) R  ?
  301.     palette_chunk = malloc(palette_data_size);, B; O6 g1 v0 k$ }
  302.     if (fread(palette_chunk, palette_data_size, 1, inrbt_file) != 1)
    ! x5 _; X( \2 L
  303.     {
    9 Q2 S7 [/ Y# n7 D. z; Q
  304.         printf("problem reading palette\n");4 y) R# `7 ^& @4 l& _) K1 L
  305.         return 0;
    . i/ k, o% G( O' R7 z# g
  306.     }& B! p8 {7 p3 @
  307.     if (fwrite(palette_chunk, palette_data_size, 1, outrbt_file) != 1)
    7 v; g; B. m- C/ g
  308.     {8 @: w" a3 W- _4 \! c1 K; F: B+ }" I
  309.         printf("problem writing palette\n");0 {0 t2 y0 K. q8 N7 i+ d
  310.         return 0;6 u; u0 k2 X4 B* b* a( B
  311.     }' D: U! B6 v4 F4 D$ H# [1 i; n
  312.     /* load the palette into the internal context */
      o' T7 e1 g  ~$ b
  313.     memset(rbt->palette, 0, PALETTE_COUNT * 3);
    , `7 k, Q; p- V) m, ~" C
  314.     first_palette_index = palette_chunk[25];# `( Y8 p0 k( k4 B
  315.     palette_count = LE_16(&palette_chunk[29]);
    % D2 {. \; h1 @
  316.     palette_type = palette_chunk[32];$ j2 x& d6 |2 L* T/ w$ C! J
  317.     palette_index = (palette_type == 0) ? 38 : 37;
    3 R) {9 p4 W# l8 m5 Q6 f8 R
  318.     for (i = first_palette_index; i < first_palette_index + palette_count; i++)( i8 m2 c: ?! ]; W; c& @) L! r
  319.     {8 v8 F) w# E6 {3 b- e( G, u4 a) ?
  320.         rbt->palette[i*3+0] = palette_chunk[palette_index++];
    6 q7 b% q9 b( y0 L& z3 n
  321.         rbt->palette[i*3+1] = palette_chunk[palette_index++];
    / s' B0 }: L5 \. x- I
  322.         rbt->palette[i*3+2] = palette_chunk[palette_index++];
    # Z+ S8 W+ F) _# [$ C( G" p' {
  323.     }9 ^% Z' P. z9 K0 M( ?$ p. [; ^
  324.     free(palette_chunk);
    $ ^8 p3 l9 X# ^, Q' e: W
  325. ' v2 j: x0 F! I: e  G2 ~
  326.     /* copy the video frame size table (2 bytes per frame), as a placeholder */' w- b5 {6 x$ D
  327.     rbt->video_frame_size_table = malloc(rbt->frame_count * sizeof(uint16_t));/ v) {) C0 v9 _' T" ?
  328.     if (fread(rbt->video_frame_size_table, rbt->frame_count * sizeof(uint16_t), 1, inrbt_file) != 1)" }- ?- A5 c. G
  329.     {
    3 s4 A9 |/ k% ?4 a2 |1 I5 A
  330.         printf("problem reading frame table\n");
    , _% H0 h( j$ q% R* e2 M2 c
  331.         return 0;9 A' V, ?8 p' s3 k: B
  332.     }
    $ M5 u& t! l6 i$ p  X5 v) ]
  333.     rbt->video_frame_size_table_offset = ftell(outrbt_file);
    3 ?' t* w; `1 e+ G/ d4 I
  334.     if (fwrite(rbt->video_frame_size_table, rbt->frame_count * sizeof(uint16_t), 1, outrbt_file) != 1)* A  O. u9 Y" A/ _
  335.     {
    % c8 R8 O% `: `: g) i5 L; Y% b
  336.         printf("problem writing frame table\n");
    . d5 h; E" d2 l; a% p# |
  337.         return 0;
    ) _7 Y% g8 r* z; w5 E' O6 y2 N
  338.     }
    & I. h$ c' W4 w$ W* C

  339. . u  u- l7 Y& O  K& Z) A; T4 M
  340.     /* copy the frame size table (2 bytes per frame), as a placeholder */
      w# x- _( A) O; B, m
  341.     rbt->frame_size_table = malloc(rbt->frame_count * sizeof(uint16_t));  b3 q9 I1 O& y* f
  342.     if (fread(rbt->frame_size_table, rbt->frame_count * sizeof(uint16_t), 1, inrbt_file) != 1)( N3 o; ^( C  `: B8 t& u
  343.     {
    & H, H( e2 I: Y* v
  344.         printf("problem reading frame table\n");
    9 T$ i( F+ u" d( P" P
  345.         return 0;
    6 [2 Y* D6 n% `! M
  346.     }
    ! S& A) `' c0 W+ f1 I+ k
  347.     rbt->frame_size_table_offset = ftell(outrbt_file);
    " }0 C. [0 R4 P' i: ?# I  K
  348.     if (fwrite(rbt->frame_size_table, rbt->frame_count * sizeof(uint16_t), 1, outrbt_file) != 1)
    * J7 O6 b' s) \" h! j& P3 r
  349.     {- \( W1 P+ u$ f8 z# X3 |
  350.         printf("problem writing frame table\n");
    + Z0 P$ g' n9 `7 n6 i- m" Z/ [
  351.         return 0;0 N: `, ]" ~& [' p/ c7 }
  352.     }: D% T. A) r+ F- [% j  ^3 u

  353. 3 U/ M& ~$ T7 q
  354.     /* find the max frame size */0 a9 Z* U& U% {0 A; o
  355.     max_frame_size = 0;
    " h6 u: N$ Z9 u+ V! p* a
  356.     for (i = 0; i < rbt->frame_count; i++)
    : Y7 p# a9 {$ _# a7 g4 _3 ?3 L
  357.     {( d6 U' N2 _: B5 n$ `7 e! U1 P
  358.         frame_size = LE_16(&rbt->frame_size_table[i*2]);/ f6 A; _+ j: |7 y8 |
  359.         if (frame_size > max_frame_size)* a) _$ ^7 m' w, H! q0 U1 d8 W+ |
  360.             max_frame_size = frame_size;
    $ U) S5 q2 d( o; B4 R4 t
  361.     }- r) O7 n: k# t8 P& t( y
  362.     rbt->frame_load_buffer = malloc(max_frame_size);
    $ d% l4 X# p! Y+ L4 U
  363. + u9 }8 `& v3 w3 Y: Z
  364.     /* transfer the unknown table(s) */
    6 i+ U- A: E! A" b" D
  365.     if (fread(unknown_table, UNKNOWN_TABLE_SIZE, 1, inrbt_file) != 1)9 L* j4 o1 _2 x7 \- ~& h
  366.     {* J- e, y9 c7 w
  367.         printf("problem reading unknown table\n");
    4 J) w1 ~& g) D  R3 r! N8 T
  368.         return 0;
    ; V/ B8 J2 K6 ]7 O: s' n
  369.     }
      ~+ }" ], x* X2 q: y" V
  370.     if (fwrite(unknown_table, UNKNOWN_TABLE_SIZE, 1, outrbt_file) != 1)* ]1 u) a& G! f* H
  371.     {
    8 Q; @: C# Q% ]. X/ w8 ~5 ]% m' t/ L& _
  372.         printf("problem writing unknown table\n");
    ' u- ?- x. Z+ |
  373.         return 0;
    + ^3 I" |' }) ]
  374.     }! ]1 i; f- E5 M* ~
  375. % M! Y% y2 S3 S; L
  376.     /* copy over padding */
    - c+ J9 M  ]) e. V' L/ e& i9 C
  377.     padding_size = 0x800 - (ftell(inrbt_file) & 0x7FF);  l) E- b, z. Z& k+ ?$ T# I
  378.     if (padding_size)
    , V! z) m; S/ I
  379.     {
    1 s, Z1 X6 R# L) Y( A' q) M! f
  380.         padding = malloc(padding_size);
    6 E9 y" |1 H: p1 R
  381.         if (fread(padding, padding_size, 1, inrbt_file) != 1)9 U: ?6 t2 l! k* |& ?8 T
  382.         {+ e1 c* \1 [; E' }' H4 e
  383.             printf("problem reading padding\n");
    9 C1 c8 A3 y, r8 ^2 j: @
  384.             return 0;, ?5 {: H1 X5 {% y7 L, n
  385.         }
    3 p& P3 n. E$ r# G8 [+ i* [
  386.         if (fwrite(padding, padding_size, 1, outrbt_file) != 1)3 I- G& P+ j, B$ {  M* f& i# f9 w
  387.         {
    / [, Y% a9 e7 K- |
  388.             printf("problem writing padding\n");
    6 N. I, N& T* q5 k6 c1 x
  389.             return 0;
    : W- S6 E" q4 F/ n! c$ ]9 J
  390.         }4 r0 I; k5 l" [3 J8 H+ ^/ b
  391.         free(padding);3 o0 e9 Y% {& h
  392.     }
    4 y; \# E; e6 d- T: m' j

  393. / C. r  [6 i* r/ g, N4 v
  394.     return 1;
    - n: T. e; e# z. ~: [
  395. }! x3 E( X, k2 m& h8 w

  396. : p# D! J/ y) e9 P! M
  397. static int get_lzs_back_ref_length(get_bits_context *gb)% u8 ^; L6 @  T5 K! g! P
  398. {8 }* i' `& h! g% P9 F6 T; A3 G
  399.     int vlc;) W# \/ i9 w' C1 x7 i
  400.     int count;
    0 {- X3 Q& _! \' U8 K" O$ i2 K
  401.     int value;! @& Y7 z: p9 m1 I2 R+ ^  d

  402. 8 Z: g- ?8 Z  Z0 Y* r) |
  403.     vlc = view_bits(gb, VLC_SIZE);( [# v8 m. ~# _! t
  404.     count = lzs_vlc_table[vlc].count;/ Q' E  U  x' \: q, N5 G
  405.     value = lzs_vlc_table[vlc].value;/ c0 z2 j8 J, S. m! ]# k0 U

  406. : A9 c/ y# v3 G+ \8 s" [; W
  407.     read_bits(gb, count);9 I' r/ v. Y/ e1 g* n: \; Q( i8 u
  408.     if (value == 8)
    3 O, \* n. Z" e. c7 X3 l4 w
  409.     {
    ) q8 ~6 m6 V; z
  410.         do
    ( ?( J* `7 k3 Z* a! g5 P
  411.         {
    ! A1 ]0 w  i9 ?$ K
  412.             vlc = read_bits(gb, VLC_SIZE);. `  K! H. E# J. S& ]) t* w6 }
  413.             value += vlc;
    ) A6 l0 U6 C7 L: v5 f
  414.         }9 e8 d/ Z! U% A4 V/ D
  415.         while (vlc == 0xF);8 x  c5 A1 l) O0 @. A; n9 N2 h- D
  416.     }
    ) S, _1 q' O% k  ^* V/ E

  417.   `0 r: c/ _3 g( L! W$ ^3 T
  418.     return value;9 g2 D8 p' k" D6 e* O
  419. }
    # Y7 d5 X( q, u- _

  420. / \- q9 ?$ {; P2 D. R
  421. static void compress_window(put_bits_context *pb, uint8_t *full_window,
    - y7 O* _4 K. P! P1 v5 D/ m7 o  `
  422.     int full_window_stride,0 V" F1 l3 B  E$ F$ |
  423.     int window_top, int window_bottom, int window_left, int window_right)
    ; D4 O- B* o2 n& G
  424. {! c9 v7 p8 B' z
  425.     int last_pixel;5 {  I- T; I9 P( T0 u1 N3 C' n* N
  426.     int run_size;1 Q" ?7 ]  t- Q( ]; x( `* k
  427.     int x;2 b- [2 \3 R" @
  428.     int y;
    $ ?! p% o/ x/ y3 H# l
  429.     int start_index;3 Z- a3 \0 w( c8 t$ j) [
  430.     int end_index;
    5 s9 G) I: k$ ^) c7 {( K
  431.     int encode_last_run;& J3 n1 ]. k4 i" b

  432. ; ~9 C: W8 n* P  \. y
  433.     last_pixel = full_window[0];4 s7 m/ z) g, j& l% t' m* }+ M
  434.     run_size = 1;
    % M+ M1 j2 b5 B
  435.     for (y = window_top; y <= window_bottom; y++)) ^& d' [4 R3 A3 @4 f" ~
  436.     {: d8 s/ |4 i; _# b! z7 e5 w4 I
  437.         start_index = y * full_window_stride + window_left;/ {7 A1 i' e9 v
  438.         if (y == window_top)
    * R4 U4 m/ Y& X
  439.             start_index += 1;
    1 o! {- _6 _+ f" n" v2 U( N
  440.         end_index = y * full_window_stride + window_right;
    - q! I6 E9 D- a' d( M& j
  441.         if (y == window_bottom)! z8 n  J! V8 S4 e: N% d) ?% b
  442.             encode_last_run = 1;+ }$ H4 v( v* N! u& a* l
  443.         else  o1 W# n' S6 K' m( p! |6 z3 \' O
  444.             encode_last_run = 0;
    1 N7 y- F- k: j7 ]8 j
  445.         for (x = start_index; x < end_index; x++)* z$ P+ n( j" F( E% l9 s
  446.         {
    , [' y6 }. p% H5 o+ ~( a; ]
  447.             if (!encode_last_run && full_window[x] == last_pixel)
    ! U# u6 @  ?: X! F& k% L
  448.                 run_size++;9 k, y8 b- {# g4 W5 M/ J
  449.             else
    ( J8 |" }0 q7 [. t( h
  450.             {
    5 s' g7 z3 Q6 \" |( C
  451.                 if (run_size == 1)( _- s3 ?5 y( U: {* a
  452.                 {
    9 w, r8 H5 q; Q7 t, A
  453.                     /* encode a 0 bit followed by raw pixel byte */1 p, h+ c2 X( O* J% B. n
  454.                     put_bits(pb, 0, 1);
    4 N0 x8 ?. J; p+ u# J4 I
  455.                     put_bits(pb, last_pixel, 8);
      t# t' ^9 z5 k- Q5 V9 [  A
  456.                 }
    & A! p2 r& o) n$ ^/ o3 U
  457.                 else if (run_size == 2)
    . G6 C1 s1 l% y  |$ Q  b
  458.                 {
    7 y7 `5 c: e* S5 s
  459.                     /* encode a 0 bit followed by raw pixel byte */
    # R. n) o: A# a8 ^; [
  460.                     put_bits(pb, 0, 1);
    6 v! W! V% \* G
  461.                     put_bits(pb, last_pixel, 8);
    % e& G# X: ]* l4 ^9 Q6 b
  462.                     put_bits(pb, 0, 1);2 ?2 c: H% D1 _" }! a( y
  463.                     put_bits(pb, last_pixel, 8);$ T5 u& X5 }0 S% U7 h+ |# D
  464.                 }
    3 @& S- P$ f1 y7 [
  465.                 else! x! W# \/ R4 |" F8 }- s
  466.                 {
    + g& M# e& q6 _4 A: F+ \. x
  467.                     /* encode a 0 bit followed by raw pixel byte */
    / d8 g2 Z9 q; @: d  v1 h' p' L
  468.                     put_bits(pb, 0, 1);% P0 ^/ a  T3 |5 o9 i
  469.                     put_bits(pb, last_pixel, 8);
    / E2 i/ F, @& m6 @
  470.                     run_size--;- P7 w( W' F# R& I% j( _
  471.                     /* encode a run: a 1 bit, followed by a back reference) k3 @( d% ~# L- y
  472.                      * offset (-1), followed by a length */, }: X/ Z9 z4 y, S8 Z
  473.                     put_bits(pb, 1, 1);
    ; _/ ?# w! \5 V& D$ c( [) d
  474.                     put_bits(pb, 1, 1);  /* 1 = 7-bit offset */
    # k3 |: a8 D# S' h
  475.                     put_bits(pb, 1, 7);5 B2 W0 y4 L, _; [8 i% G! B/ l
  476.                     if (run_size <= 4). J7 L! f+ b1 L1 I3 i+ C, I
  477.                     {
    5 X2 J9 {9 J8 z8 s- Z% P* x
  478.                         /* lengths 2, 3, and 4 are 2 bits */" K. f0 a# O. v' U; Z( }
  479.                         put_bits(pb, run_size - 2, 2);
    ! b/ n. x% Z7 b( w/ O3 E; F
  480.                     }6 P- E' B5 M0 ]' J" S3 g# W2 Y
  481.                     else if (run_size <= 7)$ ?; V) `6 B2 i2 x$ U1 ?  r
  482.                     {
    ! X/ P" C3 ?6 A, ]- [$ i/ F3 x
  483.                         /* lengths 5, 6, and 7 are 4 bits */
    5 y6 q# @4 Q4 |& X; N0 U7 Y
  484.                         put_bits(pb, run_size + 7, 4);
    ! U3 q  G. Q" f+ |+ ?' p8 j3 u! t
  485.                     }1 V$ x7 c$ T2 H& e# y; o
  486.                     else6 b5 K! e2 C6 r- U
  487.                     {; b# q, k! @* _" \7 |; \. }% E
  488.                         /* arbitrary length; start by encoding 0xF which; d9 ]" L% s8 T8 E4 z* ^( r6 k5 l
  489.                          * stands in for an initial version of 8 */
    * ?! Y) L% q- @7 P4 M4 a  G
  490.                         put_bits(pb, 0xF, 4);/ w6 B/ t: d7 Z
  491.                         run_size -= 8;: W. n0 k! h' |0 o& I6 R) F

  492. 3 ~0 ]+ M% ^6 a0 R9 ?6 W" J
  493.                         /* encode blocks of 4 bits until run_size is 0 */
    # b+ r7 P- W6 l! x2 N
  494.                         while (run_size >= 0)! t* I5 h% C4 e4 V) h
  495.                         {
    1 S" K7 ?- Q( e) I, F
  496.                             if (run_size >= 15)% i3 f- f' p1 a+ _& _% A
  497.                             {
    , g8 f; Q, S3 {3 a  @  j
  498.                                 put_bits(pb, 0xF, 4);) }/ A/ L& t0 m; |/ {" X/ ]% T7 Z
  499.                                 run_size -= 0xF;
      d7 g' Q2 R, ]2 J* p
  500.                             }$ S) u/ T- j9 L5 }7 Q* |5 Z5 p+ o
  501.                             else
    3 E1 y/ d) Q  {; P
  502.                             {
    ; L( T2 Q; e! p6 C: |
  503.                                 put_bits(pb, run_size, 4);: ?7 ?* ]7 o& n9 K* g% T: _" Q
  504.                                 run_size = -1;3 V6 ]) c9 l; L# ]
  505.                             }2 i2 R" _0 w) O8 ]0 c, D
  506.                         }
      p0 S/ T4 V( r- T1 l& A" P
  507.                     }4 d1 D3 O! Q" v  B4 f3 f
  508.                 }7 U8 _$ {& ?9 O  b+ k

  509. 2 R9 d) H- o0 _$ b7 k6 U/ ?1 V
  510.                 last_pixel = full_window[x];, [: J# }* r; h2 C" [
  511.                 run_size = 1;$ t# |5 {9 m, f: z1 j* u5 d

  512. 8 B. e: ~# G+ x2 s" ~* p+ u& j6 R
  513.                 /* this single x iteration was only here to close the final run */: U2 t/ g0 w! q$ X" t# B/ c1 o& ~% G4 Y
  514.                 if (y == window_bottom)
      ]  g& c  S/ G- H( Q8 ?
  515.                     break;
    ) T* @  r$ }) O
  516.             }
    ' v/ X' a( _3 g% w( _
  517.         }
    , N. s# A8 _: T% h' h" G
  518.     }; Q% a7 |' b7 w& }9 u4 H0 K' g
  519. 0 S5 J6 |  j: I3 J2 \
  520.     /* close the bitstream by encoding a back reference with length 0 */# {- l( O1 e1 F  ^9 E7 }& Y
  521.     put_bits(pb, 1, 1);  /* back reference run */
    " ]8 f) q. D* Q; |* U7 n
  522.     put_bits(pb, 1, 1);  /* 1 = 7-bit offset */
    % O3 E9 F; `6 Y: g" A% ~
  523.     put_bits(pb, 0, 7);  /* length 0 */, ?# X# G+ P/ \# g  S. `

  524. $ L/ G+ l$ ~! I% m6 }5 {/ h' B
  525.     put_bits_flush(pb);
    ) g. I2 @6 `+ `3 m: [6 o1 {* u
  526. }
    % O9 E6 c* ^# I: k, U4 @+ M. `

  527. 5 d9 k8 i+ B& }8 d8 q
  528. /* compute Euclidean distance between an RGB color and the desired target */; r: p7 t/ X$ i: C
  529. static int compute_rgb_distance(int r1, int r2, int g1, int g2, int b1, int b2)
    7 N3 M' V0 [3 N- W
  530. {
    % f6 L( W% D$ C/ \' U. W- V- j
  531.     return sqrt((r1 - r2) * (r1 - r2) +% @) U+ H  K. ^1 l8 j: Y
  532.                 (g1 - g2) * (g1 - g2) +2 r+ \; n/ g" n' ~5 @* R0 u
  533.                 (b1 - b2) * (b1 - b2));
    . N' R4 ^2 F1 p8 }# b
  534. }0 S0 @! d6 Q9 }9 _- r" ]0 C7 Z

  535. : V  y' s) N$ W4 @* M# V: L
  536. static uint8_t find_nearest_color(rbt_dec_context *rbt, int r, int g, int b)
    / f, A* a) G: f" r
  537. {
    ! I8 `4 f/ d; f, T! K8 P5 E/ r
  538.     int i;
    7 B& d+ v/ m6 c
  539.     int nearest_distance;5 p- y$ I$ ?; ?/ q; P3 Y
  540.     int distance;
    ! m5 e5 B) d0 F- |
  541.     int rp;
    0 x$ h4 _9 Z, J
  542.     int gp;
    5 G( {1 o0 q5 j; M3 `' E2 n5 Z
  543.     int bp;
    3 `, v5 s! A) Y" z
  544.     uint8_t palette_index;6 V! t0 U" h" r  u7 Z( H3 G

  545. - i# t- B! F. Q! `
  546.     nearest_distance = 999999999;
    , L" s" w. I7 q1 d
  547.     palette_index = 0;
    , K. J8 ^  u- P% R% z6 W6 S
  548.     for (i = 0; i < 256; i++)' R- b+ e! c. J* O" Q  z$ \3 `
  549.     {+ c. T2 t3 k. A9 W* _1 W
  550.         rp = rbt->palette[i * 3 + 0];! n5 k& P# q/ _; `0 z+ U* A
  551.         gp = rbt->palette[i * 3 + 1];
    ; I' V. F9 b8 ?8 ]: {# Z
  552.         bp = rbt->palette[i * 3 + 2];2 Z: `9 i8 T! j! t
  553.         distance = compute_rgb_distance(r, rp, g, gp, b, bp);
    0 l! C4 F- S& q3 {7 P
  554.         if (distance < nearest_distance)
    5 g. x2 s% H, p1 Y' D% ]' B6 X, x: }
  555.         {2 T* K) q3 U  r/ L: x
  556.             nearest_distance = distance;, p: P8 ^( z/ N  P0 Y
  557.             palette_index = i;4 x' @+ ~& J! X9 K4 u
  558.         }! ^. @$ M5 P* E- ?/ V2 X3 A! W
  559.         /* can't get closer than 0; break early */
    9 }  a7 |: u: ]( v) n
  560.         if (distance == 0)) `9 \8 Q$ A5 E" p5 o. {% H
  561.             break;$ O$ x' t; c2 ~& X- J
  562.     }
    0 H$ O8 Y& S! Z( E
  563. ; \' ]9 k7 k- u3 E# G
  564.     return palette_index;
    3 k' y( `8 \" l
  565. }2 m& q- G1 N2 o+ C# H
  566.   E6 Z% [- s' j* [8 }
  567. static void subtitle_frame(rbt_dec_context *rbt, uint8_t *frame,4 m) y& V: }- Z9 q* j! y
  568.     int width, int height, int timestamp)
    % h8 b/ P$ b. i  e% a! p
  569. {) _) D, k! F3 q( l0 q0 M0 m
  570.     ASS_Image *subtitles;& G: u+ C' t* Q! v' W* M
  571.     int detect_change;  ]8 t+ j& |3 W$ k
  572.     uint8_t subtitle_pixel;! A8 h8 ]4 @  }* h! ~1 J8 l/ i" P
  573.     int x, y;% L6 {" M9 H- m
  574.     uint8_t *frame_ptr;) S7 k/ j, U. U
  575.     uint8_t *subtitle_ptr;: |' N$ L! Z7 r4 L/ J! |
  576. : z" H0 Y5 V8 S$ T! x. X
  577.     /* ask library for the subtitle for this timestamp */" }. I9 v9 Y; Y+ @( N7 _  k  n
  578.     subtitles = ass_render_frame(rbt->ass_renderer, rbt->ass_track,
    # j. k' E: _) q% w2 E7 u! R4 A
  579.         timestamp, &detect_change);
    1 U8 ~' w7 ^- x% V' V0 K- B4 @

  580. 7 }# S5 _( o& C6 u0 Z0 I
  581.     /* render the list of subtitles onto the decoded frame */
    9 Z* t+ t& u3 k: |$ ?4 W
  582.     while (subtitles)
    , K% y5 k9 @2 u  B1 j) z
  583.     {
    - s9 Q* E% @+ k
  584.         /* palette components are only 6 bits, so shift an extra 2
    : q& n. m) ~0 O- h& _2 ~2 s* y
  585.          * bits off each component */
    ! l3 R% g" a- J. l" T9 V
  586.         subtitle_pixel = find_nearest_color(rbt,  l8 ?# \4 V2 S7 T
  587.             (subtitles->color >> 10) & 0xFF,
    / ~2 g+ Y0 }* m% j4 `3 l
  588.             (subtitles->color >> 18) & 0xFF," B7 B' v  Q8 x2 {0 ~; m
  589.             (subtitles->color >> 26) & 0xFF);
    " ^- C8 |' {- s! D7 B
  590.         for (y = 0; y < subtitles->h; y++)% f" u/ C: Z$ Z9 \5 {3 f
  591.         {
    0 q+ Y! H" |" _% p  F/ e
  592.             subtitle_ptr = &subtitles->bitmap[y * subtitles->stride];
    " {( Y+ s! A4 {$ W% t5 J8 Y
  593.             frame_ptr = &frame[(subtitles->dst_y + y) * width + subtitles->dst_x];  [. ~" L) N% z! Z+ v
  594.             for (x = 0; x < subtitles->w; x++, frame_ptr++, subtitle_ptr++)
    ' @( j9 P* Y4 {  N
  595.             {
    % f0 D2 C/ E  x
  596.                 if (*subtitle_ptr >= SUBTITLE_THRESHOLD): N  d) G% H% A- [4 o
  597.                     *frame_ptr = subtitle_pixel;' A* s9 R( }! Q/ F. a
  598.             }
    6 B: J# e. z9 Q. g# l+ R
  599.         }3 G4 h# j, ~# M1 o& g" k6 g" U
  600.         subtitles = subtitles->next;- G' _0 i! {) Z$ @/ ]6 T/ }& x
  601.     }) e% d: ?5 Z$ R' V5 B# C, b
  602. }5 X$ Z1 f9 t) Q+ N0 w1 L, T+ S! i

  603. " z' P$ d& K2 Z/ k# T$ y
  604. static int copy_frames(rbt_dec_context *rbt, FILE *inrbt_file, FILE *outrbt_file,
    ( |0 _& R2 `# \! t
  605.     int origin_x, int origin_y, int window_width, int window_height); r# C  I% K1 P, Z2 P* j" K
  606. {( C- t" n5 h0 }* m, R
  607.     int i;
    " Y/ N: s, n6 z* b& [
  608.     int j;+ p2 [  `& U# P  |; B4 Y7 I* K
  609.     int scale;, a4 C0 K- y5 r# ^4 q
  610.     int width;6 _4 b0 o" c. s4 v& [
  611.     int height;
    5 d- L/ Q5 R( |3 F# Z' e
  612.     int max_width;
    - @# J/ b! [) t+ u+ H4 X
  613.     int max_height;# i9 x+ b8 p* u; _
  614.     int frame_x;5 R: s4 O: u3 K' E$ q1 D9 E
  615.     int frame_y;2 o! X. Y  W- O2 I0 e# _
  616.     int fragment_count;
    ; h4 _" E: d; T5 S) _$ r1 F; o
  617.     int decoded_size;6 c1 J) o9 U* Z8 T" p; b! j
  618.     uint8_t *decoded_frame;) H5 i# t, m- c6 x: }3 j6 P6 e
  619.     int fragment;
    0 P6 ^6 O! U* z1 |( @
  620.     int fragment_compressed_size;. L- m4 X+ V. b# }" I
  621.     int fragment_decompressed_size;0 v4 z) r) c/ v/ X3 f! V
  622.     int compression_type;' k+ z! E, Y! b6 N
  623.     int index;
    * b+ W0 a  W3 W" h
  624.     int out_index;
    & E: d* ^" _" B' @. M
  625.     get_bits_context gb;
    2 m; j" B2 }3 V
  626.     int frame_size;" }& q+ {' q5 x7 U1 `. e) y6 \
  627.     int video_frame_size;
    $ ?8 T6 }8 S7 c) p
  628.     int audio_frame_size;: s6 z; w+ D4 R/ J, Y: t

  629. + m( \4 w+ P2 u& K; j' x
  630.     int back_ref_offset_type;
    9 ]* m# n; \4 L! \6 `! D, B
  631.     int back_ref_offset;# o2 A+ o# d; @# l, ]; n
  632.     int back_ref_length;
    7 _+ p4 c" m& d1 Q) I% {
  633.     int back_ref_start;* R0 H4 P& {+ |! K; Z' r
  634.     int back_ref_end;( E6 Y: N6 A( E" e; `- H

  635. " G2 C3 f! i4 x  l( E1 [9 h, W3 u
  636.     uint8_t *full_window;( X" ]" }1 [% k5 h$ [2 P
  637.     int full_window_size;
    3 M+ M% `5 [& w
  638.     int y;
    2 y" N# R& {$ s* x0 h
  639.     int window_top;
    . h  t5 J/ i' f6 a' K" {
  640.     int window_bottom;* w$ [1 w! w6 ]/ R% z7 n& Y
  641.     int window_left;7 f! s$ ]" q( ?1 v6 X1 K8 E
  642.     int window_right;2 A3 H# ~1 S1 q: [( f
  643.     int window_size;
    3 W4 F" q8 R$ Y! F

  644. 0 f( `: m" J# ^. S/ D% `
  645.     char filename[30];4 t! x2 L  _6 C( n2 I. V

  646. . n, s1 [6 k6 F& j' y
  647.     put_bits_context *pb;
    1 E. G0 j8 o. r! \9 {( \# C
  648. ! n% a. q/ L- m! }( t9 K
  649.     full_window_size = window_width * window_height;
    0 x1 Q% @9 V8 W* }; j
  650.     full_window = malloc(full_window_size);
    1 a% I3 e; k' Z! _6 P) i
  651.     pb = init_put_bits();
    . p, l! x' |9 F% j& u' r
  652. # r, H0 X1 M  z* n& H
  653.     max_width = 0;' g# S! q! P4 \
  654.     max_height = 0;
    4 Q6 ]* U" Q; }7 h+ A6 M

  655. ( b6 ~" d6 L8 E+ ~3 B6 a
  656.     for (i = 0; i < rbt->frame_count; i++)
    8 Y* a6 U& I$ `. q  U3 z
  657.     {
    ) G' {. Q/ z; o/ j1 c- a1 @  x6 R
  658.         /* read the entire frame (includes audio and video) */
    ) E4 U) o7 c" l- N( Y/ |  o
  659.         frame_size = LE_16(&rbt->frame_size_table[i*2]);) X9 k6 A* M; ]' b- {0 h' W9 u
  660.         video_frame_size = LE_16(&rbt->video_frame_size_table[i*2]);1 T" |' p4 W! x  N) O2 y
  661.         audio_frame_size = frame_size - video_frame_size;
    7 G4 i1 {7 V4 y0 V
  662.         if (fread(rbt->frame_load_buffer, frame_size, 1, inrbt_file) != 1)0 z( d9 ~9 o& E8 D& A# e& [
  663.         {
    5 l* E8 g2 T. e
  664.             printf("problem reading frame %d\n", i);
    / g3 Z3 M7 R, h+ M8 ^
  665.             return 0;3 `# Z$ C7 h4 U) {6 k7 c
  666.         }
    & F$ g/ B7 Q& \# [0 }8 D2 H. Q
  667. ' d2 r$ M( i& p! n/ C, Q7 H
  668.         scale = rbt->frame_load_buffer[3];
    5 U# n/ V- o( i+ r) F+ }( {
  669.         width = LE_16(&rbt->frame_load_buffer[4]);
    6 @+ O& ?+ W  \( p& N, ]5 n
  670.         if (max_width < width)8 k& d- ?% r& }  }
  671.             max_width = width;
    ) ]6 W  l4 s: ^6 b% t7 M: O
  672.         if (max_height < height)8 u( J. E& [' R4 w: m$ i! d' h4 K
  673.             max_height = height;, o+ W, J) _- r8 `, g% K& ~: l
  674.         height = LE_16(&rbt->frame_load_buffer[6]);7 M5 k* ]0 r6 _! f& c" h5 ~, G: ]
  675.         frame_x = LE_16(&rbt->frame_load_buffer[12]);
    % y# h% P+ W3 c5 l# a  u% M0 T
  676.         frame_y = LE_16(&rbt->frame_load_buffer[14]);* g% O1 U% g" n+ o# h0 b; x
  677.         fragment_count = LE_16(&rbt->frame_load_buffer[18]);
    1 ]1 }2 z2 C2 \2 ~/ {
  678.         decoded_size = width * height;: p) d2 Y7 ], `9 n9 z

  679. 7 n; m$ w* P0 ?' k4 x
  680.         printf("processing frame %d: %d%%, %dx%d, origin @ (%d, %d), %d fragments\n", i, scale, width, height, frame_x, frame_y, fragment_count);
    3 u) T3 @( H* T3 {( E+ R; h) R

  681. $ M# b0 J. V4 o+ l$ W* _
  682.         /* decode the frame */
    $ @! l( j3 @4 u$ k( g5 M' t
  683.         decoded_frame = malloc(decoded_size);8 \. i* P1 w, C3 c6 K2 ~
  684.         index = 24;
    1 O) ^& s( u  i5 _+ ]5 o: f
  685.         out_index = 0;
    6 V3 L  W2 g% ]+ S; `
  686.         for (fragment = 0; fragment < fragment_count; fragment++)
    5 ^! Z2 Q0 @$ Y" w+ Z. k
  687.         {
    9 {2 R' g* A+ z: [1 P, u
  688.             fragment_compressed_size = LE_32(&rbt->frame_load_buffer[index]);9 W( x  I' p$ D* R/ Y  [5 M
  689.             index += 4;
    ; P2 V; c+ B1 g2 T
  690.             fragment_decompressed_size = LE_32(&rbt->frame_load_buffer[index]);4 l- g3 t9 [- z& X; N8 ]
  691.             index += 4;
    4 L$ I2 q  \: ~7 |$ U+ W
  692.             compression_type = LE_16(&rbt->frame_load_buffer[index]);
    2 W" v1 V( d- n, |
  693.             index += 2;
    * s) A4 J; h$ j' F! ~. s) ]& W# Q

  694. 1 i4 Q+ k! U+ @4 q* K
  695.             if (compression_type == 0)+ t4 q4 I5 Z2 W; Z( ^
  696.             {8 J4 |, p, w( Y9 @& H" D
  697.                 init_get_bits(&gb, &rbt->frame_load_buffer[index],
    & Z9 C- h0 Q8 N" o# y+ }
  698.                     fragment_compressed_size);1 `, c+ s7 L$ u

  699. ( p- }8 Z6 h4 S
  700.                 while (out_index < fragment_decompressed_size)
    ( q- D" k$ F/ t5 s7 q, C# @
  701.                 {2 t3 I! H! Y3 U5 b
  702.                     if (read_bits(&gb, 1))
    0 f; T' b, y* G' p% g1 I2 x; C. w
  703.                     {
    : U8 u! ^9 f4 d- y
  704.                         /* decode back reference offset type */* U, q/ o& t: v$ F
  705.                         back_ref_offset_type = read_bits(&gb, 1);
    . X3 h; X4 Z7 X( k

  706. ( ~, U# N. r) l8 |- }
  707.                         /* back reference offset is 7 or 11 bits */
    7 K+ L, J% Q) D0 M
  708.                         back_ref_offset = read_bits(&gb,* x  o. i% E% F; `8 C6 X
  709.                             (back_ref_offset_type) ? 7 : 11);3 L& Y8 ~, q/ K" Y6 y

  710. 5 P: A: P& T$ W% f2 ?/ J
  711.                         /* get the length of the back reference */. n6 I# ^3 z5 K( H
  712.                         back_ref_length = get_lzs_back_ref_length(&gb);
    : O3 F4 i, u8 W  c7 u0 V9 ]$ b9 {( }
  713.                         back_ref_start = out_index - back_ref_offset;! k: r7 V6 [5 S
  714.                         back_ref_end = back_ref_start + back_ref_length;
    ( V9 I5 T  n1 i: o/ L& W
  715. ( P* H  T- O" H: X; n
  716.                         /* copy the back reference, byte by byte */: X* H2 a8 ?( E$ p" t- K
  717.                         for (j = back_ref_start; j < back_ref_end; j++)
    & H0 C; k7 a0 D& W" ]
  718.                             decoded_frame[out_index++] = decoded_frame[j];* A" j8 v0 t$ C! z% c. [
  719.                     }5 b% [% e. |- r+ R- H
  720.                     else! B; ]# j$ @1 u# o7 U6 o
  721.                     {6 B/ v' g2 _7 W' G, B
  722.                         /* read raw pixel byte */
    $ \/ F; \( A; M
  723.                         decoded_frame[out_index++] = read_bits(&gb, 8) & 0xFF;
    " _! A' s. t3 l) n. _
  724.                     }  }: d3 Q# ?7 N* a8 X
  725.                 }/ K6 m) U( R) ~4 h$ Q

  726. 9 A' |: Z6 q2 C7 B9 S/ Q2 z& Y1 b- @
  727.                 delete_get_bits(&gb);
    . c5 y6 x+ K( d6 O8 s5 }
  728.             }
      A8 J, U5 q' ^

  729. : N& N  J& N2 k! Q3 n
  730.             /* next fragment */6 B& I  F0 `5 K; Z
  731.             index += fragment_compressed_size;, E3 D4 S% d- I1 \" e- `+ d4 d1 `
  732.         }
    & C/ z: y' X% J1 G4 n% {5 x

  733. , _- |7 ^2 u8 a7 f. T% u
  734.         if (rbt->dump_frames)* R4 i7 k9 k: N/ Y- U/ ~  e+ z
  735.         {
    * W1 N$ Z8 E! n1 o
  736.             /* dump the original frame */
      E" X" f: R9 g# K
  737.             sprintf(filename, "original-frame-%03d.pnm", i);
    ; L7 l4 Q8 Q7 Q2 f+ ^, `5 x5 m
  738.             dump_pnm_file(filename, rbt, decoded_frame, width, height);
    ! I7 c2 Q$ c( I* Y
  739.         }; A1 W; Y* z* E; L" ]0 k
  740. / J0 a& S+ l1 @7 i5 M; Y
  741.         /* transfer the image onto the frame window */6 j, \. ]0 g; q0 x, q( N/ |! [
  742.         memset(full_window, 0xFF, full_window_size);+ M% p% v; U) h8 M3 P
  743.         index = 0;1 I% k- K) H  }7 x3 l
  744.         for (y = 0; y < height; y++)2 b( T/ V, ]6 ?
  745.         {, j2 `6 m( z. i0 C7 m$ U0 Z
  746.             out_index = window_width * (frame_y + y) + frame_x;
    9 n2 K& }- Q" ~' B! ]: T+ k2 E9 t
  747.             memcpy(&full_window[out_index], &decoded_frame[index], width);/ o9 b/ F7 f8 E9 y% ~) L8 x2 W7 ?( A
  748.             index += width;% D5 V' S" g# w& {2 i4 l3 t
  749.         }
    # Y4 o% r3 }* T4 c2 }
  750. ( L# Z5 i1 \" U$ \, l
  751.         /* write the subtitle */
    7 G6 X& e3 ^. O( {- j. r  w& ~% \
  752.         subtitle_frame(rbt, full_window, window_width, window_height,
    * I5 r% Y# A; a7 D, N6 b0 X. G
  753.             i * MILLISECONDS_PER_FRAME);
    . W- q4 F3 T. i! s8 }
  754. * T- f* w0 ?; c0 x/ }% k
  755.         /* figure out the smallest change window */3 W, L. j, d) @2 q, d  ~% ]8 F
  756.         window_top = frame_y;1 ^. [5 M2 J* s$ \' d5 z. a
  757.         window_bottom = window_height;9 E. ?1 r% [% ~+ E' ]
  758.         window_left = 0;; _, M3 O, t; _( h* ?
  759.         window_right = window_width;4 s% X9 u; P) B  [
  760.         window_size = (window_right - window_left) * (window_bottom - window_top);7 m6 z' }- [# n0 B* G+ P

  761. 5 r. d& \  Q2 s# I
  762.         /* compress the frame */
    . J# v5 Z8 f; F1 q- d1 [
  763.         reset_put_bits(pb);
      y  W5 q4 T6 L  Q
  764.         compress_window(pb, full_window, window_width, window_top,4 r% x" A: o4 \
  765.             window_bottom, window_left, window_right);
    1 N7 |0 F# [6 C: U
  766. " M; b. e% }2 A" c7 [; u
  767.         if (rbt->dump_frames)$ g) l& P/ x3 j4 B. O, g& _
  768.         {/ m4 J8 ?% T. o& `
  769.             /* dump the frame plotted onto the full window prior to encoding,/ Q  I! j. G; V7 @+ Q9 x) [+ {
  770.              * with subtitle */
    5 V: g( C) f9 T( C) l$ v1 t0 N7 ~
  771.             sprintf(filename, "pre-encoding-frame-%03d.pnm", i);
    * L) h# J" z9 c( W
  772.             dump_pnm_file(filename, rbt, full_window, window_width, window_height);3 D* `1 E9 h. X+ u
  773.         }
    ( Z+ w$ f! a, E+ x4 N' y" W( W

  774. : f# ^" t% j! z5 `$ g5 ?' D. }
  775.         free(decoded_frame);/ h" b& F* K1 T5 |" `, s

  776. ; \: A2 e  s1 j/ Y6 C
  777.         /* update the frame header */
      o$ v" ?& i4 y1 v! e5 |: V# e3 ^
  778.         /* width */
    7 ^; b, S% S; z( T
  779.         rbt->frame_load_buffer[4] = (window_right - window_left) & 0xFF;/ B0 p- u4 `9 F2 R( H" z  ?
  780.         rbt->frame_load_buffer[5] = (window_right - window_left) >> 8;
    * M5 t3 O8 A& D" b; P6 ]; h
  781.         /* height */
    , Q/ t4 f5 Y3 `4 \4 m/ O
  782.         rbt->frame_load_buffer[6] = (window_bottom - window_top) & 0xFF;
      J# g3 h6 l( L" T6 h" z
  783.         rbt->frame_load_buffer[7] = (window_bottom - window_top) >> 8;
    . M" ^* d" {6 T0 U! c# x
  784.         /* origin X */
    / u1 C. L  N3 s2 v) ^" P. E0 }
  785.         rbt->frame_load_buffer[12] = window_left & 0xFF;
    " O! [6 R6 P- F, V0 M
  786.         rbt->frame_load_buffer[13] = window_left >> 8;; `# y2 T6 W% D* V3 Z: E
  787.         /* origin Y */! h! t, R4 u5 f4 R/ L+ q
  788.         rbt->frame_load_buffer[14] = window_top & 0xFF;
    % n* E, N/ N% N% H7 R6 l
  789.         rbt->frame_load_buffer[15] = window_top >> 8;
    6 p& x+ L) m7 d- E
  790.         /* fragment payload size */0 O, G/ C9 _' m0 k& h/ t6 a4 \
  791.         rbt->frame_load_buffer[16] = (pb->byte_index + 10) & 0xFF;
    7 N- A7 V. J; S4 P" y" a
  792.         rbt->frame_load_buffer[17] = (pb->byte_index + 10) >> 8;
    9 M: A# }3 k& \4 E' Y, ~& _
  793.         /* fragment count (1) */* M2 ]' E: }. i/ U. z; A
  794.         rbt->frame_load_buffer[18] = 1;
    / i: S) _5 D0 `. n2 F( L! D
  795.         rbt->frame_load_buffer[19] = 0;: v4 M& o+ A2 \

  796. % U9 y" |2 h2 R( o9 Q
  797.         /* update the fragment header */% @! v; s& s% S0 K
  798.         /* compressed size */
    / i; D4 A" y* b" A, b
  799.         rbt->frame_load_buffer[24 + 0] = (pb->byte_index >>  0) & 0xFF;
    3 [2 S/ C+ ?# [2 z2 y
  800.         rbt->frame_load_buffer[24 + 1] = (pb->byte_index >>  8) & 0xFF;
    ! E! L$ L- }' C+ O' F4 @; f' U0 b
  801.         rbt->frame_load_buffer[24 + 2] = (pb->byte_index >> 16) & 0xFF;) i: Y9 P' Q9 M: z" M
  802.         rbt->frame_load_buffer[24 + 3] = (pb->byte_index >> 24) & 0xFF;4 H* i( N5 ^' X# S0 Y' f2 M- ]
  803.         /* decompressed size */% Y7 T' w* y) S: \/ X
  804.         rbt->frame_load_buffer[24 + 4] = (window_size >>  0) & 0xFF;
    * O. s& a3 o* h8 c& i
  805.         rbt->frame_load_buffer[24 + 5] = (window_size >>  8) & 0xFF;% c4 ]4 _+ Y3 q
  806.         rbt->frame_load_buffer[24 + 6] = (window_size >> 16) & 0xFF;
    9 Y! e' G0 d' g4 b2 v5 H# p5 i/ k" @
  807.         rbt->frame_load_buffer[24 + 7] = (window_size >> 24) & 0xFF;  M+ t' r4 u4 N( @* ~4 \
  808.         /* compression format 0 */
    5 P" i+ c% p  J
  809.         rbt->frame_load_buffer[24 + 8] = 0;
    7 H  ]0 [: K7 j5 j" j+ s
  810.         rbt->frame_load_buffer[24 + 9] = 0;4 L$ |- D' m; h, O/ {. c9 t
  811. * [" h: U3 P; A1 x4 X
  812.         /* write the 24-byte frame header and the 10-byte fragment header */
    2 B2 {) d1 [0 o* w1 w* X
  813.         if (fwrite(rbt->frame_load_buffer, 24 + 10, 1, outrbt_file) != 1)7 A- u8 ?3 O# V7 T: g8 R% z
  814.         {
    . E9 g& X* K3 n0 ^! e
  815.             printf("problem writing frame %d\n", i);
    9 i7 S. z$ E- S1 i9 O
  816.             return 0;2 W. T1 U9 }: h1 @9 t
  817.         }
    2 m3 }( M( j; n2 ?: P5 N$ L. `

  818. " l: ]1 ]7 U& H
  819.         /* write the new compressed frame data */
    8 f: w/ |: Q4 K/ M7 D6 ~
  820.         if (fwrite(pb->bytes, pb->byte_index, 1, outrbt_file) != 1)
    $ j  W7 k3 h+ a7 k
  821.         {
    ( v4 w4 p8 \! b5 g! N
  822.             printf("problem writing frame %d\n", i);
      k7 X3 h3 Z2 g/ u3 o4 o: f1 {/ Y! c
  823.             return 0;
    " L) J2 K2 N6 p9 G, q9 C
  824.         }% G% D9 K- y+ D1 C- L- z( [
  825.   j/ W! r+ [* T; t$ P: y6 G+ r
  826.         /* write the audio data */
    3 W: k6 y* J1 r
  827.         if (fwrite(&rbt->frame_load_buffer[video_frame_size], frame_size - video_frame_size, 1, outrbt_file) != 1); O0 `, r2 R+ H" F" @
  828.         {
    / H/ V) y7 T% T' N9 j: m$ u
  829.             printf("problem writing frame %d\n", i);
    # g: m1 l/ G* [! N1 b5 u. ]
  830.             return 0;+ c  t1 }# B5 A0 D& v  |( P
  831.         }; ]6 D2 N3 F( O# y$ W8 n9 m* A) d3 [

  832. ! {6 _# G+ b; |5 u: D
  833.         /* update the table entries */+ v' U! [- a5 J% @' C$ S
  834.         video_frame_size = pb->byte_index + 24 + 10;
    ! X+ V- _) Y) T8 ?
  835.         frame_size = video_frame_size + audio_frame_size;
    8 p! b/ ]( X) |
  836.         rbt->frame_size_table[i*2+0] = frame_size & 0xFF;! F$ Z! A. s6 Z
  837.         rbt->frame_size_table[i*2+1] = frame_size >> 8;
      s4 X+ i- ~0 N* z# O
  838.         rbt->video_frame_size_table[i*2+0] = video_frame_size & 0xFF;
    ! b4 @6 f* R9 A. f: y
  839.         rbt->video_frame_size_table[i*2+1] = video_frame_size >> 8;$ r* K+ r% h# h* ?
  840.     }
    # K: O: u# a9 F

  841. & G! z4 Q1 W+ z8 D" i- v$ y
  842.     printf("maximum dimensions seen are %dx%d\n", max_width, max_height);4 B1 J# h' q3 F

  843. : H  w4 G9 r# R3 m+ v
  844.     delete_put_bits(pb);) R6 C6 a& ^6 L" e; p. y+ D
  845.     free(full_window);1 g* F' P- k+ t( p! N. Q

  846. ! s, {9 e8 y6 @1 L
  847.     return 1;6 W: E& ]2 w; h/ t  S) Q
  848. }- W/ G( n% ~- X8 z
  849. 3 Z" f/ C: w6 F% m  U
  850. int main(int argc, char *argv[])
    ) K2 g: C3 V2 b' ?) `. V
  851. {2 }, A. y. A4 C0 Z. R/ E
  852.     char *subtitle_filename;
    ! X9 r; y, \* U4 b
  853.     FILE *subtitle_file;0 E4 z0 f  V) C1 |+ [
  854.     char *inrbt_filename;& p9 `4 q, D% Z- i1 G+ [; D1 ]
  855.     FILE *inrbt_file;
    8 h9 q6 M+ ?6 X0 s. s; }
  856.     char *outrbt_filename;
    ) s- ~; d2 K6 ?: p, t
  857.     FILE *outrbt_file;
    6 P0 _/ O. r1 Z9 P' i3 _
  858.     rbt_dec_context rbt;: a( J+ [- M7 L7 s  p
  859.     int origin_x;& a! F& `2 y7 C# \/ L, a
  860.     int origin_y;
    5 `* L4 ^. S: @' e" S) u
  861.     int window_width;
    9 B6 E- G! Q- s; m7 r  R9 `. k
  862.     int window_height;
    4 C& O) z7 A) V1 t, w( U; E
  863. " U( ]# {! {' J) s3 K
  864.     /* testing the bit functions */5 G' `5 n" R+ ^6 c, c. U3 w1 L6 c
  865. #if 07 x$ r: t5 B+ O' e
  866.     int i;
    2 k7 o$ f2 f3 V2 l* }. K/ c1 q
  867.     uint8_t bytestream[] = { 0x55, 0xAA, 0x00, 0xAA, 0x55, 0x77, 0xFF, 0x1B, 0x70, 0x8F };
    8 \  L6 {/ g7 m, p3 q
  868.     int bytestream_size = 10;" A' C+ S+ _! a& g% `. q
  869.     get_bits_context gb;
    + L: }3 M. x9 R" |
  870.     put_bits_context *pb;2 o' u$ [( t$ e' i' a
  871.     int bits;
    ) F/ @! r! J# C; T

  872. 6 ?: I/ s% {, ^7 n
  873.     init_get_bits(&gb, bytestream, bytestream_size);7 P* \5 x6 B3 x, G! N( X2 C3 o
  874.     pb = init_put_bits();# v% |0 |4 |& W+ N

  875. ' b: _5 I5 E: f$ `( p: a4 J
  876.     for (i = 1; i <= 12; i++)
    6 Z' d+ G3 u* b3 G+ x1 x! e
  877.     {
    . R. U% u7 `6 v, g, S
  878.         bits = view_bits(&gb, i);
    / u  }8 H/ w5 c! e+ ]; R
  879.         printf("view %d bits: %d\n", i, bits);3 s( O! u" q4 O# ^  y
  880.         printf("read %d bits: %d\n", i, read_bits(&gb, i));* e8 v# _/ W6 s1 C
  881.         put_bits(pb, bits, i);
    * A7 Y8 E+ x: p  n4 b$ A
  882.     }9 H) M5 U- z; V# N
  883.     put_bits_flush(pb);: J2 {* P- h8 N4 Y1 c* v7 c2 o5 |
  884. % Q' s" T2 B* W- h) U
  885.     printf("original bytestream:\n");. g  K5 r6 N! s* p
  886.     for (i = 0; i < bytestream_size; i++)4 z6 g- y- Q" f% f7 d, a5 e
  887.         printf(" %02X", bytestream[i]);% O/ q8 p+ N* U9 Y8 [! F; M" N
  888.     printf("\nnewbytestream:\n");& j2 ~5 @) @7 A) s
  889.     for (i = 0; i < pb->byte_index; i++)6 \3 u/ o: a7 x" a$ `
  890.         printf(" %02X", pb->bytes[i]);7 k  `) u& ^# L9 T1 J
  891.     printf("\n");
    ( C2 N6 H* L8 V

  892. 0 ~0 b; h6 i8 J% f
  893.     delete_get_bits(&gb);3 E* X4 u( u% J/ o* `3 }
  894.     free(pb);
    , F; G" c' q  w3 H
  895. #endif
    5 z) h. O5 g: I$ ~0 Z/ m% U
  896. # |4 Z& v9 Q" e$ W7 H# z
  897.     /* validate the number of arguments */
    ' N& m9 p) a) x5 ]: u; y2 T8 g( i1 g
  898.     if (argc != 8 && argc != 9)1 y# x' K) q/ h" W. ?
  899.     {9 Q: i: v4 g- n) q, z
  900.         printf("USAGE: subtitle-rbt <subtitles.ass> <in.rbt> <out.rbt> <origin X> <origin Y> <width> <height> [dump_frames]\n");
    9 J) @  O0 m/ J. t/ p6 I1 _* P/ S
  901.         return 1;
    / o& d7 h* B9 ^( u" l0 L
  902.     }6 o/ d) v& \8 P. }3 r  g* v
  903.     subtitle_filename = argv[1];
    2 Y' M; w9 J' z* k' M- Y4 s" w# _
  904.     inrbt_filename = argv[2];
    . y- d- q/ A6 ?  f/ R* k
  905.     outrbt_filename = argv[3];/ |: |. B8 W/ c) F  X" B  \: p/ Y
  906.     origin_x = atoi(argv[4]);
    % a4 J+ U/ R: \5 T0 f% i$ q7 `
  907.     origin_y = atoi(argv[5]);
      ^9 ^/ b$ J1 i: \6 [1 [
  908.     window_width = atoi(argv[6]);
    & t5 B# w8 {$ r$ o. |
  909.     window_height = atoi(argv[7]);
    : j5 h4 E7 I- U" p7 C
  910.     rbt.dump_frames = 0;7 w. M0 n2 g. c# K( d, @
  911.     if (argc == 9)
    " d/ q% [- B! `; Z' E$ q
  912.         rbt.dump_frames = 1;
    5 U2 m+ D+ G1 T1 r
  913. $ a% I" y& X, e% t0 |# F% \
  914.     /* verify that the specified input files are valid */
      ?- g! _8 c+ N
  915.     subtitle_file = fopen(subtitle_filename, "r");! r3 Y. j2 ^2 i4 S( |
  916.     if (!subtitle_file)3 v8 X! _( D2 S3 A
  917.     {! f! w( @9 B7 d# b& k  k+ r
  918.         perror(subtitle_filename);
    ! ?( G% S6 a  c" U" U3 r/ Y' A9 F
  919.         return 1;( ^! f5 ?8 s  ^5 V
  920.     }
    ) R* m+ w& l5 m6 B. `
  921.     fclose(subtitle_file);
    & T$ F/ c$ s/ t1 N* Y  n
  922.     inrbt_file = fopen(inrbt_filename, "rb");
    - `0 t$ x4 t( C; U7 u
  923.     if (!inrbt_file)! f# B* V4 D  ]! A0 E
  924.     {: {* \0 E) Z: o( y) Y- R
  925.         perror(inrbt_filename);' o# ~7 M' G  n. H7 Z& g
  926.         return 1;* d6 U; \: u- R4 r
  927.     }+ ^1 _# G- C) f9 d: ]) e$ U
  928. 7 @* K* |; P/ O! _$ v4 T
  929.     /* initialize the subtitle support */4 C! E1 J; X9 O/ M' A  @9 ]
  930.     rbt.ass_lib = ass_library_init();# u# Y; E+ t# }) I1 I- m4 z
  931.     rbt.ass_renderer = ass_renderer_init(rbt.ass_lib);
    % [7 a1 @; v9 O" Y
  932.     rbt.ass_track = ass_read_file(rbt.ass_lib, subtitle_filename, "UTF-8");' x# }( i# s/ V7 r$ ^9 Y
  933.     ass_set_frame_size(rbt.ass_renderer, window_width, window_height);2 F- l% q0 Z6 a
  934.     ass_set_fonts(rbt.ass_renderer, NULL, NULL, 1, NULL, 1);" v% T- D, w" t* E% ?
  935. ; P+ @' J& X3 q/ d
  936.     /* open the output file */
    / u- N; @" f" {: A: l& g$ d
  937.     outrbt_file = fopen(outrbt_filename, "wb");
    $ ?6 i  w, N) T& o1 }: m  z
  938.     if (!outrbt_file)$ j, T3 v$ [2 X
  939.     {" \, g: F# r3 N; }: ~
  940.         perror(outrbt_filename);1 P% p2 B6 W# a- v/ M: H
  941.         return 1;
    , c# a* _1 t# z8 `
  942.     }" Q) r8 d; z7 A& c/ S) E

  943. , p, l7 M! _; b  o
  944.     /* transfer header from input to output */% s# L2 M" `: \
  945.     if (!load_and_copy_rbt_header(&rbt, inrbt_file, outrbt_file))* q* r8 B' E- h" w  X5 K
  946.         return 1;
    1 T3 r  k8 v: C1 j: j2 x" d2 D
  947. # J9 W/ r6 A' D1 c5 `
  948.     /* rewrite the frames */, J& [+ j. l6 ?7 A  W* Q
  949.     if (!copy_frames(&rbt, inrbt_file, outrbt_file, origin_x, origin_y,
    - ~& o3 q  M2 \' A8 b
  950.         window_width, window_height))1 L  ~& J2 i9 u& ?/ i( l
  951.         return 1;4 v/ ?& K5 l% a5 J& X

  952. $ d" W; J" c9 p, G
  953.     /* write the modified frame size tables back to the file */
    + B+ J& i6 q& z. S; q- i- z
  954.     fseek(outrbt_file, rbt.video_frame_size_table_offset, SEEK_SET);+ {# y- U8 {7 Q* O
  955.     fwrite(rbt.video_frame_size_table, rbt.frame_count * sizeof(uint16_t), 1, outrbt_file);
    5 A; n& Z. `+ _0 y! ^/ F
  956.     fseek(outrbt_file, rbt.frame_size_table_offset, SEEK_SET);( c% v: Z* f' b5 T  M3 e; n
  957.     fwrite(rbt.frame_size_table, rbt.frame_count * sizeof(uint16_t), 1, outrbt_file);; s) x. O( a/ W, N0 _

  958. ) f# M7 N# B1 [1 A/ w; @% d
  959.     /* finished with files */
    7 q8 Z. w' C1 h+ E- Q" w
  960.     fclose(inrbt_file);! x! {! Z* A1 D; [9 J
  961.     fclose(outrbt_file);0 H: h1 U# G4 }4 [( q5 k  m

  962. % I5 R1 |$ G2 n2 b
  963.     /* clean up subtitle library */: p7 `' h1 u+ ^
  964.     ass_free_track(rbt.ass_track);
    8 U1 o) b8 V/ W9 x1 G$ \
  965.     ass_renderer_done(rbt.ass_renderer);
    8 w, A* ?* {% r5 V
  966.     ass_library_done(rbt.ass_lib);7 Q* `  l- j6 G4 E) E
  967. ( D% U, W% z+ z. ]
  968.     /* clean up */8 a; }) ~- o0 P* D$ e' Z
  969.     free(rbt.frame_load_buffer);
    . L! f. C. l0 S$ m) C' ^2 S+ U
  970.     free(rbt.video_frame_size_table);+ J: v  B" k6 r3 g$ _
  971.     free(rbt.frame_size_table);9 d) `% R. y3 X  w4 G1 W9 _9 J, Y

  972. % y% C1 Z6 U# g+ M
  973.     return 0;9 _: _" i3 a" r# t" g( T
  974. }
复制代码
. F* G. u5 H% {

- X- x7 y$ ?% i' v, ?5 [; `& g- T% m

% e4 y1 _( {$ v3 T" H7 a
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 很美好很美好 很差劲很差劲
回复

使用道具 举报

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

使用道具 举报

板凳
 楼主| 发表于 2009-11-19 11:38 | 只看该作者
引用第1楼soring123于2009-11-19 11:09发表的  :
* r6 o7 u0 ^( ~0 l6 _" O: R这游戏有字幕吗?
5 f& X5 e- R1 y  H& @  h* U! Q& y
好像没有字幕,我说的是给视频外挂字幕方式的汉化。% v* c" o* V5 I: j7 U
就像syberia2汉化版下面那行字一样。
回复 支持 反对

使用道具 举报

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

使用道具 举报

5#
 楼主| 发表于 2009-11-19 17:39 | 只看该作者
引用第3楼soring123于2009-11-19 17:07发表的  :1 j+ s4 A. Y$ d* X( [# V
我记得是没字幕的 比较麻烦 都是视频的

+ q7 F! z6 l4 ]" `, r" f+ _给视频外挂字幕方式汉化也许能行。
/ O: r( {& |$ j9 |5 W* [要结合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日,是全球华人共同的冒险解谜类游戏家园。我们致力于提供各类冒险游戏资讯供大家学习交流。本站所有资源均不用于商业用途。

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