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

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

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

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

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

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

本帖最后由 shane007 于 2021-1-2 13:56 编辑 & o$ d& `# [2 f0 X- c9 R/ j$ B& B, p

6 m: Z% z- e7 b9 x( c, T最近找到了一些和幽魂系列Phantasmagoria 有关的资料,3 S9 d. N4 ^0 t  A2 N: X& X4 A$ F8 _
也许将来可以用于汉化。
# e& t$ s8 }3 s& ?" T
6 M. s1 x1 c8 W' B$ ?+ A. @/ a和日文版有关的信息) y/ n6 J! c; C
http://anthonylarme.tripod.com/phantas/phintgtp.html# i8 }5 q# M/ }4 b

( x0 y2 p# m' I3 Z. o相关工具
2 j; K! y7 d; v; O1 r9 c) Rhttp://anthonylarme.tripod.com/phantas/phcheats.html
0 D& k0 K# c3 F* ?1 ]-----------------------------------------------------------------------
' T* a. |" Q" r: {$ p9 x2012/1/2  更新# B  |6 d9 W" g6 j' o
关于幽魂游戏的字幕
0 u0 ^& L' [: S5 pPhantasmagoria subtitles function discovered - ScummVM :: Forums  }- \) N- W7 f( b" L3 Q& Y' d

" C& I# u# y: `$ U" ?- XVMD文件- X3 Q& l, z  w9 [4 O: J
Subtitling Sierra VMD Files | Breaking Eggs And Making Omelettes (multimedia.cx)VMD - MultimediaWiki$ ]2 m7 q/ C( {+ e$ e2 u
" p" {9 \  z3 a! e, S6 H
字幕
; f* g3 N4 O: R( O8 _5 ^Subtitling Sierra RBT Files | Breaking Eggs And Making Omelettes (multimedia.cx)
1 b' b* t/ y) l# N# `# @  n" Q1 ~9 ^( E4 l3 t  t1 l
FFmpeg/subtitle-rbt.c at feature/VMD_encoder · multimediamike/FFmpeg · GitHub. V; k( D5 D2 E8 }. Z
  1. /*
    # ?" m- v# }6 X( f) e8 H$ K
  2. * subtitle-rbt.c! h% X" w0 b5 ?# `, H: i  b
  3. *  by Mike Melanson (mike -at- multimedia.cx)
    9 q* K3 F6 m/ y' p: v1 M9 [
  4. *
    , }% J" I4 l! r8 G9 f) R5 S& F
  5. * build with this command:! x" v( }2 I. e, H( W" I  f# C
  6. *   gcc -g -Wall subtitle-rbt.c -o subtitle-rbt -lm -lass
    0 ~4 ?4 m. I! c* _, r
  7. */9 K0 |, Y) I5 _3 ~4 d

  8. & `/ Z8 S: a% B1 A/ u' O( I) s
  9. #include <inttypes.h>4 ]- o, ]& I3 W6 b/ z
  10. #include <math.h>
    5 G9 p, d0 {! K/ t
  11. #include <stdio.h>
    - }8 _) o: e/ U, C3 @
  12. #include <stdlib.h>
    2 u& k# D7 J) I% F/ V
  13. #include <string.h>
    5 C; K3 t& K5 O* d
  14. - R2 {+ `+ s4 v  [
  15. #include <ass/ass.h>9 A" ]7 t- V0 U' l1 Q
  16. 5 r) p2 X7 J3 r2 F
  17. #define LE_16(x) ((((uint8_t*)(x))[1] <<  8) | ((uint8_t*)(x))[0]). _+ X+ I9 V( T/ f- y
  18. - b! k" @- c: r$ @( i5 J
  19. #define LE_32(x) (((uint32_t)(((uint8_t*)(x))[3]) << 24) |  \1 H. C. Y$ p& z& O4 B. j: K) U
  20.                              (((uint8_t*)(x))[2]  << 16) |  \
    9 H; ]8 \: Q2 f2 M+ Y$ K
  21.                              (((uint8_t*)(x))[1]  <<  8) |  \" r8 ]6 q/ `- s3 e- B$ N0 y. b+ K
  22.                               ((uint8_t*)(x))[0])( ]4 f8 d" w1 }! Y5 {0 a

  23. - P- h5 Z/ [6 h: h* _2 b! d7 N
  24. /*********************************************************************/; m2 `" |7 y) i" t  b  e

  25. * Q9 m3 v" \" `# a, a* A
  26. /* Bit reader stuff */4 l% D' B, ~) F6 x: X4 e
  27. * ^3 n5 ]  b9 ~, h/ _; V: x) K) O" n
  28. typedef struct
    - D$ t: c0 Q8 n* s+ o% ]7 v4 j
  29. {: i% a! {% p) v
  30.     uint8_t *bytestream;
      Q8 ?% u  m# I" Z! @' K/ t
  31.     int bytestream_size;
    ' A5 L2 \8 \0 o8 M
  32.     int index;1 V; P) }  u# L/ p  z
  33.     uint32_t bits;
    0 d( d$ R- b" J! E
  34.     int bits_in_buffer;* v6 O$ ?) o" i
  35. } get_bits_context;9 T3 w5 K7 W2 g$ Z& e9 L- {
  36. 4 E. R& a# j9 [. c7 ?4 C5 [3 Q2 [
  37. static inline void reload_bits(get_bits_context *gb). c; U) N& l, I* _* [( o2 w+ C$ n
  38. {
    0 n$ l) Z1 t6 ?" g7 S' I
  39.     while (gb->bits_in_buffer <= 24)3 d5 e/ t) U4 I% X8 u+ [; S
  40.     {2 v5 P. o) W/ f# J6 T
  41.         if (gb->index < gb->bytestream_size)6 d; y* G. O* k" M( j8 p1 L
  42.             gb->bits |= (gb->bytestream[gb->index++] << (24 - gb->bits_in_buffer));
    ' m8 c2 W8 y. m7 T6 T
  43.         gb->bits_in_buffer += 8;
      C' M' Z4 C* |1 [+ A
  44.     }7 z0 Y* H4 x7 x1 O- X. v
  45. }, v" r9 c+ i( v2 y$ ^. f: q" S+ V

  46. ) V8 Q1 b- C; S7 Z( G5 Z" U( d' L
  47. static void init_get_bits(get_bits_context *gb, uint8_t *bytestream, int size)4 c, q1 ]0 M4 O4 ?8 S4 U) Z
  48. {
    # L' {; q# S* _7 {8 T$ O6 m
  49.     gb->bytestream = malloc(size);7 f( C8 }" r8 z: q6 A* |8 D
  50.     memcpy(gb->bytestream, bytestream, size);) ]7 I3 B% S/ z7 E
  51.     gb->bytestream_size = size;( x) _9 c3 |, C
  52.     gb->index = 0;
    / x: Q  U9 @" `9 ^" A
  53.     gb->bits = 0;5 l6 K8 W+ [6 B1 C
  54.     gb->bits_in_buffer = 0;
    # M) M2 y. h) _% [" L3 W" w5 s5 t

  55. 0 R4 y/ c8 a9 o0 Z1 R/ v: z6 J8 X. {) x
  56.     reload_bits(gb);' C/ X8 `$ }% D6 I1 N( F
  57. }6 `$ Q( ^' F1 j6 Y" F( b7 n
  58. * U6 }* Z* d$ o5 t  |3 f
  59. /* read bits without consuming them from the stream */
    6 U6 x5 a" V. ?, l$ `8 A
  60. static int view_bits(get_bits_context *gb, int count)/ T3 p' s) E( u
  61. {2 I; W, [; q8 }- W" h' q* B
  62.     if (count >= 24)6 \6 J5 }5 b7 r* ]0 g
  63.         return -1;
    3 B- Z. \$ b6 _# s+ |3 `
  64.     if (gb->bits_in_buffer < count)9 R1 P& Z% j& [! P7 _1 S
  65.         reload_bits(gb);
    7 s: t# z' p& B/ P/ W
  66.     return (gb->bits >> (32 - count));
    6 [: ], G0 k: K0 B% j- e
  67. }
    & {# l  @- z: ?; {( ~5 U; t

  68. ( N5 b" V5 p/ t; n" u# Y' ]
  69. /* read and consume bits from the stream */
    + a4 A( H# {) Q- G: o1 p8 m" g
  70. static int read_bits(get_bits_context *gb, int count)$ T  U) |; G' Y2 Q$ h+ `1 j* |
  71. {
    0 B. i8 A" \4 T" J/ L
  72.     int value;
    / p9 m2 F* {+ ]5 |

  73. , Z3 m; }* |+ [4 Y2 F
  74.     if (count >= 24)9 ]7 K, _- D, J6 x& |
  75.         return -1;, k7 I* y( Y1 Z8 {3 K( |1 c# g

  76. 5 X9 ?9 Z, I/ Q
  77.     value = view_bits(gb, count);& S+ a3 `" n) v' o0 v4 L# Z
  78.     gb->bits <<= count;% t4 ?: }4 G1 D6 d2 r! S" @
  79.     gb->bits_in_buffer -= count;
    & |" z. {; I& H% e( F( m( d$ _& t
  80. % w) f7 Y$ ?+ k" n, Y7 W/ y9 @6 l
  81.     return value;. ?) U( i1 w  U$ A" V& F$ H* ~' }
  82. }
    ; j) u: {: T* k9 w0 G

  83. ! x% x7 n- V7 y. ~8 v' p
  84. static void delete_get_bits(get_bits_context *gb)
    6 U" h; k' n) f3 F6 A. G
  85. {
    % M/ E  V' D' \" r& M& W* A
  86.     free(gb->bytestream);6 e/ A) F! i- Z
  87. }
    2 d7 K; ]6 V$ E( t. X3 t! o5 j

  88. ; C  _* Q/ L. h1 c3 J+ w
  89. /*********************************************************************/
    / C- g9 a2 l# S1 H
  90. : _- f: b6 F% _
  91. /* Bit writer stuff */4 [2 g. ^1 K$ g$ K/ d: H
  92. % i8 G2 @+ Q- q$ p
  93. #define MAX_PUT_BITS_BYTES 63000
    4 _3 ^" Z" ~: q8 T$ _/ k6 ^1 d
  94. typedef struct
    . m5 f& L, S, a! N0 W8 G. U1 K' q
  95. {
    8 o" D5 l* ^1 _4 ~" O% N
  96.     uint8_t bytes[MAX_PUT_BITS_BYTES];7 \$ T6 ~- A! a8 U! w+ e1 p- m
  97.     int byte_index;( z2 q; \0 k2 r
  98.     uint32_t bit_buffer;. l/ _, F- j4 w  k
  99.     int bits_buffered;
    # x  k* T4 C# M& b2 n: O
  100. } put_bits_context;
    , x1 }$ ?+ i* [) c, y
  101. . B' W# \# N7 |. g+ p
  102. static void reset_put_bits(put_bits_context *pb)
    3 q  @! M& r3 s# E  g! r
  103. {
    , n4 S) `2 h0 v4 M
  104.     memset(pb->bytes, 0, MAX_PUT_BITS_BYTES);
    1 S. e9 [0 \: t" N: j
  105.     pb->byte_index = 0;4 F9 @& Z& }% x  {: b& L+ O- o
  106.     pb->bit_buffer = 0;
    / l8 x! K9 A( h1 C6 }' i' W$ [
  107.     pb->bits_buffered = 0;1 u0 R" K! k1 X5 k* `/ V9 ]3 u
  108. }
    8 Y& |6 E% D7 V
  109. / ]! p' z$ c! x5 d: X& G4 B* k
  110. static put_bits_context *init_put_bits()
    0 k2 z/ u8 {8 ]2 |7 d9 [
  111. {
    * F5 e$ W0 x4 Z2 E  M' O3 p
  112.     put_bits_context *pb;* {* `" P3 o. A* g+ G
  113. % I0 i0 @% Q0 s5 W; U! m
  114.     pb = malloc(sizeof(put_bits_context));
    # {' C, {% n0 p. X& O# D1 G' i- t
  115.     reset_put_bits(pb);1 c/ ~% ?' ]9 V! v; w

  116. 1 }# \9 a  {$ z6 U0 c: O0 z
  117.     return pb;- h8 J1 O. x' m/ t
  118. }
    8 m" c* N  b, x- O8 k6 ^

  119. . C6 S4 J- N( x# t$ B
  120. static void put_bits(put_bits_context *pb, int bits, int count)2 G% O% Y( b2 W; o/ d4 R- Y  @
  121. {
    7 u# t- x( T6 x4 f3 ]
  122.     pb->bit_buffer <<= count;; N  A6 w4 O4 x4 i2 h% j
  123.     pb->bit_buffer |= (bits & (~(0xFFFFFFFF << count)));8 h) N/ G* {' T( J) `2 S
  124.     pb->bits_buffered += count;) y! J  J2 n, Y+ N- K

  125. & O3 \1 W9 _: |$ i* x( `8 V
  126.     while (pb->bits_buffered >= 8)
    # e  y! t9 R" ^; ?6 {* T* h4 `: d' P( v
  127.     {
    % V, _# E- Q/ I
  128.         pb->bytes[pb->byte_index++] = pb->bit_buffer >> (pb->bits_buffered - 8);
    ) d  u0 v3 W" h. O: a
  129.         pb->bit_buffer &= (~(0xFFFFFFFF << (pb->bits_buffered - 8)));" f! Q& d, U4 h& `$ t
  130.         pb->bits_buffered -= 8;* y3 O5 M- B5 F
  131.     }% Y  X4 M3 L  b+ `6 c7 ?, c
  132. 8 v4 X. J1 N; }; Z
  133.     if (pb->byte_index >= MAX_PUT_BITS_BYTES)$ b" L3 l& Q' f
  134.     {) k! M" t1 N' T9 b' a
  135.         printf("HELP! Bit overflow\n");
    / N! n' P, M& K
  136.         exit(1);
    / v. q0 z, O0 j9 L2 T
  137.     }
    . L2 S6 U6 p$ C/ l2 Z8 y. |0 t$ _4 |
  138. }6 ^( y+ K1 J% M! m2 D1 k
  139. 6 n. R( A- c2 {6 l% {7 F
  140. static void put_bits_flush(put_bits_context *pb)& ?1 w" X% X" _+ O3 d
  141. {# i& K2 j8 J0 @: M$ k: Z
  142.     if (pb->bits_buffered > 0)
    2 U3 [5 J/ N/ p$ C/ i+ F8 D
  143.         pb->bytes[pb->byte_index++] = pb->bit_buffer << (8 - pb->bits_buffered);
    3 u) y1 k5 r% r! S3 h! M
  144. }
    5 E  Y" A4 T+ z, N
  145. 6 g$ T# f4 M& a8 Q( a, y
  146. static void delete_put_bits(put_bits_context *pb)$ E7 z: _, Q- Z, X; N
  147. {: Z7 `" T) M, s8 w' n, Y
  148.     free(pb->bytes);& X. s0 a' _# [
  149. }
    1 ~# h, h+ [- N, U: j/ u9 Z7 Y1 L

  150. 5 i- V6 d( n8 N4 R1 |" @8 n1 y+ J; ~
  151. /*********************************************************************/
    % \  _" v4 V% l! Z6 G, Z
  152.   c/ L) p0 t' A( z
  153. /* RBT functions */4 J5 |  _. m5 G8 \' c/ K

  154. 9 M/ B! S# `6 p
  155. #define PALETTE_COUNT 256
    2 T- W" U* H4 ]1 i# B: V3 R* b6 W
  156. #define RBT_HEADER_SIZE 60; B* ]9 p. Z5 O9 u* J; [9 A3 E
  157. #define UNKNOWN_TABLE_SIZE (1024+512)1 X3 g! v; F" Y9 y2 U: W
  158. #define SUBTITLE_THRESHOLD 0x70
    ' H# u; r: }( e7 Z% c  m( a2 a4 N* ]
  159. #define MILLISECONDS_PER_FRAME 100( C9 `  `$ b1 I" _& Q) z
  160. $ e& ?$ e/ b* m
  161. /* VLC table */
    0 o- h5 [4 H4 q# L# k4 F$ z1 V) @
  162. #define VLC_SIZE 4  j' z# }9 E! R3 P
  163. static struct* W/ v8 {) y0 Y; x) w' S
  164. {5 w2 ?. J; {: }7 o
  165.     int count;$ M- @! i: V% s: `/ F0 T: V
  166.     int value;5 `  b- g5 y& t9 Q8 d
  167. } lzs_vlc_table[] =& w" p1 R5 b5 q4 I0 S$ p" Y3 p# h
  168. {5 ~- B" s( G0 ]' j# l
  169.     /* code length = 2 bits; value = 2 */
    / n  K+ E7 [! p) S' d/ }' Z
  170.     /* 0000 */ { 2, 2 },+ f$ v8 c1 [: v7 x( T; E
  171.     /* 0001 */ { 2, 2 },
    ( X# N  J1 q: [9 @& u8 w/ r8 C: M6 _
  172.     /* 0010 */ { 2, 2 },
    1 B; b4 Q9 W, [6 y* B4 z
  173.     /* 0011 */ { 2, 2 },0 z, M. ^( I- Q3 ]" @: Z
  174. 8 F* }9 e: m0 ~* D' v1 F" J6 i
  175.     /* code length = 2 bits; value = 3 */8 g2 Q  C5 |" F2 j) ^7 K: c3 @8 k
  176.     /* 0100 */ { 2, 3 },
    . C& w9 W5 z5 V  @! E
  177.     /* 0101 */ { 2, 3 },3 x+ n  h7 {7 x$ q
  178.     /* 0110 */ { 2, 3 },8 f$ S- S: L8 e9 b
  179.     /* 0111 */ { 2, 3 },
    4 v# h6 b* C8 a7 K

  180. ; a8 a7 q) p; g9 ?
  181.     /* code length = 2 bits; value = 4 */
    : h  s: a9 u4 x. ^9 P2 z
  182.     /* 1000 */ { 2, 4 },' M9 D) }% h' V" `) n
  183.     /* 1001 */ { 2, 4 },. W. R; d% ]0 I/ Q7 }. {/ ~5 w4 [
  184.     /* 1010 */ { 2, 4 },+ I0 U; t7 M0 _* C" q
  185.     /* 1011 */ { 2, 4 },5 i7 V4 T) Y5 X2 {7 y
  186. , {" i' C+ T2 ]+ Y1 _: ~+ m
  187.     /* code length = 4 bits; value = 5 */5 d! {! \* s2 E; c( {
  188.     /* 1100 */ { 4, 5 },) n; m) M2 T- F, {# e, w. V
  189. 4 I- Z, |- w) n7 m# [1 H
  190.     /* code length = 4 bits; value = 6 */
    , ]" J# G; u! w, N0 ^& C
  191.     /* 1101 */ { 4, 6 },: \5 v0 Y- N' w" G4 Y0 x7 C7 z

  192. 2 {: A  S; h: W7 A  Q3 Q
  193.     /* code length = 4 bits; value = 7 */5 k( y# j- k: l  c1 `) V  p
  194.     /* 1110 */ { 4, 7 },
    8 H# @+ T% f5 T: {

  195. ; ~9 W' p  f4 {' h5 d7 \
  196.     /* special case */
    ; w, x0 m5 F6 M& P  Y8 m; I
  197.     /* 1111 */ { 4, 8 }9 b' a" o! P5 G' [- s
  198. };# }# Q! c7 E+ ]4 I8 `4 X

  199.   Q# N+ L# s, u& S$ F2 S! ?( P6 y
  200. typedef struct
    7 L' _" m+ S3 {' T/ {6 a
  201. {
    9 H! H% ~& M3 A1 e* A0 Y0 g+ o
  202.     int version;$ H8 H$ `  b' [: V
  203.     int width;- P) @9 P0 }3 H. A
  204.     int height;" H( S5 w! z# q7 M% Z" p
  205.     int frame_count;# W% z; a2 G+ I" N
  206.     int audio_chunk_size;: A! I/ @5 z4 V
  207.     uint8_t palette[PALETTE_COUNT * 3];/ H3 x6 H4 d5 v: t
  208.     off_t video_frame_size_table_offset;
    3 H9 P/ g: ]7 U0 U- m) ^2 v
  209.     uint8_t *video_frame_size_table;3 j  e" u, ?. n3 u& J
  210.     off_t frame_size_table_offset;' O/ }0 b* g2 |- ]% K
  211.     uint8_t *frame_size_table;
    7 m4 H2 p! |  l( e$ X
  212.     uint8_t *frame_load_buffer;
    5 V& x! T/ I2 J2 F
  213.     int dump_frames;3 D4 s: E+ ]9 P& I4 X

  214. 1 W, _0 n) i: o+ o) S
  215.     /* subtitle library */" ~7 C& ]1 t' K9 ~5 F+ H$ [! z& Q
  216.     ASS_Library *ass_lib;( ^; H/ P7 w* W) ?, i) W
  217.     ASS_Renderer *ass_renderer;$ u$ G( a. D1 y3 K1 S
  218.     ASS_Track *ass_track;
    ! d" G; F+ J: v+ z: ]1 o+ d/ V6 _
  219. } rbt_dec_context;
    " g3 z9 _5 W1 Y1 ]. Q

  220. " B; x' M7 W" M
  221. static void dump_pnm_file(char *filename, rbt_dec_context *rbt,: ^6 N" w/ U3 Z: d
  222.     uint8_t *image, int width, int height)
    # D' U0 B& r4 G) A2 K& w, d& I. f. s: c
  223. {
    + q0 s& r/ i3 R: ^9 h' v9 ?9 T1 g
  224.     FILE *outfile;
    ; ]/ l  ^& x7 O; l# R3 \7 ?
  225.     uint8_t bytes[3];
    / @" c, z3 {  g( T, w
  226.     int p;
    8 y  y* @6 [1 M4 D4 F# U- C) Y$ |
  227.     uint8_t pixel;
    " O' H) G$ A! T! m; W
  228. : i4 I8 p, j% F7 y9 _
  229.     outfile = fopen(filename, "wb");
    5 I  E- H: e/ [; c4 e7 \0 t6 u
  230.     fprintf(outfile, "P6\n%d %d\n255\n", width, height);
    8 e' C% \3 I+ b7 X, g. _
  231.     for (p = 0; p < width * height; p++)% w7 P8 n2 C" q2 ]; a2 z& }8 [+ z
  232.     {
    ' f9 l8 p7 {- ~5 L# e6 w
  233.         pixel = image[p];
    1 V: U% ?# q; }3 c  H
  234.         bytes[0] = rbt->palette[pixel*3+0];
    ) r' Q3 U7 _% g/ A
  235.         bytes[1] = rbt->palette[pixel*3+1];
    / C/ C  J! b: `# O( g6 A% Y
  236.         bytes[2] = rbt->palette[pixel*3+2];: n- P4 n7 o: c  W
  237.         fwrite(bytes, 3, 1, outfile);
    $ F9 V2 U$ V7 F( _+ `( G& U7 k
  238.     }/ Y/ \7 n" y" q2 w# c$ g+ A7 N
  239.     fclose(outfile);. I  B- _9 t& f' E  Z6 Z
  240. }/ b6 W* J$ E1 O# T5 j2 U9 l
  241. 8 d" S( a: A! S  }
  242. static int load_and_copy_rbt_header(rbt_dec_context *rbt, FILE *inrbt_file, FILE *outrbt_file)9 D2 F: C( a6 A1 w; p, s/ q$ A6 j
  243. {
    , l+ F0 r8 K/ p
  244.     uint8_t header[RBT_HEADER_SIZE];
    . y1 F. @- H8 [6 l1 t# E* p
  245.     int palette_data_size;
    - U4 {2 f- D  b' r8 P# l4 p; k
  246.     uint8_t *palette_chunk;
    3 l- Z2 k; }& I. i: ^
  247.     int unknown_chunk_size;$ m) W" U! L: O7 h1 r' k5 [
  248.     uint8_t *unknown_chunk;
    ' H' x, [/ n, w* p$ o$ \8 }8 ^" M
  249.     uint8_t unknown_table[UNKNOWN_TABLE_SIZE];
    ; x" b4 n1 C9 \
  250.     off_t padding_size;
    / ?% a( k( n, y( y8 ]! @& @! m& z
  251.     uint8_t *padding;- a* g2 [4 t) A% _
  252.     int i;: U1 K" q7 K) u
  253.     int frame_size;
    : Q) V+ p4 K/ s% [) O% ~. y
  254.     int max_frame_size;
    . X" m$ b1 N. J! c
  255.     int first_palette_index;5 F" C7 H6 t$ @! |
  256.     int palette_count;4 z$ D' p- p/ `' y/ H
  257.     int palette_type;
    0 X, V6 _- F* ^* o1 g4 \9 k7 J6 Z
  258.     int palette_index;6 N0 H" U/ w2 J, F+ T& G

  259. 1 Q7 X+ e0 I5 a7 q/ a: a4 G7 V
  260.     fseek(inrbt_file, 0, SEEK_SET);
      b3 i4 u5 M& w% |' K& U
  261.     fseek(outrbt_file, 0, SEEK_SET);
    # v3 F1 i, y! V3 K
  262. ' p1 {! g0 ?" o
  263.     /* load the header */
    % M9 f: t9 o/ [1 [! J6 d1 }) \
  264.     if (fread(header, RBT_HEADER_SIZE, 1, inrbt_file) != 1)6 j( o& d0 g  s) \
  265.     {: c+ m3 V( y. h# D- F. V
  266.         printf("problem reading initial RBT header\n");- [1 M% W% Z) z: d7 i
  267.         return 0;& v5 z; i6 R8 \5 I, ]; K
  268.     }2 N+ Q, f# {3 x. f- A& j  {5 B6 X

  269. / D7 ]; A- F6 g1 \; ^' w; B1 V) @) S
  270.     /* copy header to the output */
    6 b& d1 T( V( a+ i
  271.     if (fwrite(header, RBT_HEADER_SIZE, 1, outrbt_file) != 1)
    ; i' t1 Y/ _) G5 e2 ?9 ]6 D
  272.     {+ Q+ n. }: M( L3 c3 h  h/ E
  273.         printf("problem writing initial RBT header\n");" J# N6 _. O0 D5 Y- O3 B
  274.         return 0;
    - [* h! ?! G/ ]7 B: [% _* o
  275.     }3 x4 A1 F( @7 w3 f5 y2 @" O
  276. 8 U. R* P% u1 k% b' K/ I" e
  277.     rbt->version = LE_16(&header[6]);
    , t% U3 p/ U, Q4 |
  278.     rbt->audio_chunk_size = LE_16(&header[8]);! z) _% @; _; k3 ]% N0 m( B/ N) G9 d
  279.     rbt->frame_count = LE_16(&header[14]);
      Y9 q; T5 [1 S! R/ U5 x5 L+ f$ o0 Z

  280. 2 h: ]$ I( K5 X+ ]* q; E
  281.     /* transfer the unknown data, if it's there */4 K' L0 P0 F+ K" ]
  282.     unknown_chunk_size = LE_16(&header[18]);: U$ k; J* d" {
  283.     if (unknown_chunk_size > 0)! J, c8 I' I3 _
  284.     {: P' N, p2 e8 M5 K
  285.         unknown_chunk = malloc(unknown_chunk_size);
    ; s* i, g1 @0 k& t
  286.         if (fread(unknown_chunk, unknown_chunk_size, 1, inrbt_file) != 1)
    6 T5 m! X) T+ x8 A. j# m& T! I! a5 `
  287.         {
    6 F" }  C# ]6 [% @7 x
  288.             printf("problem reading unknown data\n");5 Z! N% g# c2 c2 C
  289.             return 0;
    ( t4 _2 y5 [: g/ z: q* v
  290.         }5 C8 s- |: l' s
  291.         if (fwrite(unknown_chunk, unknown_chunk_size, 1, outrbt_file) != 1)
    / E) q5 F. C8 V7 x7 J
  292.         {' q* z# I1 D4 A, _- u$ o
  293.             printf("problem writing unknown data\n");! g: {) I" M9 {9 V' E
  294.             return 0;
    * e+ m7 L  K+ C- ]" U* a
  295.         }0 S1 ^/ o8 S" z( ~5 i* T7 `- z5 b
  296.         free(unknown_chunk);
    $ d% q' m1 M# d9 @
  297.     }9 ~* X9 D$ `& N, m. E

  298. 7 [; a6 ]6 C* l! E: ^% {1 i
  299.     /* transfer the palette chunk */
    & x% v: i) W" }; q
  300.     palette_data_size = LE_16(&header[16]);9 v0 P( W5 [, z. G
  301.     palette_chunk = malloc(palette_data_size);. P, S+ J7 z7 A2 V$ U; Q
  302.     if (fread(palette_chunk, palette_data_size, 1, inrbt_file) != 1)
    3 {; V5 Z/ B- Q% _
  303.     {
    / ?' ?% D' b7 E0 ?
  304.         printf("problem reading palette\n");" F( V0 D# r% h4 K5 w$ s2 N
  305.         return 0;2 q" p" \+ g8 y8 M6 D4 o; Q
  306.     }# c  \$ X1 K& I) s8 U0 _
  307.     if (fwrite(palette_chunk, palette_data_size, 1, outrbt_file) != 1)
    3 b  a; R+ @, L  _6 }( F
  308.     {
    8 M' M# ]! L$ c* `9 }' N
  309.         printf("problem writing palette\n");
    ' Z" R8 r" y1 J1 E5 q/ I2 r- z4 {# G
  310.         return 0;
    2 ^4 V2 x7 i! ~6 i! s2 K
  311.     }8 s& S: [. d5 S
  312.     /* load the palette into the internal context */
    0 B+ r6 ?4 ^5 a! T) @
  313.     memset(rbt->palette, 0, PALETTE_COUNT * 3);
    4 s; H5 x  u. a1 }3 z# F
  314.     first_palette_index = palette_chunk[25];9 o" ^% G  s, a$ X4 x
  315.     palette_count = LE_16(&palette_chunk[29]);
    6 f9 o- J% X" X% L; G: ]& X& B
  316.     palette_type = palette_chunk[32];
    " g( f( n  O4 R' {& p
  317.     palette_index = (palette_type == 0) ? 38 : 37;3 o! f( ?3 D; ?6 d& X2 J
  318.     for (i = first_palette_index; i < first_palette_index + palette_count; i++)
    - c2 p6 b' `+ g% @# x! V! o
  319.     {
    " _# s8 m) x+ ~- k& J
  320.         rbt->palette[i*3+0] = palette_chunk[palette_index++];
    " u9 M( F3 \0 c' }* [% F2 n
  321.         rbt->palette[i*3+1] = palette_chunk[palette_index++];$ i% O2 ~  n5 e2 v/ H
  322.         rbt->palette[i*3+2] = palette_chunk[palette_index++];# t+ X0 y) `( I( T- }
  323.     }
    # C2 X% C  H  l. s; B8 Z
  324.     free(palette_chunk);$ {& A1 _# [4 t5 b: R. H! I4 [
  325.   F' N' n9 U: L4 D9 X2 @! M
  326.     /* copy the video frame size table (2 bytes per frame), as a placeholder */
    % @; U; T5 |9 P) y& x. @
  327.     rbt->video_frame_size_table = malloc(rbt->frame_count * sizeof(uint16_t));! k) H# v- P" G. Y
  328.     if (fread(rbt->video_frame_size_table, rbt->frame_count * sizeof(uint16_t), 1, inrbt_file) != 1)
    ; c$ ?3 ~5 h, n
  329.     {# m7 }7 T5 N& }' M; E% T
  330.         printf("problem reading frame table\n");6 N1 J. y6 q+ [" @
  331.         return 0;# n$ U0 r( ]6 G3 g& v- }5 U  C
  332.     }! ]3 S$ ^, o5 q* S4 D3 x
  333.     rbt->video_frame_size_table_offset = ftell(outrbt_file);
    ; p3 J9 {+ u' C/ ?
  334.     if (fwrite(rbt->video_frame_size_table, rbt->frame_count * sizeof(uint16_t), 1, outrbt_file) != 1)% _( O* ^2 G) I( r* f
  335.     {
    : p" c. I& U; u6 q: A
  336.         printf("problem writing frame table\n");
    # ~' q) b* q* c! m- [
  337.         return 0;& Y9 m3 J" Q- g" Z# n5 s2 E
  338.     }. b" u- q$ X5 P% o& e
  339. 4 u# a4 H, D- [( f
  340.     /* copy the frame size table (2 bytes per frame), as a placeholder */
    ; J5 d% R# O" R/ ~% R; m, ^
  341.     rbt->frame_size_table = malloc(rbt->frame_count * sizeof(uint16_t));
    # b4 T- M5 T- A. q
  342.     if (fread(rbt->frame_size_table, rbt->frame_count * sizeof(uint16_t), 1, inrbt_file) != 1)
    ) C3 C% h# _" e; p# K8 A
  343.     {
    : I2 M; K- s) X8 Q
  344.         printf("problem reading frame table\n");' h2 u5 z; y1 \, o; q$ W6 {
  345.         return 0;
    - f! m7 M! m' T# x0 N: N* \- A
  346.     }# e: u0 s" P. d/ @
  347.     rbt->frame_size_table_offset = ftell(outrbt_file);
    1 d  R6 l8 J/ |
  348.     if (fwrite(rbt->frame_size_table, rbt->frame_count * sizeof(uint16_t), 1, outrbt_file) != 1)
    : v8 I+ e% h" ?& }
  349.     {
    ' L3 A4 h2 L  j6 t* G6 Z6 ?
  350.         printf("problem writing frame table\n");! W6 u2 l0 r: Z$ E  g: s
  351.         return 0;/ p/ ]1 Z( `4 v( g2 R! J1 h0 X
  352.     }
    * @# H% t5 s& K4 r9 ~' o
  353. : @( E/ a4 G, h: E' h% n$ m" B
  354.     /* find the max frame size */
    9 s* {8 @6 ]9 H, A8 p
  355.     max_frame_size = 0;
    + x( Q- e) Q5 k: |5 l0 w
  356.     for (i = 0; i < rbt->frame_count; i++)! v; K0 M; X0 Q/ `% ~7 A5 ?
  357.     {  g7 a5 r* I) T6 [3 E
  358.         frame_size = LE_16(&rbt->frame_size_table[i*2]);8 J  i4 t  r7 L# B2 X
  359.         if (frame_size > max_frame_size)
    * s) ?3 e# f) M/ F1 F
  360.             max_frame_size = frame_size;
    / X4 o. o9 q% l( j5 C" ]
  361.     }& l0 K$ ^5 F& V
  362.     rbt->frame_load_buffer = malloc(max_frame_size);
    " R: _' t; ]" L' |6 H/ `; }  D3 S

  363. 7 [! A+ P' P% X- b* ?3 a  ^$ Z' O
  364.     /* transfer the unknown table(s) */6 F; m: U) ?$ L6 {- K8 `
  365.     if (fread(unknown_table, UNKNOWN_TABLE_SIZE, 1, inrbt_file) != 1)
    3 _/ u* f; ~' e3 P0 T, {, E
  366.     {" Y. q4 h* O4 N" M  |8 W5 L  H  g
  367.         printf("problem reading unknown table\n");
    0 z7 {' K& ~) N' y
  368.         return 0;
    . T1 }' x- i8 |0 R6 a
  369.     }
    - g, z- @/ F  M3 n' d  \
  370.     if (fwrite(unknown_table, UNKNOWN_TABLE_SIZE, 1, outrbt_file) != 1)
    , s9 n- L5 r0 R- c: `. @& h5 k
  371.     {
    ) G! {5 w( O5 }( L; ~9 t
  372.         printf("problem writing unknown table\n");
    9 S0 t$ J9 ^6 W1 t  k0 F
  373.         return 0;& A3 Y7 f. Q/ z# v  O! T1 H1 [! k1 U
  374.     }
    0 q# h8 T9 W8 H% ~

  375.   K7 h# r5 X8 F
  376.     /* copy over padding */# X- d8 k  D, c- {
  377.     padding_size = 0x800 - (ftell(inrbt_file) & 0x7FF);
    " r  Z* t! b% Y- R
  378.     if (padding_size)2 P( a! C0 @9 a
  379.     {
    2 \; _' q+ B3 P+ J6 e
  380.         padding = malloc(padding_size);
    ' O1 n; c+ T3 M# I
  381.         if (fread(padding, padding_size, 1, inrbt_file) != 1)
    ! u+ B" V  |5 |2 s
  382.         {5 u& g5 [) e) N7 [
  383.             printf("problem reading padding\n");  }3 |: ~. ~5 @% `  N
  384.             return 0;& J4 B* h8 Y* L* c  f" Z
  385.         }
      \6 Q& }, l( a6 W: y, A
  386.         if (fwrite(padding, padding_size, 1, outrbt_file) != 1)
    * H" ?& }& T" b1 j, l3 L6 {5 [
  387.         {
    5 h& j( ?) Z+ y# q9 f! H9 q
  388.             printf("problem writing padding\n");
    1 r/ p+ a% Y" t/ \1 a/ \
  389.             return 0;  K! Q& B3 n# Y$ M" l* b* W
  390.         }: Q. t, n; c' J8 H  y* I* X
  391.         free(padding);
    : C% i7 }% ?; ^$ z' \
  392.     }
    : h2 O/ K+ _' H7 ?& I! o* E3 U7 e
  393. 7 d9 f, v+ S- b( S9 V8 |; Q! R
  394.     return 1;% B( e, b# _% a( c! C, t) I  N; k! l! S
  395. }
      h4 j/ `( ?1 v+ u' ^

  396. . ^% y# |9 I, R
  397. static int get_lzs_back_ref_length(get_bits_context *gb)5 o6 [  T8 S* C
  398. {+ N. A% u: Q6 {
  399.     int vlc;
    0 ~1 O  T7 ?+ ^; Q' @* X! k: B$ s% y* B
  400.     int count;* @" a3 w6 @4 D6 E
  401.     int value;6 J9 u* _0 R% J3 d
  402. ' m* y: S" f& A7 m( t( _: l
  403.     vlc = view_bits(gb, VLC_SIZE);  n# e$ ]4 X# c, m+ f9 C3 [+ ~
  404.     count = lzs_vlc_table[vlc].count;
    . @! |- t: m# }! R' m9 l  ^
  405.     value = lzs_vlc_table[vlc].value;
    , H+ _7 H8 c7 q0 g
  406. 5 \) x" X& ^, H; p
  407.     read_bits(gb, count);0 Q" U; L3 A9 v! }# i" e: z. ~
  408.     if (value == 8)* W# s4 V% l5 p. b
  409.     {: h! T+ o% ^: E& B1 ]
  410.         do9 _. J  `6 _1 U8 H% d  b8 q
  411.         {" {+ D3 _) J# l* S' O% H
  412.             vlc = read_bits(gb, VLC_SIZE);
    % T( M* R. T& }2 w3 w( Q
  413.             value += vlc;. q! \1 L/ V$ ~+ [
  414.         }# r! J  j/ ~# z4 c& W
  415.         while (vlc == 0xF);
    " W- u' k+ Q/ S, q& j, g
  416.     }: j0 Q/ `  z( K, Y2 h

  417. ! \! |- ?3 K6 @* G
  418.     return value;, j3 r" a4 I3 @, U
  419. }
    ! V, q" V( t3 Q- T1 T& I! S  p/ a
  420. ( M1 W5 l8 h( I8 [" |) Y& d) y
  421. static void compress_window(put_bits_context *pb, uint8_t *full_window,
    7 C7 h( z( P7 X3 E7 r1 v
  422.     int full_window_stride,* N8 z" Y9 n; B: b9 F
  423.     int window_top, int window_bottom, int window_left, int window_right)! s% y) k; R! O! t- a6 b
  424. {1 V1 o/ L" B8 M8 U0 G: u% C7 ]
  425.     int last_pixel;
    + b* u7 {7 K1 w9 K
  426.     int run_size;
    1 Z2 P0 E4 @* `4 s$ |  F, W
  427.     int x;! m+ c7 s. t9 ?6 P/ f" Q) ]! C
  428.     int y;/ d0 o7 Z& G, x4 o' v5 `+ Z6 J
  429.     int start_index;
    % L, |! A. Q) P+ r, D
  430.     int end_index;9 Q0 e0 q7 Z! ]' `5 I
  431.     int encode_last_run;( j8 {3 ]# ?, Y9 A9 p

  432. ' D  o- ?& D7 T* e2 m* S2 v
  433.     last_pixel = full_window[0];) L6 V3 C3 E! v3 |. t2 M
  434.     run_size = 1;- H0 B5 i9 p) ?9 f+ ^, f
  435.     for (y = window_top; y <= window_bottom; y++)
    # ?' R; q- K, G% L; Q* ]7 |
  436.     {
    8 T+ R+ _1 w) T& A7 O
  437.         start_index = y * full_window_stride + window_left;
    & M. u% z- l& Z. K
  438.         if (y == window_top)( B/ N0 I* g' k1 [$ \5 {
  439.             start_index += 1;0 z/ C0 I% V8 s( u
  440.         end_index = y * full_window_stride + window_right;
    5 d; j; `" Q, G
  441.         if (y == window_bottom)
    ' o0 U8 V9 _# G% n! k7 J/ {! S
  442.             encode_last_run = 1;
      t: G; M5 D/ k" f3 B
  443.         else
    : c5 V; U$ j3 V) h  v
  444.             encode_last_run = 0;
    ! W4 y; m; a4 i7 L
  445.         for (x = start_index; x < end_index; x++)% k* f, h4 [& Y/ N
  446.         {
    % n9 w( D% H4 T6 {/ O+ H2 r- A# c. Q
  447.             if (!encode_last_run && full_window[x] == last_pixel). C" k/ h+ n8 l
  448.                 run_size++;
    % N8 V2 f( p# Q* v  P& O
  449.             else
    ( T2 e/ \* e' T1 H) W7 x
  450.             {
    + Y/ @; L+ p0 R6 e; c
  451.                 if (run_size == 1)
    ) E+ L5 r: E" X0 x2 @6 V
  452.                 {
    / D9 ]8 U4 ^# g* n! p; x0 D( l
  453.                     /* encode a 0 bit followed by raw pixel byte */
    : ]8 C6 p. N2 P4 ]: G# U. ^1 w, b
  454.                     put_bits(pb, 0, 1);
    ; Y/ A* I. x2 H! R$ o+ R
  455.                     put_bits(pb, last_pixel, 8);; P! K. |; e, v& c( M6 d! ^
  456.                 }6 I5 E6 F' ?0 c
  457.                 else if (run_size == 2)
    / e# {' O7 Q3 V4 v. D
  458.                 {7 P7 L7 s& R! j$ l+ i- \& l  k+ J
  459.                     /* encode a 0 bit followed by raw pixel byte */
    % [  p6 b* o7 e) V0 P
  460.                     put_bits(pb, 0, 1);
    & E% S5 j( e/ x. U
  461.                     put_bits(pb, last_pixel, 8);
    ! ~+ ?. ~2 [2 Y! Y$ \
  462.                     put_bits(pb, 0, 1);3 @2 x2 E  q+ p- u3 s7 N- h
  463.                     put_bits(pb, last_pixel, 8);9 O! [+ v; F1 E4 e
  464.                 }
    . M' ~& v* H- N3 ?& L
  465.                 else3 @2 H1 O9 A$ ?! ^; L
  466.                 {9 T5 k0 i% v8 M
  467.                     /* encode a 0 bit followed by raw pixel byte */& O4 S+ h- W: j# Z( X5 Q4 m4 m1 N5 a
  468.                     put_bits(pb, 0, 1);" s' X& R+ s* h% l  |0 v1 ]- f
  469.                     put_bits(pb, last_pixel, 8);
    , r) ]. Z1 z% P1 S* t9 s
  470.                     run_size--;3 \% C1 s: a9 r9 W& b0 x- y
  471.                     /* encode a run: a 1 bit, followed by a back reference
    - ^; c0 o  Q' f% K, K
  472.                      * offset (-1), followed by a length */
    3 h" |( O1 i- P! t1 T" o
  473.                     put_bits(pb, 1, 1);% i% x- n1 q" `, f
  474.                     put_bits(pb, 1, 1);  /* 1 = 7-bit offset */
    2 r% o% e: @# a$ g
  475.                     put_bits(pb, 1, 7);2 _2 o0 y2 J4 `9 X7 z$ x, a" E- ?
  476.                     if (run_size <= 4)( @, }  x) X7 T$ K. p. t0 ]
  477.                     {7 U) j5 M4 _/ H. [
  478.                         /* lengths 2, 3, and 4 are 2 bits */% B! s. X- @! K
  479.                         put_bits(pb, run_size - 2, 2);
    & T% O: g% r! T0 b2 ^0 g7 k0 v" A. O
  480.                     }: K: m3 v. |; L  ]& M
  481.                     else if (run_size <= 7)
    5 z& `: H, y7 l  f, v) ?
  482.                     {
    - S$ Q. [; D2 [1 _: u" M
  483.                         /* lengths 5, 6, and 7 are 4 bits */, o% {- \1 F& J2 G# w
  484.                         put_bits(pb, run_size + 7, 4);
    6 h3 C' q8 M* K/ S( a* h9 Y+ ^
  485.                     }
    9 R; x; y' s! Y9 N  {7 M
  486.                     else
    0 Y' S" J0 S) M0 j% A  F
  487.                     {1 z1 X& r! Z2 j# Y* a. E
  488.                         /* arbitrary length; start by encoding 0xF which
    ! Y3 _+ {9 U! O' v
  489.                          * stands in for an initial version of 8 */
    2 K# T$ ^% c9 w: r% y- I
  490.                         put_bits(pb, 0xF, 4);9 l) X% Z5 g9 L, x
  491.                         run_size -= 8;) m5 O; _9 [, J
  492. / R; m) R" n2 s5 U6 {' f
  493.                         /* encode blocks of 4 bits until run_size is 0 */
    7 o$ ~7 m- l) D$ O+ b- i
  494.                         while (run_size >= 0)  s5 E5 X8 I9 u# n7 }
  495.                         {
    8 G& k- N; h$ i2 W1 t
  496.                             if (run_size >= 15)  @4 v5 ]% D. K$ k! k; ^2 x$ }
  497.                             {4 B; N# H6 i$ n' C; Y
  498.                                 put_bits(pb, 0xF, 4);0 v# M. {: x" k5 F% `3 F
  499.                                 run_size -= 0xF;
    3 s, B2 m$ \$ _9 N+ c6 K9 K
  500.                             }! ~# r6 u4 ?: J. t( u
  501.                             else+ A3 {0 {3 x$ o; q; d7 ~
  502.                             {
    5 w+ q3 o! }4 U5 z+ ^  t  _
  503.                                 put_bits(pb, run_size, 4);2 \4 C6 I5 H- b4 J1 @
  504.                                 run_size = -1;1 X9 x% W4 R; J9 i
  505.                             }( c) `  R+ _, A, M4 W
  506.                         }
    ( W. }9 X% }0 N3 Q* `1 [3 N. C2 A
  507.                     }
    + o  n* P8 _6 X; x' x2 q) ^
  508.                 }
    ' E& o4 l2 G& y4 T

  509. 7 i' o( l1 v5 S9 ~+ F# u( p$ Q0 {
  510.                 last_pixel = full_window[x];
    + I. Q  [1 E% y0 U3 ^
  511.                 run_size = 1;# \$ S2 T5 s9 |1 W, c$ |' S
  512. ; {/ W9 }9 R; z' ?- A
  513.                 /* this single x iteration was only here to close the final run */
    ! T! p4 `/ F; U' Q5 C2 M
  514.                 if (y == window_bottom)
    3 {' \3 P5 X: F" ^+ M
  515.                     break;- W! C( t+ J4 L% }
  516.             }7 a. p& r2 o$ t0 B3 ]+ P
  517.         }
    ' O3 I; C# ~8 j
  518.     }! u  l' {9 [* c1 V. h% a9 L. X

  519. 6 w8 w/ H% n3 ^
  520.     /* close the bitstream by encoding a back reference with length 0 */
    8 V; \+ a% M) R4 Y3 M
  521.     put_bits(pb, 1, 1);  /* back reference run */
    : U+ y6 G$ @# V, ]
  522.     put_bits(pb, 1, 1);  /* 1 = 7-bit offset */: ~  d* ~0 n6 `& O& z1 z' b' M
  523.     put_bits(pb, 0, 7);  /* length 0 */' I% z- g/ G1 I  n) V, R3 f
  524. 1 D2 h, K; a. d  S" x
  525.     put_bits_flush(pb);2 p* V9 d9 q' ?  L) x( M9 M
  526. }# C9 F$ R. G3 ^( k! A1 @

  527. 3 A2 t) e+ n0 g
  528. /* compute Euclidean distance between an RGB color and the desired target */
    + r) `- J" c! U5 e! I7 I0 }
  529. static int compute_rgb_distance(int r1, int r2, int g1, int g2, int b1, int b2)( }. x+ H6 u; c7 ^: c- E
  530. {7 `, m% t$ o. z6 x9 x% I7 Q* w
  531.     return sqrt((r1 - r2) * (r1 - r2) +
    7 ?% p" h+ p" p! p* X* I9 L- U
  532.                 (g1 - g2) * (g1 - g2) +- w5 @' Y/ ^: Q' F
  533.                 (b1 - b2) * (b1 - b2));2 J# k8 Y$ Q0 r5 G+ n/ u. X) @; o2 Q
  534. }
    9 F0 ~1 K6 p5 A. O# ^% u
  535. ( t: ?' y4 `9 q5 X, ?) `
  536. static uint8_t find_nearest_color(rbt_dec_context *rbt, int r, int g, int b)
    , k, a$ }/ {2 }7 M/ e, P
  537. {
    , n* x" e% K8 e( q1 \4 r7 K* h& y
  538.     int i;9 E+ M  {8 y  {' ~7 K+ a3 H
  539.     int nearest_distance;
    1 d1 E# @$ d/ r8 S; Q: [- R, {0 A3 P
  540.     int distance;
    4 W# x$ \# [! [
  541.     int rp;7 p$ _+ Z) b5 @6 X, F" I
  542.     int gp;
    " f0 f/ X1 R0 t& B$ f/ @
  543.     int bp;$ `6 t6 \9 w! t3 V
  544.     uint8_t palette_index;
    6 r. d. m# y- n+ C+ a! N
  545. 4 w+ t$ l/ G: y8 y
  546.     nearest_distance = 999999999;( a% d8 {; n# N6 J- J9 z3 Y: H
  547.     palette_index = 0;
    " D( T+ u$ @/ t( D
  548.     for (i = 0; i < 256; i++)
    ! I- m. ]. |, e, n. [
  549.     {
    1 j/ v. |0 J2 _4 t
  550.         rp = rbt->palette[i * 3 + 0];# ~4 T) U& r! ]6 S% A1 ?
  551.         gp = rbt->palette[i * 3 + 1];
    ! t2 J8 `4 H$ @: _5 `
  552.         bp = rbt->palette[i * 3 + 2];
    . S4 |' ~( t9 B8 [
  553.         distance = compute_rgb_distance(r, rp, g, gp, b, bp);1 m, \  a  Z( f
  554.         if (distance < nearest_distance), L0 \$ }2 Y. @9 _
  555.         {
    3 b! p0 I* g9 C& Y( @: t
  556.             nearest_distance = distance;
    2 T* M; S" w1 y
  557.             palette_index = i;
    8 y6 i- ~6 b/ j" r" K
  558.         }* S7 |7 X3 E+ v# r  V( o+ v. {
  559.         /* can't get closer than 0; break early */
    % ?  J! a+ N3 L, Y: u( @! B; f; A
  560.         if (distance == 0)
    0 b6 V, B# t. J' W/ m/ {1 v0 t1 B
  561.             break;. o3 h3 E& N7 Y7 T
  562.     }$ D" J/ ~) B5 s- P  N6 C+ x
  563. / i! g1 W2 K; G0 K  S! X% r
  564.     return palette_index;
    # Q  u( t1 I. I- G
  565. }( N5 M; _9 f: _1 Q  ^7 A: y6 Y* G
  566. * G$ C0 }- X$ I) g7 b! R1 h: Y
  567. static void subtitle_frame(rbt_dec_context *rbt, uint8_t *frame,
    9 U+ z: v) ?6 r- ^* B; ~5 \9 J' G
  568.     int width, int height, int timestamp)2 r  P5 ^7 H9 c- v: Q) g
  569. {
    5 t( E" D: s& P
  570.     ASS_Image *subtitles;. o; s; C- D# d" E5 T8 P
  571.     int detect_change;- N( s. Y  ~% u; q2 d
  572.     uint8_t subtitle_pixel;
    * Z7 E$ R: G; e2 E3 n2 `' b
  573.     int x, y;' n" I+ I$ k" i3 r- v
  574.     uint8_t *frame_ptr;
    ( c8 _% N" U/ a6 ^) X' ~9 }
  575.     uint8_t *subtitle_ptr;
    * H, P: N6 t/ {' Z" j

  576. ; e4 z9 O6 k, q; Z( ]1 Q' h
  577.     /* ask library for the subtitle for this timestamp */& R7 D! B. R8 T& k5 v
  578.     subtitles = ass_render_frame(rbt->ass_renderer, rbt->ass_track,
    1 ]: h! |6 p5 Q; r! Z6 F
  579.         timestamp, &detect_change);
    2 n9 d! O' h$ o- \" `
  580. 5 h0 k8 D4 f# f
  581.     /* render the list of subtitles onto the decoded frame */# m5 P" |+ v4 A3 {" Q' [/ N# K- H
  582.     while (subtitles)9 T- C  y' z6 n9 Y' ~
  583.     {, Y3 n* @1 Y/ ?0 ^5 T/ B
  584.         /* palette components are only 6 bits, so shift an extra 24 W0 q; z- n% q% m2 T% t3 b, g6 Q: P0 N
  585.          * bits off each component */
    ( G) N, j, G0 L; ^7 h; X
  586.         subtitle_pixel = find_nearest_color(rbt,2 w9 H3 v0 w; v% g. _( J
  587.             (subtitles->color >> 10) & 0xFF,- @( b  q" w& b
  588.             (subtitles->color >> 18) & 0xFF,
    # `2 T) z) A5 O/ C" L8 j. U
  589.             (subtitles->color >> 26) & 0xFF);) I3 x: J9 r  m5 e
  590.         for (y = 0; y < subtitles->h; y++)
    " R0 a: X2 T$ l! t# I, c) q
  591.         {
    " u, O! g$ L5 h( [+ K5 Y
  592.             subtitle_ptr = &subtitles->bitmap[y * subtitles->stride];
    ! a7 e' o) ~4 o+ V
  593.             frame_ptr = &frame[(subtitles->dst_y + y) * width + subtitles->dst_x];) A( ^! n+ A. w6 `
  594.             for (x = 0; x < subtitles->w; x++, frame_ptr++, subtitle_ptr++)8 c1 ?) B  C1 n% s9 X) j
  595.             {; ?/ H7 j" h  T% n
  596.                 if (*subtitle_ptr >= SUBTITLE_THRESHOLD)$ u, [# e5 r" j5 g& ~; Q
  597.                     *frame_ptr = subtitle_pixel;1 v+ t# C" \1 m$ R3 n5 _
  598.             }8 j; _' T: U5 _! H
  599.         }
    ! R& R6 K+ s+ O; p7 [* h8 E
  600.         subtitles = subtitles->next;- H& c) l/ I7 ~3 n% m) ^/ D
  601.     }
    2 O7 C9 r6 J- \, A3 C4 o
  602. }4 B# o8 j7 u2 A; R; J! x
  603. ! \. v1 f$ ]' F* z- X! l9 p* V
  604. static int copy_frames(rbt_dec_context *rbt, FILE *inrbt_file, FILE *outrbt_file,
    * x" R0 y# |& b. u2 o
  605.     int origin_x, int origin_y, int window_width, int window_height)6 i7 b1 V7 O9 g6 I) U9 Y8 t1 r8 {
  606. {
    3 c) a. e  S! e% \$ |# b5 q
  607.     int i;
    : p% T9 r% f& J, ~/ H1 Q" c
  608.     int j;7 _) c. A4 e$ z5 }4 t
  609.     int scale;5 k5 ]5 W1 v: s9 h
  610.     int width;  a4 I2 @6 w: J- K
  611.     int height;
    1 h: W: U9 y( z+ H4 U5 {. W
  612.     int max_width;4 H: q2 b- z; |4 @& G" r
  613.     int max_height;
    0 _8 ]; S& d. d  F
  614.     int frame_x;" [' O3 ?% O( K8 T4 W' x1 q9 k+ [8 Q" k
  615.     int frame_y;$ ^9 P( X: ^' u  w
  616.     int fragment_count;
    7 n8 T0 Q. Q) X3 d
  617.     int decoded_size;
    % c/ V3 ^8 j" ?& `* V- _
  618.     uint8_t *decoded_frame;
    0 j. I3 D) ]1 `
  619.     int fragment;
    5 l# Y6 z3 d  a5 F& F* b, W
  620.     int fragment_compressed_size;
    2 z# j, k: m  @% c
  621.     int fragment_decompressed_size;2 K5 z1 s! K5 k, b
  622.     int compression_type;  P+ h3 z2 N+ z
  623.     int index;
      T5 b6 s/ {8 a
  624.     int out_index;
    , U8 D$ l' [* l
  625.     get_bits_context gb;1 e7 d; ~: o  Y  }: @
  626.     int frame_size;6 [: s' \: a6 `
  627.     int video_frame_size;0 K  N  u* R8 t; y$ B
  628.     int audio_frame_size;3 |) _" y% d! @1 B

  629. , N9 v+ X2 v  I4 s+ o$ z& `
  630.     int back_ref_offset_type;4 h1 U8 c7 r) m* C6 k+ S% W, ~
  631.     int back_ref_offset;/ {: ^5 t; z7 O0 O( E
  632.     int back_ref_length;+ a. b* I) l. G( x' o6 q% `' H
  633.     int back_ref_start;' P& s2 I  \" V" I" o8 Y
  634.     int back_ref_end;. Q1 K: H* E/ l
  635. 2 j* v3 H& c: F5 v
  636.     uint8_t *full_window;4 M1 ^% T; r" o6 T* O" V8 q% z
  637.     int full_window_size;; ~* P# G0 E. w9 I1 }
  638.     int y;0 p  N4 J) s1 z$ T" _
  639.     int window_top;8 m! X# Y: {3 g( S- O, c/ N
  640.     int window_bottom;
    5 l+ V+ r, o0 m. l6 Z; u
  641.     int window_left;# e# z0 N5 l9 V8 @! \6 s
  642.     int window_right;
    6 p5 ~% B1 s( M
  643.     int window_size;
    - {7 w: q8 p2 c8 J
  644. ' ^. ?9 y0 q& h* R7 O5 U, d# R
  645.     char filename[30];# p6 U$ F5 j# B' T

  646. ; y9 b7 X% K, j0 Q
  647.     put_bits_context *pb;
    # ~  x/ n: J8 G- U  g3 P# X: V5 I
  648. / f6 y/ L/ _  V* w3 e
  649.     full_window_size = window_width * window_height;; g4 C( e' C# o, x5 `: u0 A
  650.     full_window = malloc(full_window_size);
    ( d$ m( a" m" ^# K
  651.     pb = init_put_bits();4 n; D8 q$ D* I4 K: J

  652. 4 t) V4 w+ o4 M( }" @
  653.     max_width = 0;' U- I  \, P( `$ K! r6 q1 S* L
  654.     max_height = 0;. ~% g9 z8 V7 q. d% `0 F4 h
  655. ' E) m9 z6 [- u- q5 ^7 O6 s
  656.     for (i = 0; i < rbt->frame_count; i++)
    ; t1 y- ~2 `3 S% f3 P8 c
  657.     {" k# m, r7 u( N. T4 t
  658.         /* read the entire frame (includes audio and video) */
    ' U, R. N. N1 T! \, h' ~6 b( Z6 @
  659.         frame_size = LE_16(&rbt->frame_size_table[i*2]);
    0 T" Q7 J! ]. V# J0 v$ X# G- ]
  660.         video_frame_size = LE_16(&rbt->video_frame_size_table[i*2]);
    - t9 q: K* z' C/ Z3 @
  661.         audio_frame_size = frame_size - video_frame_size;
    ' M$ q" n( s% M3 N9 b
  662.         if (fread(rbt->frame_load_buffer, frame_size, 1, inrbt_file) != 1)5 P1 _' G  C" m3 x3 Q. R
  663.         {" D* w3 y( q, m$ b6 |% I- x+ R
  664.             printf("problem reading frame %d\n", i);( i; t' b6 Q7 J! v1 F1 P
  665.             return 0;: u. x! ~5 k  G
  666.         }3 ]+ v' `# i: B% Z( u4 u

  667. 9 s1 a- Y- A* t; c- b
  668.         scale = rbt->frame_load_buffer[3];- \8 k& c1 Y, P' N
  669.         width = LE_16(&rbt->frame_load_buffer[4]);
      Y" M6 B' r3 x+ Y
  670.         if (max_width < width), K, d  ^% T" v8 W
  671.             max_width = width;
    5 p$ I7 o0 N4 M6 e1 d' b
  672.         if (max_height < height)5 s9 N( r* _6 i) I/ @" G$ E5 v
  673.             max_height = height;6 @- s/ w2 @7 w1 j/ t5 v
  674.         height = LE_16(&rbt->frame_load_buffer[6]);' h3 {' \' Z0 g( K! o
  675.         frame_x = LE_16(&rbt->frame_load_buffer[12]);
    $ D  @+ i  g/ G/ w1 e
  676.         frame_y = LE_16(&rbt->frame_load_buffer[14]);
    7 P" d) y+ T# g4 J
  677.         fragment_count = LE_16(&rbt->frame_load_buffer[18]);
    2 y+ N' d( |6 `4 }6 g
  678.         decoded_size = width * height;' @* C: `- D+ i# g% U

  679. 1 G8 E: N% \2 ^* o5 y1 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);
    ; |; V1 G1 j" {( B
  681. , B( C9 m7 O9 z9 `
  682.         /* decode the frame */
    2 A3 E1 }; d. }3 J( {6 `4 i8 j  T* ]
  683.         decoded_frame = malloc(decoded_size);$ [+ o: l8 g' O  @1 T
  684.         index = 24;
    3 T; {9 f6 ?1 W/ b3 j0 F, ?
  685.         out_index = 0;* U) G8 ^$ T* S
  686.         for (fragment = 0; fragment < fragment_count; fragment++)
      L& i: V! [; N. `
  687.         {
    % i5 W8 |$ H0 D; g3 n( ^# S
  688.             fragment_compressed_size = LE_32(&rbt->frame_load_buffer[index]);2 f1 ~" j  w! m
  689.             index += 4;
    0 l3 m" u8 R3 B& E) B2 }  S/ @' H
  690.             fragment_decompressed_size = LE_32(&rbt->frame_load_buffer[index]);/ C  F  H5 t( {6 I+ ~' R+ Z+ g
  691.             index += 4;% h2 Z& q: k2 f. Y  [
  692.             compression_type = LE_16(&rbt->frame_load_buffer[index]);
    ; e' i3 i! |" y* W* V
  693.             index += 2;
    / G8 u# D. [' [/ y: T
  694.   ]6 P( e# U1 {" A$ r) L0 b; r
  695.             if (compression_type == 0)4 o6 W5 B" n6 I
  696.             {9 j* r3 K& o! F$ N/ Z3 B& k4 ~
  697.                 init_get_bits(&gb, &rbt->frame_load_buffer[index],& V8 T: t$ u9 e
  698.                     fragment_compressed_size);
    8 u8 i0 X$ G2 m! B8 K; ]4 O7 z: F, B

  699. , Y9 u3 w" l. W$ i- v4 W3 J
  700.                 while (out_index < fragment_decompressed_size)
      W; M( W0 n7 y& K
  701.                 {! Z  E3 |; L  l$ I
  702.                     if (read_bits(&gb, 1)). E. M6 b) H6 ?9 \
  703.                     {4 W- s" b2 d# P; r& X& o
  704.                         /* decode back reference offset type */
    ! j. t7 X2 ?5 ?7 P5 Q
  705.                         back_ref_offset_type = read_bits(&gb, 1);
    / u# b: e3 O7 J% X. e6 I

  706. 3 q$ G  n$ K/ a% s8 x6 c
  707.                         /* back reference offset is 7 or 11 bits */' |2 w( M. D: M; d; `6 ]* }
  708.                         back_ref_offset = read_bits(&gb,
    " a7 ~+ q8 s5 J9 z# q
  709.                             (back_ref_offset_type) ? 7 : 11);# w7 M* \/ s: A0 a

  710. # q/ c+ U/ y% ?8 S$ D$ C' Z: h
  711.                         /* get the length of the back reference */
    6 J0 _3 N, P2 `" Y" A
  712.                         back_ref_length = get_lzs_back_ref_length(&gb);
    & N) C" _3 A5 M) e
  713.                         back_ref_start = out_index - back_ref_offset;
    * r0 a7 J1 n: X- D" ]
  714.                         back_ref_end = back_ref_start + back_ref_length;0 `& X5 z! y& D+ a" y

  715. 9 I& G5 C0 ], e: K% t; k4 O
  716.                         /* copy the back reference, byte by byte */" \' ]( h  ^- ]' ]- ~. f
  717.                         for (j = back_ref_start; j < back_ref_end; j++)$ C1 S% M! o* w' i
  718.                             decoded_frame[out_index++] = decoded_frame[j];
    . T+ I4 k7 U7 E5 u* u
  719.                     }
    . ^0 F+ k: r+ i2 O9 p( A
  720.                     else8 Q2 z- r, b, d$ \% m$ ~
  721.                     {0 q4 A. U- Q7 E0 E8 x5 c
  722.                         /* read raw pixel byte */: X1 r6 b0 K+ ~; D- X( U1 l
  723.                         decoded_frame[out_index++] = read_bits(&gb, 8) & 0xFF;
    5 j7 j# H& a% n5 ?1 d/ I/ I0 M
  724.                     }
    , r2 h* z- L" M
  725.                 }
    9 A" `6 ?' ~  |2 ]
  726. % x5 U! C* H  }$ x' Z
  727.                 delete_get_bits(&gb);
    9 m4 K/ i8 {9 u, [
  728.             }; c  K9 ~/ h# }5 h3 I1 \. S
  729. & n1 D% ?6 p, f1 v/ u8 C* f$ c$ N
  730.             /* next fragment */
      y1 D& i* L& G% D% F, q
  731.             index += fragment_compressed_size;- f2 k, T, p1 _  ~2 ^7 o# n
  732.         }
    " N8 B: N" Q0 ^% ?# _

  733. 6 R; W, p% q5 t
  734.         if (rbt->dump_frames)
    : d# |+ ~/ L2 v' N- p# d# ?2 p
  735.         {
    # ^+ O. r2 B/ c( H; H; r7 y! s- S
  736.             /* dump the original frame */
    # _2 L. |+ \$ B& T4 z
  737.             sprintf(filename, "original-frame-%03d.pnm", i);
    7 i6 {1 {; `1 R" i  I
  738.             dump_pnm_file(filename, rbt, decoded_frame, width, height);
    : T6 T6 x: k5 U1 ?9 e. I- Y
  739.         }
    1 v4 s& z7 d  q; [. O) }: ^" N1 F

  740. 3 F: B* @8 A# R5 C' G/ X4 N
  741.         /* transfer the image onto the frame window */
    4 M" s: G0 ~. x! J+ ~
  742.         memset(full_window, 0xFF, full_window_size);1 Q& t% L/ \1 K' h
  743.         index = 0;
    $ n6 @, b8 a5 d5 g' {4 f
  744.         for (y = 0; y < height; y++)
      L+ z4 [9 r* h
  745.         {
    $ M/ j$ E) [8 @! f  }3 P/ m0 P3 D
  746.             out_index = window_width * (frame_y + y) + frame_x;
    " D9 }; s0 d- G9 I2 v; M
  747.             memcpy(&full_window[out_index], &decoded_frame[index], width);
    6 S+ b! \2 @% T* b5 X* r- |
  748.             index += width;
    3 V! H# _  N, H  m* L. h8 a
  749.         }
    $ Z. U- z; B. x
  750. & n& b/ B/ P6 L9 C
  751.         /* write the subtitle */# O. y- X# o$ G. v& U
  752.         subtitle_frame(rbt, full_window, window_width, window_height,- d# J: V& Q3 J- t, s7 P/ j% q
  753.             i * MILLISECONDS_PER_FRAME);: O- [, J; z1 @5 L! B) n

  754. 9 X4 F- y# s+ b; q# c
  755.         /* figure out the smallest change window */
    ( e+ I- W* J% B1 L: X) f
  756.         window_top = frame_y;3 V3 F2 A: S, g
  757.         window_bottom = window_height;, ~/ {" D/ \' ^
  758.         window_left = 0;3 L  V9 g/ j4 c9 \" w* a. H
  759.         window_right = window_width;# f$ V9 |2 g) _- C
  760.         window_size = (window_right - window_left) * (window_bottom - window_top);8 Z0 {. A- f' ]2 K3 o

  761. # Q9 Y& z8 `! d
  762.         /* compress the frame */9 o. B8 N# T! I7 s3 a" G! E4 S
  763.         reset_put_bits(pb);
    7 [' A8 ^' y/ r1 K
  764.         compress_window(pb, full_window, window_width, window_top,
    4 N7 J. l' g( x, a7 d  G
  765.             window_bottom, window_left, window_right);1 T8 z  [, B7 F8 G! w( l

  766. ; i% @1 o6 P8 X7 j+ Y: G
  767.         if (rbt->dump_frames)/ h) H2 `8 w1 a6 x" C- [% x& e
  768.         {7 |# n/ ^: K' f: Z2 ?
  769.             /* dump the frame plotted onto the full window prior to encoding,
    6 C- y) C8 k8 s! [" d2 D9 W- c& F: k
  770.              * with subtitle */3 N; [$ D0 j" s6 ?
  771.             sprintf(filename, "pre-encoding-frame-%03d.pnm", i);
    : V6 E7 |4 i8 z/ f$ K0 A
  772.             dump_pnm_file(filename, rbt, full_window, window_width, window_height);4 S" Q4 b6 ^5 c; {; ?7 ?
  773.         }) c8 i* Y& _: I- s0 o8 Z2 J( u2 d
  774. $ _% h, F. o, T; C% E# h
  775.         free(decoded_frame);
    - v( r! `' w( D4 Y* p5 v

  776. 4 N1 o% n! _/ v/ k; J
  777.         /* update the frame header */9 S" @  m8 K; Z* u2 ?, Y- a# B
  778.         /* width */, P1 i2 m0 y2 i4 v: Z
  779.         rbt->frame_load_buffer[4] = (window_right - window_left) & 0xFF;
    1 J0 ]$ G' _1 A
  780.         rbt->frame_load_buffer[5] = (window_right - window_left) >> 8;  e# [3 M2 {0 e# K
  781.         /* height */4 l! ?* l  w( i
  782.         rbt->frame_load_buffer[6] = (window_bottom - window_top) & 0xFF;
    1 X9 L7 w1 G4 h3 Z0 i
  783.         rbt->frame_load_buffer[7] = (window_bottom - window_top) >> 8;
    % G+ x5 ?' q4 H% j0 `1 A& ]1 c
  784.         /* origin X */
    ' i3 u8 q' a: V4 y
  785.         rbt->frame_load_buffer[12] = window_left & 0xFF;
    6 t  u% F* }2 P$ k( S
  786.         rbt->frame_load_buffer[13] = window_left >> 8;
    & t, a- O5 S! t" u9 a2 K) f
  787.         /* origin Y */
    / X6 b" d) R; w3 K! F- R9 ?# G
  788.         rbt->frame_load_buffer[14] = window_top & 0xFF;6 Q& Y1 u8 B8 y2 ]
  789.         rbt->frame_load_buffer[15] = window_top >> 8;" s& ?8 q! S! h/ @8 y- a2 y
  790.         /* fragment payload size */! ]( m: m0 f" j/ j) Q
  791.         rbt->frame_load_buffer[16] = (pb->byte_index + 10) & 0xFF;
    ' D1 B# F9 _) {$ ?- U) c: y& s
  792.         rbt->frame_load_buffer[17] = (pb->byte_index + 10) >> 8;
    . I# _2 v2 ]6 s% L* H$ r: f
  793.         /* fragment count (1) */
    ( I9 M) `  s. N6 p7 y
  794.         rbt->frame_load_buffer[18] = 1;$ Q4 m! {" M& n* r! J+ L6 g
  795.         rbt->frame_load_buffer[19] = 0;; ]/ Q. a( c/ _4 H8 i* J9 p7 a! J
  796. * ?& f/ f7 a, A5 e" f; q, j
  797.         /* update the fragment header */1 ^% e- w; O! Y0 l' T' ~- w
  798.         /* compressed size */
    4 f8 u' \+ f& _2 s" q
  799.         rbt->frame_load_buffer[24 + 0] = (pb->byte_index >>  0) & 0xFF;  h4 H% ~+ N5 t* k
  800.         rbt->frame_load_buffer[24 + 1] = (pb->byte_index >>  8) & 0xFF;
    9 q, M! }  x5 {+ O4 X
  801.         rbt->frame_load_buffer[24 + 2] = (pb->byte_index >> 16) & 0xFF;! }9 o, \  y4 g( T7 S* o$ d
  802.         rbt->frame_load_buffer[24 + 3] = (pb->byte_index >> 24) & 0xFF;
    ' O$ \4 f! H. E* h# j
  803.         /* decompressed size */
    " O" T% \0 u. ^& C
  804.         rbt->frame_load_buffer[24 + 4] = (window_size >>  0) & 0xFF;
    . }4 T  H+ h. b6 P( U! L
  805.         rbt->frame_load_buffer[24 + 5] = (window_size >>  8) & 0xFF;
    . v! z% A5 u) b
  806.         rbt->frame_load_buffer[24 + 6] = (window_size >> 16) & 0xFF;
    ; b( E* V  C; g5 ?7 {9 a
  807.         rbt->frame_load_buffer[24 + 7] = (window_size >> 24) & 0xFF;! _% T# I( Q5 a7 _; \) v- |4 O8 L7 i$ [
  808.         /* compression format 0 */
    # l" {0 y- F5 d5 l& k: r
  809.         rbt->frame_load_buffer[24 + 8] = 0;
    7 [9 d. c7 [4 {: |6 H
  810.         rbt->frame_load_buffer[24 + 9] = 0;
    $ _, B5 x0 a$ Q
  811. # N9 D3 k! {/ R
  812.         /* write the 24-byte frame header and the 10-byte fragment header */
    . u- j2 T: _' R+ h' P; h/ l* @% g
  813.         if (fwrite(rbt->frame_load_buffer, 24 + 10, 1, outrbt_file) != 1)8 _* Y0 z8 ~, m9 {9 w. J3 x
  814.         {
    4 v% a0 H. p* Q" X& a& f* B
  815.             printf("problem writing frame %d\n", i);
    * ?" ?; V/ e. _' X! S
  816.             return 0;
    . B( s3 I5 G6 o  F4 s0 L9 s
  817.         }
    # t: c% f2 n' K% a
  818. ! P2 [' L% u" p6 X! L" t  n3 {
  819.         /* write the new compressed frame data */9 h' e5 o# g2 H8 R% _  x* b7 p8 \
  820.         if (fwrite(pb->bytes, pb->byte_index, 1, outrbt_file) != 1)
    4 Q. h8 f7 T$ c/ e+ E: B
  821.         {! |" c/ T( |2 q) n4 D0 A( e
  822.             printf("problem writing frame %d\n", i);
    0 G5 G" W% e; S! E, b
  823.             return 0;6 z8 [0 u4 Z- w/ q; N
  824.         }7 h5 G, T  f& C5 {

  825. 8 G; c" |' H3 P6 `$ T
  826.         /* write the audio data */
    - h4 X* r- D8 G5 D2 x
  827.         if (fwrite(&rbt->frame_load_buffer[video_frame_size], frame_size - video_frame_size, 1, outrbt_file) != 1)2 |; m. D: A  J( e& i4 M& u0 }  w
  828.         {
    1 \* z. |4 f, I& R8 [/ `1 t8 s+ E
  829.             printf("problem writing frame %d\n", i);
    & U  W+ ^# ]/ J. k6 o1 O
  830.             return 0;2 @  ]3 x1 h. N- A* c9 a
  831.         }
    & Y8 _: O* t& l
  832. 9 k: z8 O. C' R
  833.         /* update the table entries *// D7 d) Y, I3 C4 A- R3 o
  834.         video_frame_size = pb->byte_index + 24 + 10;) Z% W0 Z9 X& b- ^
  835.         frame_size = video_frame_size + audio_frame_size;1 V" D0 O7 X9 p: @8 V6 X
  836.         rbt->frame_size_table[i*2+0] = frame_size & 0xFF;. P/ `* ^& c3 b$ R, k8 y/ u3 ~
  837.         rbt->frame_size_table[i*2+1] = frame_size >> 8;" N( f1 y3 @. m, L; u
  838.         rbt->video_frame_size_table[i*2+0] = video_frame_size & 0xFF;: M; R! J/ P9 I$ d6 U! Y. r, G6 }
  839.         rbt->video_frame_size_table[i*2+1] = video_frame_size >> 8;
    ' }" s4 i0 I% [
  840.     }; \  K3 u7 A& M
  841. ! G7 N* |6 Y9 u! P2 B! o* S" D# N
  842.     printf("maximum dimensions seen are %dx%d\n", max_width, max_height);
    , n2 E3 f5 U3 B

  843. ' }" J9 l9 D  R6 j$ Q" B, |( T
  844.     delete_put_bits(pb);& j3 U: i( U9 q5 _1 d3 F% B
  845.     free(full_window);
    % M$ x* L2 ^& A% V5 e7 i

  846. ' a$ P0 Y0 Q- ~/ @; C5 d
  847.     return 1;
    7 z  D+ R4 Z3 Q) o- n/ X+ Q; g
  848. }
    ! L9 U  N$ h# i& }4 y4 \. Y
  849. ( z0 |6 `. `$ E; k
  850. int main(int argc, char *argv[])
    ( j% q, b1 Y1 n
  851. {+ A- Y: \- w( R! z1 R+ M
  852.     char *subtitle_filename;& M/ D& G; a- f% W) V
  853.     FILE *subtitle_file;8 G' ]' M! A) H; P
  854.     char *inrbt_filename;$ ~3 z. G3 K  Q" ?6 Q
  855.     FILE *inrbt_file;
    6 T; K4 ^' x  v( Z
  856.     char *outrbt_filename;
    : }$ N  Q" }2 n! [; w5 R6 y
  857.     FILE *outrbt_file;
    2 I, O* O. d& ?
  858.     rbt_dec_context rbt;3 E3 I" w. t' d# {0 ~: q
  859.     int origin_x;; H6 u# b1 L$ H0 {7 W) ]9 t% w0 ^, T# b
  860.     int origin_y;
    3 X# ]) w# O1 f9 Z% d+ T
  861.     int window_width;4 ^6 Y; N% T4 Y" t: O; b$ w: W
  862.     int window_height;
    * E4 ^, e! e) P5 v5 J6 b3 C' |

  863. % m# C/ j: B& ^- h
  864.     /* testing the bit functions */
      P1 K* R* G" P* Y
  865. #if 05 a$ E' V; b) O
  866.     int i;  |2 p+ o" y1 p
  867.     uint8_t bytestream[] = { 0x55, 0xAA, 0x00, 0xAA, 0x55, 0x77, 0xFF, 0x1B, 0x70, 0x8F };
    ! q6 n3 F( K! \8 k
  868.     int bytestream_size = 10;2 P* J/ Q$ x( l- K# X
  869.     get_bits_context gb;
    : A2 @) z' r) B! g7 A
  870.     put_bits_context *pb;) d3 C2 i2 m  |" q
  871.     int bits;( `( I4 _/ A; r3 F/ f% y
  872. 9 l/ T! j$ V! j& T* {% L% _# z" t
  873.     init_get_bits(&gb, bytestream, bytestream_size);
    ) Z. t# a, x/ A4 B
  874.     pb = init_put_bits();" f- n0 I5 P4 o2 H6 k5 R

  875.   m& ^/ e! N$ S3 ]& c
  876.     for (i = 1; i <= 12; i++)) n8 ~6 q9 B- p# W/ F/ `
  877.     {
    8 Q  w- ]' H7 R+ O% Q
  878.         bits = view_bits(&gb, i);
    ' I/ F" v/ L. C9 u: F; e( z9 n3 k
  879.         printf("view %d bits: %d\n", i, bits);+ o: \2 L5 u8 D. q/ ^) Z# i
  880.         printf("read %d bits: %d\n", i, read_bits(&gb, i));
    3 E% [( j9 G, y$ @7 m! b
  881.         put_bits(pb, bits, i);
    & ~6 _7 v: E  _2 o
  882.     }( k; `* C$ K  Y  [, j! k1 q. `
  883.     put_bits_flush(pb);2 ]# v6 i+ @; ?  e* I% c
  884. , p/ T, q' U! B: e) w, ?; v4 C* I' r: [
  885.     printf("original bytestream:\n");2 H$ D. C. J4 z% a: g$ @
  886.     for (i = 0; i < bytestream_size; i++)
    $ l, ~3 [! `! g3 M0 m" l! \
  887.         printf(" %02X", bytestream[i]);
    4 g  L, Q1 q; `6 c5 N
  888.     printf("\nnewbytestream:\n");( q0 r/ R4 b, z; O1 f2 j1 V
  889.     for (i = 0; i < pb->byte_index; i++)5 j2 p+ h5 z! _- L9 t) }! g* f& Z. u
  890.         printf(" %02X", pb->bytes[i]);
    - \& V# t( n8 y& d% Q
  891.     printf("\n");
    6 f3 A" F: j0 S% H* T! ?9 j$ @* o& k
  892. / g0 J1 h7 c3 m/ [! @: m8 u
  893.     delete_get_bits(&gb);
    0 N$ l* s) W  g  n$ o
  894.     free(pb);; X* r0 K! E' Z- Z4 \) d) ^
  895. #endif, ]6 T; _, t6 K7 K' g

  896. 6 L+ N8 h4 P/ x6 J% V) m& ?) S  H! P
  897.     /* validate the number of arguments */
    & {8 B/ @5 X* s0 H
  898.     if (argc != 8 && argc != 9)6 z2 q/ D& o# q2 r& V" ]6 A" A' G9 v
  899.     {
    ! c. n  P7 w! y: S) \, I1 ]
  900.         printf("USAGE: subtitle-rbt <subtitles.ass> <in.rbt> <out.rbt> <origin X> <origin Y> <width> <height> [dump_frames]\n");: [1 |+ V& [. z3 L; ~
  901.         return 1;) t5 t+ G5 G: O' o' x9 ]# a" h
  902.     }1 H9 p+ q0 W4 t" O+ f
  903.     subtitle_filename = argv[1];
    " M5 u6 c6 y8 M9 O+ l& l
  904.     inrbt_filename = argv[2];
    5 z9 T0 e2 L8 ~6 q
  905.     outrbt_filename = argv[3];
    . I( U0 y' p, Q7 x. i1 a. `: ^: J
  906.     origin_x = atoi(argv[4]);6 w" `9 {# y  a$ L# O
  907.     origin_y = atoi(argv[5]);
    " Y/ n1 J! F! T/ O% M: u* L- Y2 d
  908.     window_width = atoi(argv[6]);
    * ~  P! v: E4 I. O# g
  909.     window_height = atoi(argv[7]);
    9 B  l! x+ C5 g+ `
  910.     rbt.dump_frames = 0;
    6 ^. t8 b% g% J8 U& C
  911.     if (argc == 9)
    6 p9 R7 m  B" Z) _6 n+ X2 U
  912.         rbt.dump_frames = 1;
    , ~6 x4 K2 O' @+ X

  913. " k0 x8 \4 K4 Z& e- _
  914.     /* verify that the specified input files are valid */% {: @) A8 U* U& _8 A
  915.     subtitle_file = fopen(subtitle_filename, "r");
      p( n& h0 _7 Y9 U
  916.     if (!subtitle_file)6 D0 ?% {  u  m7 M$ o
  917.     {
    % |2 k6 i; ^0 E9 y; ~
  918.         perror(subtitle_filename);
    - O, D$ _7 Z7 @5 u
  919.         return 1;: n# b% C$ ^+ ^3 Q) I
  920.     }+ p9 @. k3 l' P& A* w/ P
  921.     fclose(subtitle_file);8 v$ x: p# N3 t1 F2 r  ~3 c
  922.     inrbt_file = fopen(inrbt_filename, "rb");, e- \" Q- g7 G7 D) h
  923.     if (!inrbt_file)9 g# M2 m, p/ d1 I  @3 i" ]+ g
  924.     {
    ( Q/ O" `1 _+ T  ?
  925.         perror(inrbt_filename);' K' B5 R0 [5 t# h5 ^" v
  926.         return 1;
    4 J* ^! D' l6 i) Q$ _
  927.     }
    . ~% n- o2 ]) g7 h8 s* Y& \7 K6 b
  928. 9 v1 S+ I2 u) {8 D
  929.     /* initialize the subtitle support */* S) W2 E0 p7 d1 U, ]" j1 b: @
  930.     rbt.ass_lib = ass_library_init();& x- ], N( g7 p* @% c* J. ~; w
  931.     rbt.ass_renderer = ass_renderer_init(rbt.ass_lib);4 Z: g( t) W! A/ T3 f6 v4 u8 x; G
  932.     rbt.ass_track = ass_read_file(rbt.ass_lib, subtitle_filename, "UTF-8");8 ^, N9 j$ T4 p; E. \! V
  933.     ass_set_frame_size(rbt.ass_renderer, window_width, window_height);
    % y/ b; Q% k7 q1 F
  934.     ass_set_fonts(rbt.ass_renderer, NULL, NULL, 1, NULL, 1);; w3 V# a: C: L' H- t

  935. ! X& z' a* a6 {  F
  936.     /* open the output file */- W$ g9 A$ t2 }8 O, O# g
  937.     outrbt_file = fopen(outrbt_filename, "wb");* y3 y* D1 P$ z- s; \: B
  938.     if (!outrbt_file)- z: u0 y/ Q' Q2 ]( ?' O; S
  939.     {
    ( Q, C/ ?- U' \7 b& C
  940.         perror(outrbt_filename);
    % i4 ~0 t# `+ _: J
  941.         return 1;
    3 @8 J, `" M( O$ J; n
  942.     }
    & l# Q- G" x# o% F
  943. ! f, ]4 T/ Q9 ~  l6 ~
  944.     /* transfer header from input to output */* n3 k9 m$ G' A$ ~
  945.     if (!load_and_copy_rbt_header(&rbt, inrbt_file, outrbt_file))
    , s+ L: T0 X2 [
  946.         return 1;
    # N' [# j+ l/ G& }2 W9 ]1 Q
  947. + k* K9 ^# u" ^5 H  m* F# B7 c9 H
  948.     /* rewrite the frames */2 S: C+ Y+ u0 X- b
  949.     if (!copy_frames(&rbt, inrbt_file, outrbt_file, origin_x, origin_y,9 p; w$ v% ^( @  u+ G( ?
  950.         window_width, window_height))
    4 q! o( C% ~6 i3 |- ]8 C  N# ]' V
  951.         return 1;9 N4 N" j2 ~0 Q/ w( ^2 }

  952. + }( ^0 z' m0 P8 q8 G% e5 D
  953.     /* write the modified frame size tables back to the file */
    ; E0 p; N' c$ s: r
  954.     fseek(outrbt_file, rbt.video_frame_size_table_offset, SEEK_SET);
    - @$ n3 R3 [' X% E2 z# o+ b
  955.     fwrite(rbt.video_frame_size_table, rbt.frame_count * sizeof(uint16_t), 1, outrbt_file);: A3 V5 Y1 t& K; c/ u5 a+ \
  956.     fseek(outrbt_file, rbt.frame_size_table_offset, SEEK_SET);, a9 g- V+ }6 K5 {7 r6 r
  957.     fwrite(rbt.frame_size_table, rbt.frame_count * sizeof(uint16_t), 1, outrbt_file);
    ! h/ @6 G7 p( L- B/ P

  958. ( s. a2 G- O# E7 Q: W8 V+ m
  959.     /* finished with files */
    0 H# d( K5 O9 m% @, O
  960.     fclose(inrbt_file);2 B8 x& ~% Y1 l1 u9 q. Y
  961.     fclose(outrbt_file);
    0 J4 ?4 \, n; P" Q* i8 R

  962. . v0 I7 P; W% f' f! A( k1 I$ F
  963.     /* clean up subtitle library */
    1 m: {/ J' ?5 H, x
  964.     ass_free_track(rbt.ass_track);0 _; q5 q" S- x
  965.     ass_renderer_done(rbt.ass_renderer);5 U; C- {0 D& r- V: K8 E/ k# j
  966.     ass_library_done(rbt.ass_lib);6 b: @  ?2 C4 h5 @
  967. & [/ {% i" }2 z1 Z% m) Z
  968.     /* clean up */
    0 e$ l6 ^8 p2 K: g7 \
  969.     free(rbt.frame_load_buffer);
    8 B7 u3 u/ }3 a( f) s8 a( d
  970.     free(rbt.video_frame_size_table);
    8 p& w9 o/ m, d0 W! X% A$ Y. ?
  971.     free(rbt.frame_size_table);& F* m! N- w" W: |
  972. ( J* d) D/ l3 g  D
  973.     return 0;
    6 s" w  k. Z- i% ?. @
  974. }
复制代码
" j) Q0 c, {& G6 [
  X+ B7 I% I. X% m5 U* H/ }

- j- V/ h0 [) u; z' W* s, r9 Y1 ^
  H( r! ~5 z: z% Y+ G. z: i
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 很美好很美好 很差劲很差劲
回复

使用道具 举报

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

使用道具 举报

板凳
 楼主| 发表于 2009-11-19 11:38 | 只看该作者
引用第1楼soring123于2009-11-19 11:09发表的  :
" l& g, v9 S( X: s7 Y这游戏有字幕吗?
% m1 [5 s6 f' {, K8 Q# J
好像没有字幕,我说的是给视频外挂字幕方式的汉化。
& O, e5 K" h6 d1 |* k就像syberia2汉化版下面那行字一样。
回复 支持 反对

使用道具 举报

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

使用道具 举报

5#
 楼主| 发表于 2009-11-19 17:39 | 只看该作者
引用第3楼soring123于2009-11-19 17:07发表的  :
7 s3 S3 @, X6 J' J2 p4 u( x我记得是没字幕的 比较麻烦 都是视频的
3 }3 s5 l' y0 \3 w3 U0 @, h6 b9 T- I+ K; D
给视频外挂字幕方式汉化也许能行。
6 y8 }+ T. l# q5 o要结合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日,是全球华人共同的冒险解谜类游戏家园。我们致力于提供各类冒险游戏资讯供大家学习交流。本站所有资源均不用于商业用途。

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