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

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

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

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

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

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

本帖最后由 shane007 于 2021-1-2 13:56 编辑
; L+ e& ]1 R1 z2 a
% U6 [: f6 _$ v) d最近找到了一些和幽魂系列Phantasmagoria 有关的资料,4 a2 T6 W0 p! R; u4 q6 ^% {" m1 P
也许将来可以用于汉化。
$ r% A) D' F6 f. e5 f' n1 G8 K# G
; I$ [& [7 s( y2 {" F和日文版有关的信息* ~( I( Y& o( m
http://anthonylarme.tripod.com/phantas/phintgtp.html7 ?5 @! J" v! k6 U

  m4 c  R% s% ?8 z6 d相关工具' p! l& Y3 B8 O$ e& ?2 K
http://anthonylarme.tripod.com/phantas/phcheats.html
. v* U/ R7 r3 b' H# R. k-----------------------------------------------------------------------
9 D8 j' }- s% k7 ~. ]2012/1/2  更新
! z# G0 Y$ C. X  {) o1 o, e! w关于幽魂游戏的字幕) `3 l$ h8 E( m) r' [( k/ q
Phantasmagoria subtitles function discovered - ScummVM :: Forums- B7 h8 U1 z, Y. s6 j0 m; n5 O
2 t, q! Z) }. Q3 d* j1 ]
VMD文件
$ S$ c! X* C9 I5 D5 N1 }' Q, [Subtitling Sierra VMD Files | Breaking Eggs And Making Omelettes (multimedia.cx)VMD - MultimediaWiki
* l8 D1 f% A4 z( Y2 r" E5 R5 C0 V& N- z
字幕9 I  V& q7 n1 m3 m, I; i8 A: ]+ p. _
Subtitling Sierra RBT Files | Breaking Eggs And Making Omelettes (multimedia.cx)$ b; }0 _3 j2 N$ B6 I

! {, Y4 }4 o9 c3 c' \0 q, _' HFFmpeg/subtitle-rbt.c at feature/VMD_encoder · multimediamike/FFmpeg · GitHub
9 N* g( c- ?  h% |
  1. /*- l4 J; i; ]" ^( R
  2. * subtitle-rbt.c0 ^3 p" I9 |. m* D+ p/ V! U
  3. *  by Mike Melanson (mike -at- multimedia.cx)
    . U- l' S* q" Y+ s) ]: Z5 U
  4. *. x& L' g9 X4 F3 B" K4 U3 q6 B
  5. * build with this command:
    - H8 o8 f0 D1 K" y# f8 k
  6. *   gcc -g -Wall subtitle-rbt.c -o subtitle-rbt -lm -lass$ w0 r  o2 r$ [
  7. */) P$ G6 L3 U/ O0 G9 y; d

  8. . g4 a2 R1 [( C) P
  9. #include <inttypes.h>
    ! o; o, p6 a6 L- E' M- X0 G2 u
  10. #include <math.h>6 t6 Q$ F" \$ v8 g/ {" f
  11. #include <stdio.h>* U. j. a1 V; D) t$ _+ T
  12. #include <stdlib.h># s: z& W6 Q+ M, U7 a
  13. #include <string.h>+ Q. ]/ {7 i2 ]; \
  14. * D8 L- N) T/ e9 T
  15. #include <ass/ass.h>
    0 h( D/ {$ ]# C4 \2 k& e
  16. 3 A1 ~7 r6 E: {& s0 ^! h
  17. #define LE_16(x) ((((uint8_t*)(x))[1] <<  8) | ((uint8_t*)(x))[0])
    ! [; m- b* d$ X" P1 e) L" V

  18. 0 H; A1 [2 F) v( x/ S" p
  19. #define LE_32(x) (((uint32_t)(((uint8_t*)(x))[3]) << 24) |  \
    ; H9 a0 C6 D+ l
  20.                              (((uint8_t*)(x))[2]  << 16) |  \
    7 N8 W" H, R6 [: s! v
  21.                              (((uint8_t*)(x))[1]  <<  8) |  \! q0 K2 r8 C$ H5 \. G- J8 B
  22.                               ((uint8_t*)(x))[0])
    , W! W  S0 y3 X: F: r
  23. 7 _) y0 _3 r' \# C
  24. /*********************************************************************/
    ; Q' Y& o5 A7 K$ z8 J" R

  25. : G8 K7 i, d& _9 y' r1 T- r
  26. /* Bit reader stuff */
    : s  G( b: ]3 S5 t7 a+ w

  27. 0 @5 ]: d$ g  p
  28. typedef struct& ~: `* ~1 z: B
  29. {
    2 X# ~  c( p+ o+ B) ]
  30.     uint8_t *bytestream;
      o9 E% ~% |5 N
  31.     int bytestream_size;% a8 S) I/ R# w1 P% Z5 |, I! \
  32.     int index;
    4 ]) O: X' x6 }6 d  V0 I1 r" U' h
  33.     uint32_t bits;* B9 F/ F% o9 F! L, a# J8 O
  34.     int bits_in_buffer;
    5 l% [/ F9 ~# ^4 _: M! `3 x3 J' w
  35. } get_bits_context;) n2 }# A  E" L& j
  36. 4 X* |9 W4 ~# Z$ C& x
  37. static inline void reload_bits(get_bits_context *gb)) Q' I- K8 w7 S6 Q, \7 M" Q
  38. {
    * m  c4 y+ t) X& N& b6 S* p6 x" Z
  39.     while (gb->bits_in_buffer <= 24)7 n1 K, g2 d+ g- ^) S# X
  40.     {
    * y$ X( ?$ `4 {9 u- v2 Z
  41.         if (gb->index < gb->bytestream_size)& g# B( Z2 {( F7 u2 O# J( F
  42.             gb->bits |= (gb->bytestream[gb->index++] << (24 - gb->bits_in_buffer));* c9 `/ W4 x8 A/ d
  43.         gb->bits_in_buffer += 8;' X2 }( {8 Y, N4 u2 t
  44.     }
    1 v3 X7 @) r5 i; E" Z& X' }& q
  45. }
    7 _& t4 V; ?. r. [( p. p
  46. 3 H( n" {" i" ]1 K
  47. static void init_get_bits(get_bits_context *gb, uint8_t *bytestream, int size)
    8 M) l; `+ v# S+ _( c; a
  48. {* w/ e; n% j& [+ t
  49.     gb->bytestream = malloc(size);
    : U$ k8 u* p: o- j. C+ r
  50.     memcpy(gb->bytestream, bytestream, size);
    3 o& j/ t) g& E8 J; ?9 z( d0 T
  51.     gb->bytestream_size = size;
      m8 y" A. T7 h7 v. _2 H
  52.     gb->index = 0;
    6 F; i$ n2 u' m  ~. n# N
  53.     gb->bits = 0;
    0 B0 A1 r; x/ r8 j9 Z6 h
  54.     gb->bits_in_buffer = 0;
    : ~& v% c6 }3 O" K  {
  55. & L1 E/ A3 f( i5 J6 p+ L
  56.     reload_bits(gb);+ ~0 J! s; H! |( ~
  57. }
    $ z& S+ D- z4 w  w5 E
  58. * l7 L7 u* g" ]
  59. /* read bits without consuming them from the stream */
    4 }* |  O& ^# u9 Z; D4 {
  60. static int view_bits(get_bits_context *gb, int count): B' o8 o8 l/ o- q" A  ?; Q
  61. {
    ; T) T' u9 X- N4 `5 k
  62.     if (count >= 24)7 y" w! w/ T" s& z4 Z* N. u3 X) D
  63.         return -1;
    # D4 D' G  Z; D$ u  @' h' u
  64.     if (gb->bits_in_buffer < count)8 ?8 d6 g4 Y5 D" z% L; D+ D$ Q
  65.         reload_bits(gb);9 \0 X6 [8 g7 [/ g1 \7 ?
  66.     return (gb->bits >> (32 - count));! F0 t/ k! V) |4 z( Q; Q9 w+ q
  67. }
    ' y  i5 |$ v+ q' L- @( |! ~

  68. / E* [8 i' b/ |0 e' M( b" m0 f0 q# Q
  69. /* read and consume bits from the stream */; y# W4 z2 Y: T# H7 C+ V
  70. static int read_bits(get_bits_context *gb, int count)
    4 U2 U1 j  O  M% g5 K+ r9 z" u% l
  71. {8 W2 n$ Y% \! u& H  y+ x  \: ?5 J
  72.     int value;
    4 E/ j: y0 q% P5 Z! K$ i" C

  73. ; g, c, s2 n. h0 o
  74.     if (count >= 24)
    - A7 d/ E! J; x: w
  75.         return -1;
    4 R# D3 m2 f  V% p! x4 L( e& e5 X# X' K6 T
  76. 5 H, l6 N+ ^8 @. o; y& x# e
  77.     value = view_bits(gb, count);1 @' k2 A4 I9 V$ d
  78.     gb->bits <<= count;9 X. @1 k0 @* N: Q- y
  79.     gb->bits_in_buffer -= count;) m& ]* J, A* B* s9 b2 h
  80. 2 S! U& ?8 M7 K4 e% Z' c
  81.     return value;
      h5 W1 `7 N! V8 G
  82. }
    ; N' C, @+ ~: e) ^
  83. : T6 K7 A. G3 F, L" |
  84. static void delete_get_bits(get_bits_context *gb)& S# u) i: s. A! F2 y0 H  z
  85. {
    1 L$ k! ]1 F& |# Q5 y1 A8 J
  86.     free(gb->bytestream);" `4 g# [( [; I
  87. }
    8 }0 A8 @: p7 `8 r

  88. 4 L; D: f- [# Z/ D& E) F+ t
  89. /*********************************************************************// M1 B7 h2 J% [; L+ a) T

  90. + u0 J0 u! n$ C: ]/ o* q
  91. /* Bit writer stuff */
    ' T2 P9 V5 O. J$ l+ ~! }" _( y2 {

  92.   f) e) C1 u- a. ^: p( {
  93. #define MAX_PUT_BITS_BYTES 63000  F1 @1 [! b" D6 F- l$ Z  O4 |; }
  94. typedef struct$ e: l) ?$ \2 s8 K+ r
  95. {
      m/ ^, T8 H/ I
  96.     uint8_t bytes[MAX_PUT_BITS_BYTES];' W6 G; ~! A0 B; a! j5 h
  97.     int byte_index;
    0 ?# g2 u5 W. o6 T' f$ @2 A
  98.     uint32_t bit_buffer;( I* Q# T3 \/ ^, V  X' E
  99.     int bits_buffered;
      T; U, d4 t8 N! V0 L
  100. } put_bits_context;
    5 z6 ]6 [; j6 u4 A" b6 [( c9 @5 e% P
  101. ) W0 s- `4 F/ D* T
  102. static void reset_put_bits(put_bits_context *pb)* z& g4 F* C( v: n  S
  103. {' B' _! E6 p2 ^6 V* L9 H& ~
  104.     memset(pb->bytes, 0, MAX_PUT_BITS_BYTES);
    ; j' M: j  K2 `, U
  105.     pb->byte_index = 0;2 Y9 y, v( A, ]" K4 @+ k. l
  106.     pb->bit_buffer = 0;
    : t) {' z7 J0 F: n% e
  107.     pb->bits_buffered = 0;5 q8 C! q7 {1 x9 A5 p% _& `! O8 R+ o
  108. }$ k2 y, L& @. y  m& c8 X
  109. $ _$ A. y, Z5 D: c: o
  110. static put_bits_context *init_put_bits()5 y4 d5 G: `8 {
  111. {
    1 ]9 |' q  z7 c( j8 e. x. k
  112.     put_bits_context *pb;  _) w+ r$ P- i: L
  113. $ R  B8 b; a2 w! y$ F1 w
  114.     pb = malloc(sizeof(put_bits_context));3 z* r7 N/ I  I$ o' w
  115.     reset_put_bits(pb);
    ! m+ c& c: u" k; I3 m9 V' [

  116. 2 G  ]/ ~" X* V1 t1 z
  117.     return pb;$ o' ?7 a% M+ _( o# ]
  118. }5 ]7 Q( @: k" Z5 {0 A# Q/ J$ E

  119. 1 D" L. z$ P, r5 H7 O# l9 j9 h% j
  120. static void put_bits(put_bits_context *pb, int bits, int count)% g9 J' F9 ~# ]0 G( U& o
  121. {
    . K. O# p1 T, c; E% U( a5 F! `
  122.     pb->bit_buffer <<= count;
    3 O+ {% r, @5 ^. g* o) s  C. V4 D' s1 H
  123.     pb->bit_buffer |= (bits & (~(0xFFFFFFFF << count)));. U; P' |) L: J; a0 ^. p+ y
  124.     pb->bits_buffered += count;  w$ r; l$ b, e+ F% h" Q4 C

  125. ( d: q& w) N) _
  126.     while (pb->bits_buffered >= 8)
    8 c# P, a2 }' K% d
  127.     {0 r7 g% R: f; L- p+ t2 l" v
  128.         pb->bytes[pb->byte_index++] = pb->bit_buffer >> (pb->bits_buffered - 8);0 }- }( B. }" e' O- G$ [
  129.         pb->bit_buffer &= (~(0xFFFFFFFF << (pb->bits_buffered - 8)));+ L0 ~( u$ D! p9 Y" X4 O) M; X7 N
  130.         pb->bits_buffered -= 8;
    - p- A* R- [2 g" p1 H
  131.     }
    9 ^; @/ T- ^0 I6 Q
  132. . m) Z- K$ d  o7 u: N* f9 ?& T
  133.     if (pb->byte_index >= MAX_PUT_BITS_BYTES)
    3 ~2 _# `9 Q; h4 O. f4 J: U: q2 b3 W
  134.     {
    ! ^) y% t+ v& ^, s2 g/ I; `! \
  135.         printf("HELP! Bit overflow\n");
    / I7 n8 u$ C: m
  136.         exit(1);
    6 x/ ~9 {- I7 W0 i, w: ~3 a
  137.     }
    6 K# ?6 q: v& z: y
  138. }/ I0 J! b' E8 n- E7 G
  139. % H& K3 S" V2 ]; I% j
  140. static void put_bits_flush(put_bits_context *pb): m  Y( z6 V; F- d6 ^
  141. {: {+ c0 I& u7 C9 |2 x& g; W
  142.     if (pb->bits_buffered > 0)
    ) z( T, t- B3 E
  143.         pb->bytes[pb->byte_index++] = pb->bit_buffer << (8 - pb->bits_buffered);
    ; }; r( l9 R) @0 n5 e- F* {9 X
  144. }
    ( W5 ]* z: `$ z9 z. v

  145. 7 Z% x2 M7 j( _6 b/ u
  146. static void delete_put_bits(put_bits_context *pb)
    : N& I+ e. g; y) V  q  ~2 z  u6 ?6 j% m
  147. {
    + O' s8 Y* j2 L$ V
  148.     free(pb->bytes);# S+ C/ @& T+ C7 ?) m' p
  149. }) |; p+ Y+ `! T9 e+ M- C+ c. k

  150. . [, I$ K( Y0 l7 [
  151. /*********************************************************************/
    % Y- E( t  e7 J

  152. / g  p7 ?# L- d, Y
  153. /* RBT functions */# r, X( L  s3 I* h* ~3 f, m. H

  154. 5 ^, k' ]! P* L7 h, O% c* B
  155. #define PALETTE_COUNT 256( o, A+ E0 A5 T
  156. #define RBT_HEADER_SIZE 60  d9 }( }, m/ q
  157. #define UNKNOWN_TABLE_SIZE (1024+512)
    4 u: x1 L, m# J* o, T
  158. #define SUBTITLE_THRESHOLD 0x706 K. ?+ `# R* N1 ^, k7 ^
  159. #define MILLISECONDS_PER_FRAME 100& ]8 E+ M1 V  |7 \: q0 y8 ^# A
  160. 8 Q8 |" u8 P+ n3 W3 o8 r8 S
  161. /* VLC table */
    . K' `4 L! c; m+ X' R) V  g
  162. #define VLC_SIZE 4
    ; B& g) }3 _% K- S1 g
  163. static struct
    9 l& |; X; E5 ]9 C4 j/ X
  164. {' ]; s0 G8 Q, |+ T( s
  165.     int count;7 a# I* r' U, e' _( D; p2 `
  166.     int value;7 s; H. {2 M# I# `3 [
  167. } lzs_vlc_table[] =: o; ?0 x  y8 L
  168. {& R6 d3 o3 e$ @) v, V1 G5 Y' q
  169.     /* code length = 2 bits; value = 2 */. E% i  x, ]" K% v; ~$ t
  170.     /* 0000 */ { 2, 2 },
    + y: z; |) i2 w7 K
  171.     /* 0001 */ { 2, 2 },
    + m' i2 K1 {9 Z: R' l# c9 k
  172.     /* 0010 */ { 2, 2 },8 ^" I' f: l3 X1 O, P
  173.     /* 0011 */ { 2, 2 },+ B2 z$ w- U2 l  A2 {. {( C6 H

  174. 9 `' O# m% J6 k2 N0 e$ L% }
  175.     /* code length = 2 bits; value = 3 */
    $ j% u; L' A' w- T3 v( [
  176.     /* 0100 */ { 2, 3 },) {2 Q4 H7 t) _- ?5 z* F8 f
  177.     /* 0101 */ { 2, 3 },
    # F" t2 U6 E. L% J4 C/ s% {0 t
  178.     /* 0110 */ { 2, 3 },7 c2 `0 `3 q: H/ Z3 i
  179.     /* 0111 */ { 2, 3 },& H( |$ t- n! B, E+ j
  180. 5 {5 A+ ^* J/ f
  181.     /* code length = 2 bits; value = 4 */* j+ g4 d0 k# r" G
  182.     /* 1000 */ { 2, 4 },$ Q% P- {; @1 v/ f6 J
  183.     /* 1001 */ { 2, 4 },2 M# g* X' l/ s& H$ _/ s7 D
  184.     /* 1010 */ { 2, 4 },8 t& E% ?, _! G
  185.     /* 1011 */ { 2, 4 },+ t: M$ r* c6 Z, m, ]' f" I
  186. 8 p0 R& W5 d: C1 a: g. y
  187.     /* code length = 4 bits; value = 5 */
    : U" c8 m4 h5 Y' W
  188.     /* 1100 */ { 4, 5 },
    : N/ X' ~4 F( e& c; ~4 Q; T! ]7 ~

  189. $ D" Y0 l1 J) J! y/ x/ _; e8 p
  190.     /* code length = 4 bits; value = 6 */) P% }  w# `  P9 i7 y) s
  191.     /* 1101 */ { 4, 6 }," f9 R4 }) ~8 I6 u4 s. p' u8 A% X
  192. . q3 ~: C8 {' Q
  193.     /* code length = 4 bits; value = 7 */7 \2 }0 I$ p+ k$ G, O9 z
  194.     /* 1110 */ { 4, 7 },# z& R/ {& g+ Z. p' Q/ Z

  195. 3 h8 A* B* c- k: a# u* ~
  196.     /* special case */
    / @8 S  l) D" \6 x- o
  197.     /* 1111 */ { 4, 8 }1 {2 S( ?, s/ Z# x- p! J9 h/ G
  198. };
    * X8 }( y2 b5 N" x% {
  199. + C4 |9 d/ I, @, R+ \4 ?
  200. typedef struct
    8 |: l! y/ t! x' X/ x
  201. {
    ; g( W* o' `% W% ]
  202.     int version;1 {+ `: Z, r, p  H1 H- _
  203.     int width;& u/ R, S# N) n$ D
  204.     int height;
    $ Z6 ^# ^# \9 W( `" ]
  205.     int frame_count;8 Q4 F" A! @& w& r6 c! `
  206.     int audio_chunk_size;; |0 q5 o# k; G, _4 L! q6 E2 S
  207.     uint8_t palette[PALETTE_COUNT * 3];
    , G( `; P) \6 l' a: \
  208.     off_t video_frame_size_table_offset;* o8 \- Q9 W$ T- A4 i/ a3 h2 z
  209.     uint8_t *video_frame_size_table;# E; U  u0 d6 L1 F; j
  210.     off_t frame_size_table_offset;1 a& }+ I6 ^8 a# \9 Q* H: Z
  211.     uint8_t *frame_size_table;4 G0 ]5 C7 M( q% b% J$ t+ t) Q
  212.     uint8_t *frame_load_buffer;
    ) z# ]$ R5 Q5 F, Z) k6 Y- a, A& W( O
  213.     int dump_frames;
    0 _( O& B8 D" P( C  `/ f6 V0 p

  214. 9 O/ |- m& o+ \( F# H* v
  215.     /* subtitle library */
    $ d0 K# j4 `1 V$ v3 V; F/ r
  216.     ASS_Library *ass_lib;2 D- I, {6 t4 y) T  L7 ^# T
  217.     ASS_Renderer *ass_renderer;
    5 }5 }2 D8 E5 }" }7 C( k
  218.     ASS_Track *ass_track;
    2 [6 R; F* d& u5 U1 A% |
  219. } rbt_dec_context;
    ' S; t$ n+ n. J; W2 ^
  220. * |5 t  j& n& a$ \5 B
  221. static void dump_pnm_file(char *filename, rbt_dec_context *rbt,0 T/ J; R1 F; r* [/ p4 h
  222.     uint8_t *image, int width, int height)
    $ K) h2 S% L8 g. A1 H
  223. {
    % q) r' h2 o- g7 u8 V8 a
  224.     FILE *outfile;
    ) [4 l+ J1 e' Z' ^& w
  225.     uint8_t bytes[3];
    , g. T& y+ n  W  h# c
  226.     int p;
    9 P  W$ w& @4 e! p
  227.     uint8_t pixel;
    2 m7 z7 n( a9 T. o/ b
  228. . L: i% m. B) l1 j9 ?2 X
  229.     outfile = fopen(filename, "wb");
    % b* u7 p6 z( s! \) o. u& _
  230.     fprintf(outfile, "P6\n%d %d\n255\n", width, height);0 I, ]1 E% Z1 g9 [5 @; n; O0 J5 _
  231.     for (p = 0; p < width * height; p++)
    9 p: I) l% k% m/ v5 b; N
  232.     {6 b1 m, F' m' A( }/ Z1 v* F* H: A
  233.         pixel = image[p];- C% @8 [0 Q! R0 V1 B, r* j0 H5 ?- k
  234.         bytes[0] = rbt->palette[pixel*3+0];
    ' y. ~- R+ }6 Q5 l) w0 H
  235.         bytes[1] = rbt->palette[pixel*3+1];
    3 Z; T) X9 K5 n2 [0 Y& W' a
  236.         bytes[2] = rbt->palette[pixel*3+2];
    " H7 @' u1 i. b
  237.         fwrite(bytes, 3, 1, outfile);; J/ Y9 u( [7 _1 p( v2 Y9 _2 Y
  238.     }
    * b2 K( {2 q! Z5 R( |, h: _4 n
  239.     fclose(outfile);: c/ p% L1 y! Y4 @
  240. }* C6 G2 T" y# v4 W% v% Z" I) K
  241. 9 s1 W, ^& v# P
  242. static int load_and_copy_rbt_header(rbt_dec_context *rbt, FILE *inrbt_file, FILE *outrbt_file)+ \+ r0 U: c* R0 }4 `
  243. {
    ' `' v+ n+ H! u
  244.     uint8_t header[RBT_HEADER_SIZE];
    1 p8 z4 ~+ J1 y$ u2 K; S: o. w
  245.     int palette_data_size;
    3 U" R. r7 H8 g+ d
  246.     uint8_t *palette_chunk;, E. X: [4 v4 B0 M6 H
  247.     int unknown_chunk_size;. E5 r/ ^. I, k6 F! {' S
  248.     uint8_t *unknown_chunk;/ ?0 E% {% D. y) p7 n" u# e
  249.     uint8_t unknown_table[UNKNOWN_TABLE_SIZE];
    . C, h3 R1 |/ X, {# t
  250.     off_t padding_size;* x* z! F5 W: C
  251.     uint8_t *padding;
    0 R1 A, h$ }- C! k# U( S
  252.     int i;
    4 R! G7 K: k' ?% _+ @3 F+ B/ T4 c2 {
  253.     int frame_size;
    % J  P( K" W0 o
  254.     int max_frame_size;
    0 i2 W& C" W  d/ w4 @% Y
  255.     int first_palette_index;
    6 ^0 Q0 J4 y1 r5 M1 L
  256.     int palette_count;  X' c: l; [4 k4 b
  257.     int palette_type;2 S* g2 V* z8 G
  258.     int palette_index;
    - S, Z1 p8 w7 @

  259. 2 w, D2 o" i& u; p9 ]6 N
  260.     fseek(inrbt_file, 0, SEEK_SET);/ ]! s, E& @5 M
  261.     fseek(outrbt_file, 0, SEEK_SET);) T: S- v# v% S* C
  262. 1 k; q' d4 N" j+ R
  263.     /* load the header */
    2 u" V" f: R1 l2 G& N$ X+ h
  264.     if (fread(header, RBT_HEADER_SIZE, 1, inrbt_file) != 1)- }9 s& t: }  }. C* L1 G' p* d9 e5 V, u
  265.     {
    0 `) k# K: t' m4 h
  266.         printf("problem reading initial RBT header\n");
    $ j3 h  u, I& r. p
  267.         return 0;
      Z+ I; q4 e* Q" K9 D
  268.     }8 t9 {3 g; n6 V7 z
  269. 8 d; g7 z3 _/ G# ]) D9 l6 i
  270.     /* copy header to the output */6 {# H. l/ _" R+ |; Q' X
  271.     if (fwrite(header, RBT_HEADER_SIZE, 1, outrbt_file) != 1)
    ' {. n3 X$ E- M! E. H& b0 R" Y# @
  272.     {
    ! o) N3 T" g' x6 }% M/ H- Y5 k
  273.         printf("problem writing initial RBT header\n");
    ) D5 Y6 t( J. c/ p& K
  274.         return 0;
    " c( s8 }9 t" ?5 x  @' L  v, W
  275.     }
    * G" h5 v( c! K- c. {4 b+ K! s
  276. + S$ q# c( v5 R+ ]- u" I* I8 m, j
  277.     rbt->version = LE_16(&header[6]);; C. @; z: Z8 E7 M+ G
  278.     rbt->audio_chunk_size = LE_16(&header[8]);; Y' X0 A' v" C4 S  p( n
  279.     rbt->frame_count = LE_16(&header[14]);1 p# S9 \2 r1 ]# N' W' b6 `

  280. & E3 d# N. P. n& c, b+ i4 B& j
  281.     /* transfer the unknown data, if it's there */
    3 o  G9 r8 j  T. L+ w! Y9 Z
  282.     unknown_chunk_size = LE_16(&header[18]);
    ) z9 W" `* a5 D
  283.     if (unknown_chunk_size > 0)3 ~/ Z# V8 h- r  Y  R
  284.     {
    : I0 V% K! C6 k$ _) L! l
  285.         unknown_chunk = malloc(unknown_chunk_size);6 c: m& X2 K; h1 G. H9 C
  286.         if (fread(unknown_chunk, unknown_chunk_size, 1, inrbt_file) != 1)
    ) [5 J8 C  K1 Y$ T6 e* s5 l
  287.         {/ V! a' S: }- C: S9 j
  288.             printf("problem reading unknown data\n");
    / e" s$ o; X/ |# @5 s4 `0 F" x  O; t
  289.             return 0;6 Q8 M3 d, k$ C! O9 b  E: r. |$ @5 o1 w
  290.         }
    5 a5 l! n& }' s
  291.         if (fwrite(unknown_chunk, unknown_chunk_size, 1, outrbt_file) != 1)$ d: K! S+ O% K
  292.         {
    6 ^+ l1 B6 N! z' b
  293.             printf("problem writing unknown data\n");
    0 [6 c; y$ j$ L
  294.             return 0;" h$ m  Z  d( d3 ?, ]* m
  295.         }
    ; M5 S' ]6 G8 j7 i! m. U+ m$ w1 P7 ^
  296.         free(unknown_chunk);
    " g* c& Y4 Z  v& l3 a
  297.     }: z8 v, w' D# P/ I
  298. + Q4 I( k; }0 v# u8 [% F( N$ e
  299.     /* transfer the palette chunk */
    9 }$ @# W4 r4 s$ r; V7 U
  300.     palette_data_size = LE_16(&header[16]);6 A% L+ s; |% p" e6 x2 d
  301.     palette_chunk = malloc(palette_data_size);
    , {& _" M4 k/ D! R
  302.     if (fread(palette_chunk, palette_data_size, 1, inrbt_file) != 1), U# T# f( u' {4 k* f8 l
  303.     {
    " m9 _8 ^5 W. l( \  Q& @
  304.         printf("problem reading palette\n");
    ' x( {  T5 U, J! a: i& a6 ^. v
  305.         return 0;7 I, I( B* K( G; U
  306.     }
    7 p. E6 X4 {1 G% m6 ]6 @8 a
  307.     if (fwrite(palette_chunk, palette_data_size, 1, outrbt_file) != 1)) H' i$ P4 x9 P, l0 j# I8 W
  308.     {
    8 n) |$ U2 ~) ?& l, P
  309.         printf("problem writing palette\n");
      r/ q8 h" m' R, X) t9 Y
  310.         return 0;3 X% X+ R; p* T3 j- C8 [
  311.     }7 O" r4 U6 h$ O) i+ z
  312.     /* load the palette into the internal context */
    0 g! K6 W1 s7 W* s) }
  313.     memset(rbt->palette, 0, PALETTE_COUNT * 3);
    ( }) s5 k5 a- D- `4 C
  314.     first_palette_index = palette_chunk[25];
    . q9 M. q- l0 r  d; e/ F, F
  315.     palette_count = LE_16(&palette_chunk[29]);3 k2 X8 _/ S8 M9 K+ N! E
  316.     palette_type = palette_chunk[32];
    0 v* P: P$ q  t$ ~. t% q# Q# w* n. e
  317.     palette_index = (palette_type == 0) ? 38 : 37;  L! j1 m# w; b$ @. m0 ?
  318.     for (i = first_palette_index; i < first_palette_index + palette_count; i++)
    ! B9 D8 y0 R# E8 b
  319.     {8 |: j8 F4 x( \. W3 N$ ~
  320.         rbt->palette[i*3+0] = palette_chunk[palette_index++];/ A9 T+ w, u  Z6 N# @
  321.         rbt->palette[i*3+1] = palette_chunk[palette_index++];1 l4 V4 |3 b: i$ k# L& Z
  322.         rbt->palette[i*3+2] = palette_chunk[palette_index++];
    3 O7 C5 R- t) x  t
  323.     }; F7 V$ S1 k, o3 M- t
  324.     free(palette_chunk);
    ) }! I$ C- H* p5 e% g$ @' ?
  325. ' u9 U0 H% n  Z+ u% |( Y! i* A
  326.     /* copy the video frame size table (2 bytes per frame), as a placeholder */
    0 q# P9 v# S" y- r4 ^7 J
  327.     rbt->video_frame_size_table = malloc(rbt->frame_count * sizeof(uint16_t));% M/ E. f* X5 @, A' a+ I
  328.     if (fread(rbt->video_frame_size_table, rbt->frame_count * sizeof(uint16_t), 1, inrbt_file) != 1)
    7 W& S. W' X2 r4 B2 A
  329.     {# I; y8 r9 _8 x: g: y! B
  330.         printf("problem reading frame table\n");  F9 Y" |) I: m$ s6 w
  331.         return 0;
    , a: `2 v* i  Y
  332.     }
    ' h+ [: B' o, u8 b4 {+ s3 S- [% _
  333.     rbt->video_frame_size_table_offset = ftell(outrbt_file);* h- u+ w4 b; @( ^" v3 a( r+ a
  334.     if (fwrite(rbt->video_frame_size_table, rbt->frame_count * sizeof(uint16_t), 1, outrbt_file) != 1)
    $ ^8 U- k  w5 l8 w' P8 O
  335.     {
    0 q; H& C( K' Y& ?. `! m. s% I
  336.         printf("problem writing frame table\n");
    & g# \' |5 C) K2 W2 p
  337.         return 0;
    , J) u. O$ y9 b" `: T+ ~+ r) {. o" ~
  338.     }
    + P" ~3 T5 R" J; \" x2 x3 r

  339. 7 h# t0 ~* f8 h# J9 [' z% Q
  340.     /* copy the frame size table (2 bytes per frame), as a placeholder */9 m2 F- G3 {" t- u2 D( S* ?
  341.     rbt->frame_size_table = malloc(rbt->frame_count * sizeof(uint16_t));
    ; {$ Z. u3 w! v7 X  O1 D3 u" @
  342.     if (fread(rbt->frame_size_table, rbt->frame_count * sizeof(uint16_t), 1, inrbt_file) != 1)
    # I) K3 p4 b3 w; ~6 \
  343.     {) R* B3 B7 N" W9 a
  344.         printf("problem reading frame table\n");- ]& t) c  r9 \: e, m" T5 S
  345.         return 0;
    7 V- O2 f6 d; u) x& i
  346.     }8 f7 T! Y* s9 k! R
  347.     rbt->frame_size_table_offset = ftell(outrbt_file);
    1 |+ t* c4 A7 @% i$ t: l" C) Z
  348.     if (fwrite(rbt->frame_size_table, rbt->frame_count * sizeof(uint16_t), 1, outrbt_file) != 1)
    ) K5 |0 l4 F" n% B5 E( ~8 O  M& ~& y; n
  349.     {
    , W. M. C% {" g' F! U7 `' a
  350.         printf("problem writing frame table\n");
    # D6 h0 Q* G/ E  M3 D3 X' h1 x
  351.         return 0;
    + p) P4 d4 p3 l
  352.     }
    8 W7 O  A% g% x! j4 j
  353. ( G  x  w: M3 y- F+ S
  354.     /* find the max frame size */
      \, h; \. \; O. n7 G5 b9 L$ I
  355.     max_frame_size = 0;
    ' {% ]7 U" B+ ]4 R
  356.     for (i = 0; i < rbt->frame_count; i++)
    * U9 W( u+ Y. |( v; B; [& |  N
  357.     {
    1 V& K' V8 \+ e* }! N4 U) F
  358.         frame_size = LE_16(&rbt->frame_size_table[i*2]);
    , ?5 f9 F0 i) r
  359.         if (frame_size > max_frame_size)$ g+ u' Y# ~7 q; O# b8 W( F
  360.             max_frame_size = frame_size;: A- V! T/ W* a5 n
  361.     }( N( M. m8 p  t. X2 F
  362.     rbt->frame_load_buffer = malloc(max_frame_size);
    8 u5 r. z4 Q$ O; Q' H, M6 y5 r
  363. $ [+ S9 V, {- Y. g$ d
  364.     /* transfer the unknown table(s) */' G) v% G4 s! v6 x7 r* v2 f
  365.     if (fread(unknown_table, UNKNOWN_TABLE_SIZE, 1, inrbt_file) != 1)8 G: c; M' e) M( H  Z
  366.     {
    ( J- S# q1 }" j  r
  367.         printf("problem reading unknown table\n");9 w( _' G# Q* ^) X  P% \& H
  368.         return 0;2 _- {8 t% F* e" s$ I' M
  369.     }1 v% m& K4 F8 y* J
  370.     if (fwrite(unknown_table, UNKNOWN_TABLE_SIZE, 1, outrbt_file) != 1), V5 R+ b4 e' C; \
  371.     {) d; e9 j  t6 ]
  372.         printf("problem writing unknown table\n");! ^& P- K* G: |2 E# q7 \. R
  373.         return 0;
    3 T: V/ S3 M* V3 V& s4 Y2 H
  374.     }6 D( k+ z% N, l+ _4 U5 m9 B8 K

  375. 4 c: w9 ~$ x$ s) x( Q
  376.     /* copy over padding */
    ) d* p% P$ z4 l, P. B5 C
  377.     padding_size = 0x800 - (ftell(inrbt_file) & 0x7FF);2 I4 z0 }0 z7 G2 p$ s
  378.     if (padding_size)
    8 q8 U  _# \# C7 O1 P! @& t
  379.     {/ u, h7 S, }( n
  380.         padding = malloc(padding_size);! A6 E; c1 L& A) C" s
  381.         if (fread(padding, padding_size, 1, inrbt_file) != 1)) `$ i4 p! d0 p4 B
  382.         {
    6 t, q0 B7 l! i! t) N6 D
  383.             printf("problem reading padding\n");. U) ~) ]- r( S8 Z; q* P6 i
  384.             return 0;& ]  j1 ~* W- O* j
  385.         }
    : j; c, }' r3 Y  |: m1 Z& c6 ^
  386.         if (fwrite(padding, padding_size, 1, outrbt_file) != 1)1 m& o4 C1 [0 i+ ]1 Q$ B
  387.         {9 r  U; Z8 D/ E7 K4 i
  388.             printf("problem writing padding\n");
    ) f' P4 }0 J9 E1 G1 D: }3 T
  389.             return 0;
    & o- J* F) f' P. f+ E1 j# A
  390.         }
    : ^) g) v' g3 `+ E
  391.         free(padding);4 z) D$ J4 C% ~
  392.     }
    0 j8 z+ C" _( [" w2 v

  393. 1 n$ d& Y4 N" B) \, ^
  394.     return 1;0 _$ Z7 W$ H2 P% Y% t
  395. }' Z8 b' q8 L4 {" Z; E' n  c  T3 ~
  396. 2 O0 B9 o$ m- f
  397. static int get_lzs_back_ref_length(get_bits_context *gb)/ M+ G: O" u& @. k8 h' \$ s1 v, C
  398. {
    - i& f% F- v; a4 `7 B. b
  399.     int vlc;; \* q7 U; U) ?2 V8 Q9 ]4 O
  400.     int count;* l. q8 v: \' p
  401.     int value;
    7 X4 K! I9 h! F8 {; i

  402. 0 D8 o# R. @, T% X
  403.     vlc = view_bits(gb, VLC_SIZE);8 R! _; M: q: T
  404.     count = lzs_vlc_table[vlc].count;
    $ \" R# M& p2 k* ^6 ?
  405.     value = lzs_vlc_table[vlc].value;( K$ Q& [: z" `  ~! o9 }

  406. , C0 A! R& d! X9 c+ T
  407.     read_bits(gb, count);
    . N& F; _- J/ ^6 k( ]* B* |. j
  408.     if (value == 8)
    . O9 J6 r2 f3 m: R- d5 D; R
  409.     {
    : Z$ l5 H+ T0 h/ f
  410.         do; }0 a: ?! x" D
  411.         {
    : ~- s* K" D- X: Q1 Q
  412.             vlc = read_bits(gb, VLC_SIZE);- t2 P2 B4 M7 z+ b
  413.             value += vlc;
    0 s' f# O. W* w8 E: r" N- L
  414.         }. J5 n: n3 `2 I  ]- C1 j4 @/ @% N
  415.         while (vlc == 0xF);3 G# \4 c; F" x; }2 \: H
  416.     }( H4 M2 Y* q9 J2 s& f

  417. $ I  K5 h8 l+ t' B# F+ w4 E4 Z; @  J
  418.     return value;
    ( m$ l) ^6 u  l. c/ E5 g
  419. }* m- j) z8 F2 Z; H0 J# q
  420. " ]3 Y: X1 T: V
  421. static void compress_window(put_bits_context *pb, uint8_t *full_window,2 G+ r+ R9 Y! }* Q
  422.     int full_window_stride,! J" _( i0 ~% R1 ^  p. ^
  423.     int window_top, int window_bottom, int window_left, int window_right)
    ; @, |% u2 P) n$ H5 _. m
  424. {8 C; [6 S: h# Y1 C, k
  425.     int last_pixel;# b9 l* |0 P- U& I7 E
  426.     int run_size;
    - {+ A" }  ^3 H
  427.     int x;1 S* C4 E9 B7 A' V. q- @
  428.     int y;
    % ^7 i6 t% |$ A  a
  429.     int start_index;
    6 V8 t' i# E9 ]4 I4 B: l9 a" A
  430.     int end_index;$ j$ [7 k( P; V  G
  431.     int encode_last_run;
    ) P! D7 C! s$ f9 z. X( L% b! }% p9 K
  432. 2 }  O0 k1 }: x; T. `9 g- ^
  433.     last_pixel = full_window[0];
    7 p8 P8 g2 H' ]) X5 G
  434.     run_size = 1;$ \8 M# G0 e# L5 ?
  435.     for (y = window_top; y <= window_bottom; y++)
    ) m% a1 c0 }& N
  436.     {& p- Q, `3 [0 t5 \
  437.         start_index = y * full_window_stride + window_left;/ F+ S$ f) ?' V% B
  438.         if (y == window_top)4 \5 m4 U! v( y2 ^! k, a5 P
  439.             start_index += 1;
    4 s4 u; \  c9 j6 L
  440.         end_index = y * full_window_stride + window_right;, b3 Z0 y3 f/ ]3 r& p. Q2 h/ l
  441.         if (y == window_bottom)9 ~3 v- i3 `3 b# N3 L0 V- F$ {
  442.             encode_last_run = 1;, e  O% s, a' f
  443.         else
    ' r2 r0 U; a, u' u
  444.             encode_last_run = 0;
    6 d" y4 V0 s* J0 H' k9 k* C7 y
  445.         for (x = start_index; x < end_index; x++)
    - O6 i8 z  B4 b5 ?  c9 Y  D
  446.         {
    * a( ?6 A* C) ?' O" \
  447.             if (!encode_last_run && full_window[x] == last_pixel)- r4 f9 I+ {9 _6 v
  448.                 run_size++;
    $ c5 k2 L/ u: \& {: i) a: S
  449.             else5 D6 p$ q$ Z  U
  450.             {
    9 Y$ l+ b& g8 c+ h  A; q1 P
  451.                 if (run_size == 1)
    / V8 h1 W! W6 ^% l
  452.                 {
    6 k' n( S9 y$ e6 ]4 s2 h9 m
  453.                     /* encode a 0 bit followed by raw pixel byte */* _* k- I2 t5 B- \
  454.                     put_bits(pb, 0, 1);
    # b7 m) O! @) _2 b; F3 b- m( ~* \8 [! P
  455.                     put_bits(pb, last_pixel, 8);5 y8 Z8 X- c9 o8 u9 ?' ?0 p
  456.                 }
    ) Y  ^6 R& O5 ]$ r0 `: ~# N
  457.                 else if (run_size == 2)
    ) O+ Y! X  |: G
  458.                 {! n4 |3 ]; r7 ]5 s* H( k2 N" T
  459.                     /* encode a 0 bit followed by raw pixel byte */1 L* e5 F& h, Q' f8 u
  460.                     put_bits(pb, 0, 1);
    : v" X' u, a8 _- n: x( r4 P6 j# T# X
  461.                     put_bits(pb, last_pixel, 8);* }* u# ?/ K: z! W% C
  462.                     put_bits(pb, 0, 1);7 V6 i# A0 J6 Y+ k
  463.                     put_bits(pb, last_pixel, 8);0 F( N/ x+ t; \& p
  464.                 }2 ]( s6 L  R; d, Z9 M
  465.                 else5 [/ Y) @% N; O9 K
  466.                 {! P& U  g+ I! q
  467.                     /* encode a 0 bit followed by raw pixel byte */( k7 I" h* p* S- v' N4 ^
  468.                     put_bits(pb, 0, 1);
    ' ~! g& y! l: _
  469.                     put_bits(pb, last_pixel, 8);0 p/ S9 ?' N3 p  E2 s7 @
  470.                     run_size--;6 Q/ z; j9 i) W; h( T# D
  471.                     /* encode a run: a 1 bit, followed by a back reference
    0 O& b9 J) ]2 H) A# W
  472.                      * offset (-1), followed by a length */6 r% L9 c5 U+ d6 E) k3 w
  473.                     put_bits(pb, 1, 1);
    , h$ {1 j3 t& t2 F8 l" o% {9 g
  474.                     put_bits(pb, 1, 1);  /* 1 = 7-bit offset */
    5 m0 r; k0 Q# z; M9 V; \
  475.                     put_bits(pb, 1, 7);% x, Q4 G& N/ x: L. W$ r' J/ G
  476.                     if (run_size <= 4)
    1 U4 [1 ~, u4 ^* ~; {1 {
  477.                     {: s& `& }, i3 k) v  J
  478.                         /* lengths 2, 3, and 4 are 2 bits */' R" e% e# @. s9 m' g
  479.                         put_bits(pb, run_size - 2, 2);5 M. |9 c4 U" T1 ^; g
  480.                     }) d8 X7 c) R% c  r8 C; |, F
  481.                     else if (run_size <= 7)
    4 h3 K; V: W- g3 g, H: V# \. b1 V! `
  482.                     {; ?# t' ?/ R7 |( ^; Y6 r3 E
  483.                         /* lengths 5, 6, and 7 are 4 bits */
    ; ]; X7 q! Z- Y( g
  484.                         put_bits(pb, run_size + 7, 4);" g3 e( _* Z# s6 S- F
  485.                     }
    7 J% C, J& m+ x. o+ t$ F
  486.                     else% N! `9 m/ K3 l4 p6 q" P
  487.                     {
    ! C& N( i& @3 W7 @* Y! h- @
  488.                         /* arbitrary length; start by encoding 0xF which
    ( R; u6 w: R) g+ R
  489.                          * stands in for an initial version of 8 */8 M! N, M6 p# l) J
  490.                         put_bits(pb, 0xF, 4);
    4 j# {/ w- h0 t! O
  491.                         run_size -= 8;
    ' n! \& p" q# e  }; J
  492. - B% N! }+ u8 [8 H- ^
  493.                         /* encode blocks of 4 bits until run_size is 0 */
    : R; G3 }8 L2 y& Z# g
  494.                         while (run_size >= 0)& L/ f$ M! L- N' y9 Z- D
  495.                         {
    6 p; e) N5 B1 G3 L" D" W# }$ B4 u
  496.                             if (run_size >= 15)
    ( d5 b! A3 x, z' t/ Z
  497.                             {0 C, ~" X8 C% z8 Y
  498.                                 put_bits(pb, 0xF, 4);
    0 n& N0 `2 z- W* b: Z
  499.                                 run_size -= 0xF;
    7 z$ N& ]; c% W+ `, |  ?# ^/ h
  500.                             }
    % u- S6 f1 n/ R
  501.                             else7 Z, Z( T+ @$ Y0 \7 t5 s
  502.                             {8 g. e4 b9 |$ M  v7 w2 r3 K
  503.                                 put_bits(pb, run_size, 4);1 W0 s- z# E, K" N- g& u
  504.                                 run_size = -1;
    ) Z2 t% q3 r# S$ z5 e
  505.                             }
    - y  i& o, n2 e/ j$ b2 m
  506.                         }
    * f) C" E. \. c$ c4 b
  507.                     }
    * r! Z" l7 T. E/ l; y9 C
  508.                 }9 g$ v$ A5 ?* A2 t3 b: O

  509. : X* `" \/ w$ @9 @% v, p. x
  510.                 last_pixel = full_window[x];* F+ a" N1 G! @# l/ _
  511.                 run_size = 1;
    8 v# N' n! |) q1 Q6 h
  512.   Z! p4 k7 ~! Y! M) [
  513.                 /* this single x iteration was only here to close the final run */, D5 `* v3 {) Z' p
  514.                 if (y == window_bottom)9 a0 r5 i  H3 W8 p) m
  515.                     break;( l& w$ F4 x2 W/ V( }" g; I1 q
  516.             }
    ' c3 D4 ?# ]  b. C- }/ n3 ?
  517.         }) a& Z9 `1 |6 j0 I
  518.     }
    ; K; e! A6 n. H( t9 E7 f8 I1 v8 {
  519. * G1 @' t( i; l
  520.     /* close the bitstream by encoding a back reference with length 0 */" n3 z1 I  F* Z( h3 Q1 {; h# ~
  521.     put_bits(pb, 1, 1);  /* back reference run */2 G0 ~& ^% A5 `3 D7 w  `4 p
  522.     put_bits(pb, 1, 1);  /* 1 = 7-bit offset */
    ) ^6 w& t* o$ e9 A0 W# E/ }
  523.     put_bits(pb, 0, 7);  /* length 0 */& k0 t2 t& G9 {8 o1 ^

  524. " W- @0 B, @, V3 d5 A; Y3 j
  525.     put_bits_flush(pb);$ K7 L; d( Q% I* Q# y
  526. }7 `# Y4 M& B+ c- L; Q. B
  527. ! t4 Q& M) k7 @5 E- G& Z( @
  528. /* compute Euclidean distance between an RGB color and the desired target */3 b5 a% Y3 Y) `4 H/ @5 i( D
  529. static int compute_rgb_distance(int r1, int r2, int g1, int g2, int b1, int b2)
    0 \) V: U2 r0 x6 v( r$ X
  530. {
    3 d6 [6 D1 I1 X! E
  531.     return sqrt((r1 - r2) * (r1 - r2) +
    5 @9 ?, U8 C+ A% Y
  532.                 (g1 - g2) * (g1 - g2) +
    1 o8 a& o; Q+ Q; V6 h
  533.                 (b1 - b2) * (b1 - b2));
    6 @: L; q% B4 V8 R* ?* T
  534. }% P# L4 i, c% W- D- v# e7 n) D

  535. $ i5 V" g. i, e% R0 n1 E4 q9 X% i1 c
  536. static uint8_t find_nearest_color(rbt_dec_context *rbt, int r, int g, int b)' M+ O, C' \& \
  537. {5 y6 v% j6 N7 q( S) h. v
  538.     int i;
    % w# i, }4 K+ Q- [- {2 J
  539.     int nearest_distance;/ X4 P) f/ J2 U. [8 z
  540.     int distance;3 C0 u! u: [! g9 v, a) {
  541.     int rp;
    6 ]0 [, \% [; g) o: J5 n: G
  542.     int gp;+ K/ h! \1 X2 R2 d  G" U! e
  543.     int bp;
    ; j, `- `" X8 }
  544.     uint8_t palette_index;$ [( s4 E" P( F6 k2 F5 x3 T9 i4 y

  545. + i- S1 u6 _6 v. O( l
  546.     nearest_distance = 999999999;! ^. K" \8 G- ^' D+ S) K- s: A+ |
  547.     palette_index = 0;
    9 T' G$ n1 }/ F5 u9 j+ `
  548.     for (i = 0; i < 256; i++)
    # W6 L& C9 o4 d: Q* y
  549.     {6 S5 y6 |: _6 [" H; C' M
  550.         rp = rbt->palette[i * 3 + 0];
    2 h1 p  i% X  q# E' c* z
  551.         gp = rbt->palette[i * 3 + 1];
    7 A2 y! g8 H# n2 k
  552.         bp = rbt->palette[i * 3 + 2];
    6 H+ b* }# }7 w) _
  553.         distance = compute_rgb_distance(r, rp, g, gp, b, bp);
    ' @* {: R! c+ i% k7 I. _
  554.         if (distance < nearest_distance)
    & o* F2 ]! A( E5 p5 _/ b
  555.         {
    7 t* i- b" @1 i8 n$ \% X
  556.             nearest_distance = distance;
    . O8 d3 Z! \( W  a& e3 P1 b
  557.             palette_index = i;
    2 {$ C! ]6 m8 }
  558.         }- v9 |. \7 ?4 c+ s
  559.         /* can't get closer than 0; break early */
    * V8 D, D8 J: L! A
  560.         if (distance == 0)& q/ k. A9 X6 u8 T/ n' Y! m; n
  561.             break;8 Y2 Q; e- t7 w& o8 s8 A. f6 j
  562.     }9 |& }/ c6 \4 B, e8 x$ o) x
  563. 0 e( B4 ~9 G8 E) d  U& y* N$ P
  564.     return palette_index;
    - U0 U- J/ ?1 b! Z' d0 o
  565. }( G' z1 ~' o# D# B) N, A8 p* ?

  566. / @4 c' x% c: T7 `5 o4 D- q
  567. static void subtitle_frame(rbt_dec_context *rbt, uint8_t *frame,
    8 C; e6 c* M, S6 h# a6 m, a' a
  568.     int width, int height, int timestamp)& I7 \; O9 E. s
  569. {
    5 C1 A' a3 t7 h' P' d" h
  570.     ASS_Image *subtitles;; v, ?5 Z1 J/ M1 b' Y' V1 y2 Y
  571.     int detect_change;
    ' `1 q% y' Y! w
  572.     uint8_t subtitle_pixel;0 B0 H1 ]5 ]8 c6 d. ]( h: i$ K
  573.     int x, y;
    4 N* R+ L4 y) f9 G3 G; ?
  574.     uint8_t *frame_ptr;2 g7 r: W4 F# T$ ~
  575.     uint8_t *subtitle_ptr;
      H0 w! L8 C+ y: w% g
  576. # _: b* c1 S$ \* E; C2 ^+ j3 s
  577.     /* ask library for the subtitle for this timestamp */
    ( Y# U' z0 }0 Q* _' f; P8 t5 }$ v
  578.     subtitles = ass_render_frame(rbt->ass_renderer, rbt->ass_track,9 w& [3 k6 N! D2 l$ {
  579.         timestamp, &detect_change);; j0 h6 x; ^" U/ R5 W
  580. 5 V/ x- G; _1 i9 l6 x
  581.     /* render the list of subtitles onto the decoded frame */' V' G6 }4 U$ n" m' s  D
  582.     while (subtitles)6 V5 Z9 |2 Q. W1 C, d( \, v7 y3 T
  583.     {8 g; h+ [1 i. ~, m2 f) u3 r
  584.         /* palette components are only 6 bits, so shift an extra 2+ O# c& h' p4 p
  585.          * bits off each component */" P8 s' }; K# F" c5 E& }
  586.         subtitle_pixel = find_nearest_color(rbt,4 c6 [" u8 `9 W( _- p
  587.             (subtitles->color >> 10) & 0xFF,
    6 ^: ?3 ?! K1 ]) L$ {/ F
  588.             (subtitles->color >> 18) & 0xFF,5 k" i' ^& l( j; |  e. q" k. b1 k# _. L
  589.             (subtitles->color >> 26) & 0xFF);
    ) D1 K: D4 K( Y* _
  590.         for (y = 0; y < subtitles->h; y++)
    " D* r8 j: g* i3 q; u! P( B7 I  C, R
  591.         {& X$ N1 J+ N4 |" ~1 T# |& V0 O
  592.             subtitle_ptr = &subtitles->bitmap[y * subtitles->stride];. z  c. Q- B1 {% v
  593.             frame_ptr = &frame[(subtitles->dst_y + y) * width + subtitles->dst_x];
    ' ^1 F' v* C5 J# p; x) _) q  t
  594.             for (x = 0; x < subtitles->w; x++, frame_ptr++, subtitle_ptr++)/ C' [: G, S& G- P+ ]
  595.             {" H( {* [# L. A- q
  596.                 if (*subtitle_ptr >= SUBTITLE_THRESHOLD)9 N& F# n+ v1 ^1 a$ t; W* Z
  597.                     *frame_ptr = subtitle_pixel;9 b% k3 |; j! t7 ?
  598.             }) @. H% m6 [, z
  599.         }
    8 R  d, a4 \5 z& k: V
  600.         subtitles = subtitles->next;
    , E2 V% ?6 h& f0 s7 {1 _
  601.     }
    0 j) E; @8 z& X1 h: [* o
  602. }7 Z& @3 E# L* ]& C+ y: H

  603. % {$ H$ a2 r0 y4 o' H
  604. static int copy_frames(rbt_dec_context *rbt, FILE *inrbt_file, FILE *outrbt_file,6 D% f$ S: S- _& E2 s# B7 J6 V
  605.     int origin_x, int origin_y, int window_width, int window_height): j* r$ P* `1 x7 d/ {" e4 D3 c
  606. {
    6 A( E* A% h  l5 s/ T
  607.     int i;0 ]. Y+ |* c2 N! V# P7 _4 t5 V+ }/ B
  608.     int j;
    & Y, m! u7 q5 G; I2 f: j
  609.     int scale;
    - \6 n8 j& v- T8 v* Z
  610.     int width;
    * |- j* K4 ~8 ?& K5 B* b0 q; v
  611.     int height;, P  O% o6 v; q' t! X* ~- T' t* G
  612.     int max_width;
    6 f% l! h, I* j1 y4 X
  613.     int max_height;  y" V. J  A  _, B
  614.     int frame_x;
    8 _4 _: s! F9 q9 a; _- q8 W
  615.     int frame_y;
    0 I/ K! y+ K: v6 ]* Q
  616.     int fragment_count;
    3 k0 g0 e# D2 P
  617.     int decoded_size;
    4 H" n' L" L% o: Q
  618.     uint8_t *decoded_frame;8 N7 l1 s, a4 b9 X6 C8 o. M
  619.     int fragment;# t% S+ M# n! a& p
  620.     int fragment_compressed_size;
    : H# W& E& S- H- a4 O1 c0 z( t
  621.     int fragment_decompressed_size;
    " v6 Y7 Y1 X+ \) T+ H6 Q7 Y! D
  622.     int compression_type;, D8 z2 B3 G8 Y! ~. }& B
  623.     int index;
    & S) {! C+ G$ }, C! r/ o
  624.     int out_index;
      C9 [' R' p% n: J3 I7 {# B
  625.     get_bits_context gb;
    + f3 t' H# W( V! ]
  626.     int frame_size;
    & q3 m  u  ^' E/ ^& E
  627.     int video_frame_size;
    4 o9 v" n: v: C' S
  628.     int audio_frame_size;
    / g. [/ _& N9 A% z- p

  629. 3 S: i, |& h$ D; f- j3 y( _$ ^2 L
  630.     int back_ref_offset_type;' q; Y" @+ j: w7 i# \% W% H
  631.     int back_ref_offset;5 G6 H) V7 o* \. l
  632.     int back_ref_length;
    # s1 s- k" \4 X8 m
  633.     int back_ref_start;) P- A, V4 N3 O9 D- f
  634.     int back_ref_end;" T2 l* v: g, y8 r1 B

  635. - ^& L$ E/ H: a1 w
  636.     uint8_t *full_window;
    8 @* n+ X* [2 e
  637.     int full_window_size;* b. D2 t6 p6 t2 C" y0 u8 {
  638.     int y;
    5 a* y  M0 Q9 s' }* y+ |; D7 V
  639.     int window_top;5 Z* m4 c& @1 k) f+ w* }/ i9 J
  640.     int window_bottom;  ?1 i" D7 z+ `. p) t  c- f; Z
  641.     int window_left;/ X# i5 d. b# G$ i
  642.     int window_right;
    # I4 c. |, x) k7 m  G( P# c
  643.     int window_size;
    % d2 }: H( D8 p
  644. 9 |( J1 [3 [2 @3 \" z
  645.     char filename[30];2 s1 h3 r: S% ^! `- u9 _, _7 Q

  646. 8 k5 j# c" k7 B* O+ f9 l
  647.     put_bits_context *pb;) k# t3 i4 ?8 p# `( Z
  648. ! M4 f  C( Y0 ^( e" ~
  649.     full_window_size = window_width * window_height;# f, P: r9 N# i
  650.     full_window = malloc(full_window_size);3 ]$ y. ]- @8 [
  651.     pb = init_put_bits();
    ) Y. v+ I+ v. S1 T' I

  652. & a7 A8 J1 g# a7 m6 ~, X
  653.     max_width = 0;" j& D7 q! H: j' b
  654.     max_height = 0;+ D- v( m+ b% O* ?  U  [

  655. 3 X4 ]1 x$ b# C" Y
  656.     for (i = 0; i < rbt->frame_count; i++)% u2 |* i5 _. S( X
  657.     {( J0 v( R8 A; d4 y3 z* z
  658.         /* read the entire frame (includes audio and video) */
    4 K2 X) \* X& E& ]# s
  659.         frame_size = LE_16(&rbt->frame_size_table[i*2]);
    ; m  ~  Z6 U4 X( u9 V
  660.         video_frame_size = LE_16(&rbt->video_frame_size_table[i*2]);
    # ?  J- v- u; a0 u& c$ `9 o2 Z
  661.         audio_frame_size = frame_size - video_frame_size;1 _2 y! {( y( o6 {! P9 ?
  662.         if (fread(rbt->frame_load_buffer, frame_size, 1, inrbt_file) != 1)
    ' i8 ]) [) l5 p7 @; o& M  m! E4 X
  663.         {
    % |/ F" l2 D, S7 N( i7 n3 }, S/ @- \
  664.             printf("problem reading frame %d\n", i);3 Y, T) E+ T" V; l0 x5 {! P7 g9 n
  665.             return 0;
      u, ?0 A. e: X0 x  E1 }4 r
  666.         }
    8 @' v# U) T: L* r9 i/ l1 J
  667. : E% C1 w8 g3 Q! {
  668.         scale = rbt->frame_load_buffer[3];$ X7 C7 P5 Q+ V$ q1 P
  669.         width = LE_16(&rbt->frame_load_buffer[4]);
    2 C, }1 S+ N# @
  670.         if (max_width < width)" V0 P" q0 d4 `' Z5 i7 z4 m
  671.             max_width = width;0 U+ r: C3 C# }# k# F4 i! E
  672.         if (max_height < height)' S. Y6 m: @0 x' b* h( T$ n" f
  673.             max_height = height;
    9 |" ~/ n4 M% u6 Q& Q
  674.         height = LE_16(&rbt->frame_load_buffer[6]);3 W  u' r  q" I
  675.         frame_x = LE_16(&rbt->frame_load_buffer[12]);
    6 n1 g: U5 l) c; d7 Z
  676.         frame_y = LE_16(&rbt->frame_load_buffer[14]);. s( O" h3 {8 G
  677.         fragment_count = LE_16(&rbt->frame_load_buffer[18]);
    1 z2 p9 e6 j8 [$ F* F
  678.         decoded_size = width * height;- v& S* _- z: P, S1 z

  679. . d5 k& ?" F# K
  680.         printf("processing frame %d: %d%%, %dx%d, origin @ (%d, %d), %d fragments\n", i, scale, width, height, frame_x, frame_y, fragment_count);# H8 I; h$ l" Z3 L
  681. 4 a* ^0 I! `% r+ l
  682.         /* decode the frame */0 h' @% N& h' z, Z8 l. y
  683.         decoded_frame = malloc(decoded_size);
    3 }+ A4 s& {) A
  684.         index = 24;# h2 I8 w* Y3 ^/ r
  685.         out_index = 0;
    + Z9 J4 [8 C3 j7 S7 x0 @  j5 p) I4 c
  686.         for (fragment = 0; fragment < fragment_count; fragment++)  Y+ f5 L* T3 {; C& y; b( b& S
  687.         {2 R7 ^/ k% F/ \1 z! a3 X, f# w
  688.             fragment_compressed_size = LE_32(&rbt->frame_load_buffer[index]);% f7 K4 V( @% z
  689.             index += 4;, Y% [4 e  c3 a7 V" S8 t
  690.             fragment_decompressed_size = LE_32(&rbt->frame_load_buffer[index]);
    , h. E6 ?/ j% x; U3 S
  691.             index += 4;
    ; m# p" u- r+ o5 _3 M" {- b5 q
  692.             compression_type = LE_16(&rbt->frame_load_buffer[index]);
    $ N" S0 r4 A5 U1 R* _
  693.             index += 2;4 V. I8 C7 d' ~3 U  G

  694.   z3 `& B" h0 d! S2 H* I& U
  695.             if (compression_type == 0)  D# J( O' b2 S, m3 v" Z, S4 S/ `
  696.             {, a' T. c! f& `- q
  697.                 init_get_bits(&gb, &rbt->frame_load_buffer[index],
    ) C% g7 _" D4 J" b" l
  698.                     fragment_compressed_size);
    + A: O1 _( w) C  i5 Z! d$ `5 s( A* W
  699. - v! l& V7 G2 N# q
  700.                 while (out_index < fragment_decompressed_size)
    9 T  T+ B' ?$ _% S0 M! W
  701.                 {& u& b4 l% v+ c- p3 H/ J
  702.                     if (read_bits(&gb, 1))
    7 `8 Y- k9 S) @
  703.                     {
    ) Z8 f; I' s( {7 p
  704.                         /* decode back reference offset type */# }: H8 B7 S  \
  705.                         back_ref_offset_type = read_bits(&gb, 1);+ G% L) k7 j8 k$ {2 Q7 w

  706. 3 d) U, ?6 l: ~/ [( V
  707.                         /* back reference offset is 7 or 11 bits */+ @1 ?" Y/ m0 ?- J5 z8 a+ r
  708.                         back_ref_offset = read_bits(&gb,
    + |1 c: K7 |/ Z& m( z8 r& K
  709.                             (back_ref_offset_type) ? 7 : 11);3 Y9 w! n' ^* k$ X1 ~
  710. , m4 `. W7 _0 W1 Z8 [4 y. g
  711.                         /* get the length of the back reference */
    * p: u4 E9 S" ^& i; b
  712.                         back_ref_length = get_lzs_back_ref_length(&gb);) w( L. H$ S! Y  d  s& e
  713.                         back_ref_start = out_index - back_ref_offset;
    " N9 Y" V: p/ M) s
  714.                         back_ref_end = back_ref_start + back_ref_length;
      W) x9 ?5 a6 ~6 y
  715. 7 Q6 T8 I* u' w2 q7 V
  716.                         /* copy the back reference, byte by byte */5 v) V8 j! e4 w8 k$ ?  w
  717.                         for (j = back_ref_start; j < back_ref_end; j++)# j1 [- i8 T4 e( _; e7 _& j
  718.                             decoded_frame[out_index++] = decoded_frame[j];9 G8 g* B. B0 t8 V+ M- Z: A/ f
  719.                     }4 G4 ^, x6 E3 g) g/ d- ]
  720.                     else
    / t; S: F2 b* h$ o% u! R& N6 [
  721.                     {1 l3 b6 [2 t3 u: P9 D8 x
  722.                         /* read raw pixel byte */
    1 ]. o  N; Y5 x, u
  723.                         decoded_frame[out_index++] = read_bits(&gb, 8) & 0xFF;
    ( Z9 v! u, [: k: k( Q, g1 ]5 j* N) R
  724.                     }/ c0 C' j( ?0 G3 Z) p7 q7 i
  725.                 }
    " m* Q; h1 A: D( ]* X0 B

  726. - ?' F: t+ b. }7 ^7 ]  M5 Z
  727.                 delete_get_bits(&gb);
    * N; }! `+ V  B; i. W) u
  728.             }
    $ {: x0 ~" }6 V/ P( K8 q) d2 s

  729. ) F6 s: t$ p/ F6 E1 |  m  z
  730.             /* next fragment */
    : t2 Q' n3 m# @" \. i
  731.             index += fragment_compressed_size;3 J6 O% {1 l% Z0 L
  732.         }7 u$ K  K$ l& d8 b( ~, H

  733. 2 x- W! A& i- ~6 Q$ l6 T
  734.         if (rbt->dump_frames)
    8 I6 U4 R3 F5 @1 R
  735.         {% e. |9 {  M, w( g, h3 e+ T2 J3 M
  736.             /* dump the original frame */! q' `8 F- l+ a8 T- c! |/ y
  737.             sprintf(filename, "original-frame-%03d.pnm", i);
    / n9 i  |6 p8 P0 @. g+ E8 J9 i
  738.             dump_pnm_file(filename, rbt, decoded_frame, width, height);% Q5 a* R  X3 K  h$ y
  739.         }
    ! I. N8 P3 f# [( Y- f

  740. 4 J4 S( U# F; B% o- j
  741.         /* transfer the image onto the frame window */. X3 g) `0 X) w- _1 }( x; h
  742.         memset(full_window, 0xFF, full_window_size);
    ! {. f2 U3 c9 q( ?
  743.         index = 0;9 j% f; a' {$ u* i( l( |: w+ Q  i
  744.         for (y = 0; y < height; y++)
    ' M  ^5 q. @5 Q1 }
  745.         {) J+ _- d9 d! V4 s6 ^; a
  746.             out_index = window_width * (frame_y + y) + frame_x;3 v7 p% f  R9 c% U' F
  747.             memcpy(&full_window[out_index], &decoded_frame[index], width);
    # v1 v; V/ W4 z/ b4 k! Q
  748.             index += width;
    7 Z3 P1 W4 G" x. j* J. Q
  749.         }
    , y+ h) ?# }2 u. l1 ^

  750. 6 J* P4 J5 U0 E/ D% ]: N
  751.         /* write the subtitle */) N# f$ M* P& _) n1 U0 k
  752.         subtitle_frame(rbt, full_window, window_width, window_height,, n0 V$ V; }0 [' F' N. ^1 t# \2 F
  753.             i * MILLISECONDS_PER_FRAME);! X) g. i, m! J& c

  754. 3 W) b7 V, {( r5 f
  755.         /* figure out the smallest change window */
    % i8 j! G  V) F- u  o/ V' }
  756.         window_top = frame_y;4 U* E+ C, W5 M- D  g6 j
  757.         window_bottom = window_height;
    2 A- l7 Y9 o6 d9 \) d+ {8 Z5 ]! @/ y
  758.         window_left = 0;
    2 v. |6 n: ]; Y' ?8 z
  759.         window_right = window_width;0 E! J% f! x; n" H2 l
  760.         window_size = (window_right - window_left) * (window_bottom - window_top);9 L( e$ N" ^6 b3 w

  761. ! f' V2 T0 e. d% m. E
  762.         /* compress the frame */
    & o4 ]5 ?1 A' T' M& g) q% |
  763.         reset_put_bits(pb);
    9 @- Z9 e" D* [1 z+ U  t3 T
  764.         compress_window(pb, full_window, window_width, window_top,1 V/ k2 d6 g9 y- a
  765.             window_bottom, window_left, window_right);/ ~2 N9 w! }  T2 {& J1 e. ]

  766. ) A' f: {: E. g- ]0 X' W
  767.         if (rbt->dump_frames)
    % d$ H4 {% Q$ ?  v- g
  768.         {
    ! g1 E; A! q) r1 x( z+ ?
  769.             /* dump the frame plotted onto the full window prior to encoding,% G7 [) X4 ]- U/ Y6 m
  770.              * with subtitle */
    & E) d  n3 o; P' Z( [0 X9 ~
  771.             sprintf(filename, "pre-encoding-frame-%03d.pnm", i);5 S' w' R* X, ~6 V. k; G
  772.             dump_pnm_file(filename, rbt, full_window, window_width, window_height);
    9 i" f) O  u& o2 L* d1 x
  773.         }8 Q0 d9 M  y- n& o3 G9 U
  774. 4 \5 r- D5 u% l; e. r8 x
  775.         free(decoded_frame);% g( P7 T" Z/ X" Y: {; f
  776. $ e2 o6 q2 L* C4 k
  777.         /* update the frame header */  V3 b' l: ~( W# |
  778.         /* width */
    * {! Q3 _; g4 j, Z" W6 c
  779.         rbt->frame_load_buffer[4] = (window_right - window_left) & 0xFF;
    6 V! ~7 p+ h, ?& W4 A4 H' f
  780.         rbt->frame_load_buffer[5] = (window_right - window_left) >> 8;
    % W7 `0 w. ?# z$ a& q
  781.         /* height */
    8 `1 Z: k/ c; t: J2 G
  782.         rbt->frame_load_buffer[6] = (window_bottom - window_top) & 0xFF;
    ' Q8 M  l  y( @, ^9 n
  783.         rbt->frame_load_buffer[7] = (window_bottom - window_top) >> 8;! c/ a7 J8 g$ G$ x8 q
  784.         /* origin X */
      O5 p4 \9 r* E
  785.         rbt->frame_load_buffer[12] = window_left & 0xFF;
    , ?" o4 m( b6 f- h; O
  786.         rbt->frame_load_buffer[13] = window_left >> 8;! H' v. G( m6 y4 z9 l7 U
  787.         /* origin Y */
    4 I, }5 ]+ f' K/ T' L: r+ t2 l
  788.         rbt->frame_load_buffer[14] = window_top & 0xFF;
    7 X+ I, i; S7 ]" _
  789.         rbt->frame_load_buffer[15] = window_top >> 8;: A  W) Q" R( i9 E2 e2 y# o4 N
  790.         /* fragment payload size */1 k$ r/ Z; L1 q
  791.         rbt->frame_load_buffer[16] = (pb->byte_index + 10) & 0xFF;
    1 Q! `' y. [* F2 l
  792.         rbt->frame_load_buffer[17] = (pb->byte_index + 10) >> 8;
    9 \; ]  {8 c1 r* r" E
  793.         /* fragment count (1) */; B  e% [4 f4 Q9 s
  794.         rbt->frame_load_buffer[18] = 1;
    9 C% N/ ^9 l2 [
  795.         rbt->frame_load_buffer[19] = 0;
    5 [% {1 }1 C$ Y$ M7 o. V& d
  796. / p+ d3 |1 U) I
  797.         /* update the fragment header */: U( n- p" s4 S+ X
  798.         /* compressed size */* }6 d, v8 v! R) x0 f# h, B& s
  799.         rbt->frame_load_buffer[24 + 0] = (pb->byte_index >>  0) & 0xFF;
    # |4 M# S* ^& C# j# x5 U
  800.         rbt->frame_load_buffer[24 + 1] = (pb->byte_index >>  8) & 0xFF;: L7 L- m9 k# @; O% W
  801.         rbt->frame_load_buffer[24 + 2] = (pb->byte_index >> 16) & 0xFF;+ W' {" s: x, i8 f" k4 a5 v# O
  802.         rbt->frame_load_buffer[24 + 3] = (pb->byte_index >> 24) & 0xFF;
    : G% i  E  \- q6 J
  803.         /* decompressed size */! p8 U1 u6 w4 p. S" A. T
  804.         rbt->frame_load_buffer[24 + 4] = (window_size >>  0) & 0xFF;
    3 c9 V! ~; L" m/ N) ~) A
  805.         rbt->frame_load_buffer[24 + 5] = (window_size >>  8) & 0xFF;
      k3 i6 ]* r' L3 h, y% j
  806.         rbt->frame_load_buffer[24 + 6] = (window_size >> 16) & 0xFF;1 M! ?" w  _! A  O" v: \
  807.         rbt->frame_load_buffer[24 + 7] = (window_size >> 24) & 0xFF;
    3 _/ E1 u3 ?% r: Q. K9 O, V% O! u
  808.         /* compression format 0 */% `/ R" }" p1 c# O- a4 [
  809.         rbt->frame_load_buffer[24 + 8] = 0;
    ( R$ b+ O# {' R# |7 `* r4 y4 o0 e
  810.         rbt->frame_load_buffer[24 + 9] = 0;& Y/ ], I5 b. i$ S

  811. / `# c- Z: N; \2 Y" c
  812.         /* write the 24-byte frame header and the 10-byte fragment header */
    $ l0 \( W7 _3 k
  813.         if (fwrite(rbt->frame_load_buffer, 24 + 10, 1, outrbt_file) != 1)$ i, S( H$ q0 [: C
  814.         {
    $ c; ?. W! b/ u! K% |  @% u
  815.             printf("problem writing frame %d\n", i);! A9 N+ y4 t" U9 l
  816.             return 0;
    1 h& Z. ~/ |: T0 U7 Z, l4 f& m
  817.         }
    4 |% N: J/ O; j; u8 r* T8 N" o! Q

  818. ' A* B; a# C- i
  819.         /* write the new compressed frame data */
    4 M! U) X6 a4 y0 z
  820.         if (fwrite(pb->bytes, pb->byte_index, 1, outrbt_file) != 1)$ g5 o6 T" C7 a; M% ~- U
  821.         {
      \( E9 p7 H: T+ D: ^
  822.             printf("problem writing frame %d\n", i);
    5 Z# M1 w: x) S: A  \$ u1 l
  823.             return 0;
    9 k$ H' a0 a# V9 p# n" z8 B
  824.         }0 h- k5 e& E6 w& F9 V$ \
  825. : n4 t1 [. I$ E! T. Z
  826.         /* write the audio data */: v- w& Q$ D% }4 E; B/ g
  827.         if (fwrite(&rbt->frame_load_buffer[video_frame_size], frame_size - video_frame_size, 1, outrbt_file) != 1)
    5 R- `3 a5 @4 T
  828.         {9 B7 K& f* h( J7 k4 p
  829.             printf("problem writing frame %d\n", i);- J! y. z" A7 |: @5 C! ?
  830.             return 0;5 A: }; S- R* ?: P" D" a  O: w7 l
  831.         }' q; p- e$ E- x  f# B" V* h$ E; s
  832. 9 @6 |. @& |2 K9 K% |& w
  833.         /* update the table entries */# x+ E1 _( Q2 z+ c" y
  834.         video_frame_size = pb->byte_index + 24 + 10;
    ) W5 E2 o1 B) g3 w2 \( g. D+ H* Z
  835.         frame_size = video_frame_size + audio_frame_size;
    5 E+ f% N4 @& V2 h3 i* V
  836.         rbt->frame_size_table[i*2+0] = frame_size & 0xFF;& U1 V& [" P2 N9 o% _2 e, _; H
  837.         rbt->frame_size_table[i*2+1] = frame_size >> 8;' y! W- Y2 o" G' f% _6 S
  838.         rbt->video_frame_size_table[i*2+0] = video_frame_size & 0xFF;2 L0 b- M1 \7 Y. W  D: ?
  839.         rbt->video_frame_size_table[i*2+1] = video_frame_size >> 8;) a: n5 S2 P$ V. G/ G( N! X
  840.     }4 Z# x- i" G) h4 K8 w$ X4 a

  841. 8 v4 }3 ~2 `% x0 A, d( R
  842.     printf("maximum dimensions seen are %dx%d\n", max_width, max_height);+ d2 P& S8 P; R9 V6 s+ T3 D

  843. ' j% I5 e4 E3 w3 [
  844.     delete_put_bits(pb);
    4 @5 b. t2 H9 _" S
  845.     free(full_window);1 q: E  f3 ]0 C5 I, X

  846. 5 Z; i' u1 Z; D2 F$ Z9 J4 l
  847.     return 1;
    + p( b: _8 F* q+ N3 k: V2 w
  848. }& d0 `: q$ `8 V5 u
  849. " X, ^* r( a. m9 `5 z2 ]& k5 U: U
  850. int main(int argc, char *argv[])* v5 \0 W) P0 W, h3 N. d5 ]7 J
  851. {
    3 n7 {2 s0 a( o: q# e$ [0 r
  852.     char *subtitle_filename;
    8 E2 E7 y" o9 e+ u
  853.     FILE *subtitle_file;
    ) Q% t; W9 X" X/ i( C: ]8 \
  854.     char *inrbt_filename;
      H) ]6 y3 \1 t9 n3 g1 X
  855.     FILE *inrbt_file;
    7 S/ n- l: r/ V8 g
  856.     char *outrbt_filename;* [' _$ y7 G3 j/ m
  857.     FILE *outrbt_file;
    4 b9 H2 V0 ~9 _; ^' L) U, P
  858.     rbt_dec_context rbt;" l/ s7 [" n, L  R
  859.     int origin_x;0 p' E& g" `# m
  860.     int origin_y;
    % W% `7 N  ^- |5 V! R3 I
  861.     int window_width;+ b6 z$ X7 M0 b, H' ~6 k! M" h
  862.     int window_height;% n  d, L, V$ _$ y0 ]

  863. " V1 F: o. A" i+ U: f; S
  864.     /* testing the bit functions */2 f7 [8 d2 A$ P$ w( j. G& z
  865. #if 08 ]6 C) M2 Y6 P2 f
  866.     int i;7 l) _- F. s, K$ Z+ a& P
  867.     uint8_t bytestream[] = { 0x55, 0xAA, 0x00, 0xAA, 0x55, 0x77, 0xFF, 0x1B, 0x70, 0x8F };
    * N4 N8 `! ]5 ^( H0 N( q
  868.     int bytestream_size = 10;
    * S8 o, W" M, n! W+ t  G& d
  869.     get_bits_context gb;
    ) v) a. _9 X, \  k2 S
  870.     put_bits_context *pb;
    $ i. v$ Y# m1 O4 y
  871.     int bits;' ^  j2 n3 H6 g& m
  872. $ H/ V0 Y4 L; y
  873.     init_get_bits(&gb, bytestream, bytestream_size);
    7 L1 @5 D# K9 W  l% a; H
  874.     pb = init_put_bits();/ d% F- @, k$ n6 m& [

  875. 8 L0 y; H% i& l7 @
  876.     for (i = 1; i <= 12; i++)$ ]6 f* c7 C5 r4 [2 R2 i
  877.     {# @' @# }0 n' d: D) R) Z5 i- t: f! l
  878.         bits = view_bits(&gb, i);
    / f2 }7 b2 T( p& _) ~( H
  879.         printf("view %d bits: %d\n", i, bits);
    5 @, Y7 N" b: z2 ?$ C" d' @
  880.         printf("read %d bits: %d\n", i, read_bits(&gb, i));
    & _2 T' o3 Q' U' D9 D
  881.         put_bits(pb, bits, i);$ ?+ i1 d7 Y$ K
  882.     }& H0 g  \' A2 [; [# T) k% u
  883.     put_bits_flush(pb);
    $ w2 m- a1 u* H0 B1 ?
  884. $ h8 w" ^  Y1 M6 o$ c$ ?
  885.     printf("original bytestream:\n");
    4 Q( t# X; ]+ {3 e6 G6 r
  886.     for (i = 0; i < bytestream_size; i++). m6 U+ F; ~. K7 e- a, h- u9 A- n
  887.         printf(" %02X", bytestream[i]);
    # g( ~: C5 Z) i( ^
  888.     printf("\nnewbytestream:\n");# I# b& D$ V1 W- q
  889.     for (i = 0; i < pb->byte_index; i++)- l7 u& t+ w9 R+ \" I
  890.         printf(" %02X", pb->bytes[i]);
    - C' c+ n( `& F' L) |$ L1 z
  891.     printf("\n");
    / r. b1 I  X7 Q4 W/ d
  892. 9 m! ?6 \) W% [
  893.     delete_get_bits(&gb);
    ( F8 A  j/ j" X
  894.     free(pb);! r% @6 z/ g8 c9 @9 t* i- o' s
  895. #endif
    : f6 \3 o% _0 u* x, ]. f$ E2 y
  896. - ]6 _3 v( H3 u, I7 x4 m
  897.     /* validate the number of arguments */% g4 c5 Z/ G5 D, q! x9 ]7 w0 S
  898.     if (argc != 8 && argc != 9)
    + \& r' \4 Y4 d% U, u7 J! C
  899.     {
    " D! W/ G8 F1 x: \. }
  900.         printf("USAGE: subtitle-rbt <subtitles.ass> <in.rbt> <out.rbt> <origin X> <origin Y> <width> <height> [dump_frames]\n");
    ! Z) n1 z6 n# d, [5 x7 m7 X1 V4 [
  901.         return 1;- g8 a) y( F! [: @" h5 I
  902.     }* g& Y8 i& r+ N# G$ ~6 v
  903.     subtitle_filename = argv[1];9 I3 Z/ z$ B, ^7 q& m
  904.     inrbt_filename = argv[2];8 H! X' s! z3 }: @4 P
  905.     outrbt_filename = argv[3];2 [1 ?0 |' W! e( t! D) E/ d5 m9 \
  906.     origin_x = atoi(argv[4]);
    % ~" Y' \( m+ W9 M1 g+ C
  907.     origin_y = atoi(argv[5]);5 H# ~- C- |3 Z" u9 d, z
  908.     window_width = atoi(argv[6]);0 m, U* F! s, l. H* r: S: c
  909.     window_height = atoi(argv[7]);
    + E! r/ R& s6 s' j/ C' d
  910.     rbt.dump_frames = 0;
    6 O( f# y3 r) V6 M8 v; Y8 @* y
  911.     if (argc == 9)( m! |6 x3 I& j8 A
  912.         rbt.dump_frames = 1;% A, e5 `, ]" F5 E

  913. 0 F# g8 k3 `) x8 Q
  914.     /* verify that the specified input files are valid */
    - j! o/ I7 _; ~8 R
  915.     subtitle_file = fopen(subtitle_filename, "r");
    8 w) m9 E1 U* z' T  |  x
  916.     if (!subtitle_file)
    # e: y1 ^$ h! ?. E+ H2 Q) C
  917.     {
    1 I" O* N2 z5 V- b! f
  918.         perror(subtitle_filename);5 |/ w& p* d# ?1 B8 p2 z3 ~1 ^. ?
  919.         return 1;
    ; s- R) ^* P& e
  920.     }
    * t" n) V) F* \" ?9 W0 F
  921.     fclose(subtitle_file);
    ) j6 C3 Z7 Z1 n. [9 \+ a* e) r
  922.     inrbt_file = fopen(inrbt_filename, "rb");
    2 E# g$ J4 G' B) v
  923.     if (!inrbt_file), {' M( n/ J/ H  L) C5 T
  924.     {
    # T# R8 i$ F4 N5 |/ [, P( v" k
  925.         perror(inrbt_filename);
    ! b, l! k3 c3 n( y/ w7 Y. \2 U
  926.         return 1;6 i6 {: E% W+ m3 p& G1 i, T
  927.     }6 a3 l( {, R9 O8 s7 u
  928. 7 q3 ~7 f& _# G7 W7 O
  929.     /* initialize the subtitle support */4 H( }  g" `4 H! R/ q1 l
  930.     rbt.ass_lib = ass_library_init();; l3 {: Q* E& W# A2 B
  931.     rbt.ass_renderer = ass_renderer_init(rbt.ass_lib);
    : @9 U3 }: n# G' o9 Y
  932.     rbt.ass_track = ass_read_file(rbt.ass_lib, subtitle_filename, "UTF-8");
    / X. f1 G0 {: c/ a
  933.     ass_set_frame_size(rbt.ass_renderer, window_width, window_height);. V" h! r% L  T9 H- D
  934.     ass_set_fonts(rbt.ass_renderer, NULL, NULL, 1, NULL, 1);
    . ^0 m0 u5 w* o: z: J6 Q: d

  935. . G: X3 _* v4 x1 L+ e1 t
  936.     /* open the output file */3 o9 v8 v, r! p" r
  937.     outrbt_file = fopen(outrbt_filename, "wb");
    3 O5 W  i, U6 o9 g
  938.     if (!outrbt_file)2 y0 Z* ?0 i3 a& w5 [
  939.     {
    , }! E6 r$ u( B1 l& Z' d
  940.         perror(outrbt_filename);
    7 H# o4 C+ x  Q# k; f" t9 c$ C" V
  941.         return 1;
    8 b4 F" d: l' [" L
  942.     }
    6 L% W0 [) y, N
  943. 0 f5 P- o& n4 a/ g& P
  944.     /* transfer header from input to output */% s$ @7 c! g+ y+ M! \5 V+ i( C6 r- Q
  945.     if (!load_and_copy_rbt_header(&rbt, inrbt_file, outrbt_file))
      j+ }; H1 s/ k# F) W* Y7 A, `
  946.         return 1;2 c/ r, |% [5 B5 V. c7 s0 j6 C1 y
  947. ) o, s# D( O) V0 N2 D
  948.     /* rewrite the frames */
    ; s) y6 @$ |( E* e6 V, y/ d) `. I
  949.     if (!copy_frames(&rbt, inrbt_file, outrbt_file, origin_x, origin_y,
      A5 p7 ~9 Q/ u5 h; H4 `+ m
  950.         window_width, window_height))
    : H5 @; j. R) ~( M$ o. O
  951.         return 1;
    ' j' B5 d* `' l! H  S

  952.   y5 C- ~3 i8 m: H) w9 Y$ ~9 j
  953.     /* write the modified frame size tables back to the file */
    . {: h+ U$ @, D1 r* [* Q7 d" J
  954.     fseek(outrbt_file, rbt.video_frame_size_table_offset, SEEK_SET);; W8 ^, g! V; U4 P
  955.     fwrite(rbt.video_frame_size_table, rbt.frame_count * sizeof(uint16_t), 1, outrbt_file);; |. E0 y9 \: Q5 M; Q
  956.     fseek(outrbt_file, rbt.frame_size_table_offset, SEEK_SET);: e  q. C( V; G- p4 r) \4 Y
  957.     fwrite(rbt.frame_size_table, rbt.frame_count * sizeof(uint16_t), 1, outrbt_file);/ S: I- Y3 r& x; J
  958. & _. f" c5 X4 [9 b5 |* p* v
  959.     /* finished with files */
    3 H& R5 V8 \; u- o
  960.     fclose(inrbt_file);
    2 a1 v5 D2 N5 _9 |$ Y; }
  961.     fclose(outrbt_file);
    4 J" u5 z$ D9 c/ ~3 A  v
  962. % Q! z4 u" i' ~' m, i
  963.     /* clean up subtitle library */
    ' W# P+ b; _# i
  964.     ass_free_track(rbt.ass_track);
    ) M: Q/ B' V9 r- q) x6 b" X, }3 D$ O
  965.     ass_renderer_done(rbt.ass_renderer);
    & x/ @/ ?; R/ _, F; W5 y. K, t9 r
  966.     ass_library_done(rbt.ass_lib);
    9 X! A& e0 Q0 G5 c! B/ k

  967. ( b" X1 P: l$ R
  968.     /* clean up */& Q' {) @* _% z' M. A$ a3 J- Q
  969.     free(rbt.frame_load_buffer);
    . ?+ ?0 S. U5 N$ }3 d
  970.     free(rbt.video_frame_size_table);8 j/ F/ s# F! g$ x
  971.     free(rbt.frame_size_table);
    % Q, Z3 |9 L* _& Q$ }( {3 X( I
  972. # _7 `4 j+ I$ a1 s4 Q
  973.     return 0;/ X$ ~% [2 ^" Z8 e' [4 @6 u6 ]
  974. }
复制代码
) |2 r8 a* X, M) i' f0 A
1 n, Q6 s) J, Q$ o( [; x+ d

/ V) a. U& q& `. F! K! I( h& P5 s$ V
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 很美好很美好 很差劲很差劲
回复

使用道具 举报

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

使用道具 举报

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

使用道具 举报

5#
 楼主| 发表于 2009-11-19 17:39 | 只看该作者
引用第3楼soring123于2009-11-19 17:07发表的  :
: L; l" ]& A5 H/ l我记得是没字幕的 比较麻烦 都是视频的
' |9 k6 h; @9 n' R' U. \" t" B4 I
给视频外挂字幕方式汉化也许能行。2 B6 e" i: r' ]) c. q; T
要结合dosbox和代理dll技术。
回复 支持 反对

使用道具 举报

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

使用道具 举报

板凳
 楼主| 发表于 2009-11-19 11:38 | 只看该作者
引用第1楼soring123于2009-11-19 11:09发表的  :5 m8 a5 n" G7 \3 K  h( @( H' F5 ]
这游戏有字幕吗?
8 ^* s# R- T! l2 ^
好像没有字幕,我说的是给视频外挂字幕方式的汉化。; b, V5 i7 b2 n! m# L
就像syberia2汉化版下面那行字一样。
回复 支持 反对

使用道具 举报

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

使用道具 举报

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

本版积分规则

冒险解谜游戏中文网 ChinaAVG

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

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

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

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