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

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

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

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

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

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

本帖最后由 shane007 于 2021-1-2 13:56 编辑
( L( Q" u8 a, V+ D' P9 g. P( l5 p# q# Z" p) y4 M% X
最近找到了一些和幽魂系列Phantasmagoria 有关的资料,
$ `% R/ r4 y4 L也许将来可以用于汉化。1 B6 z' O0 W: _$ o0 w" l5 ?

3 y+ }  G" l' T- @$ r: T和日文版有关的信息
, \8 k, R$ K6 \3 u# x) Mhttp://anthonylarme.tripod.com/phantas/phintgtp.html8 O8 a  j5 v% o2 J8 s8 h' @& H
: M& t! I" W  N% I# }0 h
相关工具
( T% Q2 K' q2 w2 Ahttp://anthonylarme.tripod.com/phantas/phcheats.html  Y8 C3 Q% O. }' n" p
-----------------------------------------------------------------------
. z3 T# U( F0 H8 ^2 B* M$ T2012/1/2  更新
# s# P2 J) y$ B! x& A3 Z) H关于幽魂游戏的字幕
4 ?$ f7 a2 L$ {# y1 q0 GPhantasmagoria subtitles function discovered - ScummVM :: Forums
3 @7 O3 ]# U9 o9 P- s  W: y; f7 c4 R2 B1 B. [- j3 y5 Z, s' Y) o
VMD文件2 ?7 o7 E) W1 |& ]* x
Subtitling Sierra VMD Files | Breaking Eggs And Making Omelettes (multimedia.cx)VMD - MultimediaWiki
7 X" M5 [8 O' T0 X& l* l  h  x; A$ v/ M1 D! e; H
字幕7 g! z; t8 n2 A" x+ i% R
Subtitling Sierra RBT Files | Breaking Eggs And Making Omelettes (multimedia.cx): Q6 U! r& z. L0 {7 s: L$ k
  o2 @1 D6 c+ A7 c
FFmpeg/subtitle-rbt.c at feature/VMD_encoder · multimediamike/FFmpeg · GitHub5 V% k9 ?. x$ K; k- n  }( Y
  1. /*
    + b/ g$ t: I& P1 d, O% r3 n
  2. * subtitle-rbt.c" V( v9 o+ p- {  Z) A/ t, ^
  3. *  by Mike Melanson (mike -at- multimedia.cx)
    ( N7 C( u6 `& @8 \
  4. *
    & s- L! E' a, d! L; F# o
  5. * build with this command:- ~6 j3 Y% Q1 ?1 t0 R5 X5 y
  6. *   gcc -g -Wall subtitle-rbt.c -o subtitle-rbt -lm -lass
    8 H! M. H  H" h7 k0 a/ |: R
  7. */
    & _1 F- f# Z; ~% \) r. l9 X# v! m
  8. " b  K2 F! w/ `& O; T! d8 g# P0 j) e1 {
  9. #include <inttypes.h>
    ; S* }9 \' r( i0 z  u; a, w7 L
  10. #include <math.h>
    1 N) P2 i' S4 l/ L; [+ K  W. N# |
  11. #include <stdio.h>
    8 s+ u* p# M% ~9 u$ Y  M
  12. #include <stdlib.h>
    / C3 s5 J. k: F0 m1 C! x
  13. #include <string.h>
    5 B9 C- ^( {2 T, j, g
  14. ! a/ f; I/ ~; Y& Y0 m" _$ ]
  15. #include <ass/ass.h>
      d& S" h: n2 X# G  N. E/ \

  16. " }: L4 ]" q# K* B* s8 [
  17. #define LE_16(x) ((((uint8_t*)(x))[1] <<  8) | ((uint8_t*)(x))[0])9 T# [" \* {- U0 H& Q# s% X7 s

  18. & U8 |- @: _+ ?- Z
  19. #define LE_32(x) (((uint32_t)(((uint8_t*)(x))[3]) << 24) |  \
    ' `4 P3 a9 y* }" b$ {
  20.                              (((uint8_t*)(x))[2]  << 16) |  \0 G9 I+ p. ?6 Y( @% n- d
  21.                              (((uint8_t*)(x))[1]  <<  8) |  \: C( Y' z& S  j1 Z- O/ E$ ^% K
  22.                               ((uint8_t*)(x))[0])
    " W4 [) m( V, o" \& K
  23. 4 t0 H: ^7 s4 @' Y
  24. /*********************************************************************/2 F+ w2 j( K, `) |/ y! G

  25. , |$ ]; R+ k4 ^' u4 n
  26. /* Bit reader stuff */* v' i& y! v! ]6 |& G
  27. 1 s' {% D$ q* k. P
  28. typedef struct
    ! \! t4 ~% Z6 S/ H$ }
  29. {0 n- e8 e' A, Z+ Q' t
  30.     uint8_t *bytestream;
    2 [+ O) y% \, T. b
  31.     int bytestream_size;
      F( s) d* A( |  q7 K. q
  32.     int index;
    . |/ v- ?" Z6 r# `) a, x+ k, S6 X& D
  33.     uint32_t bits;+ @2 W0 d9 J$ I" K  r
  34.     int bits_in_buffer;
    , s8 ?7 L: k( @5 W: [
  35. } get_bits_context;4 D) S' ?3 v: X; p

  36. ( G; Y' Q* z: U; r4 P4 }+ T
  37. static inline void reload_bits(get_bits_context *gb)
    5 z$ A( a& O# m1 R* @6 z( e' ]1 |
  38. {
    1 I8 v( X9 r& S- Y' z& w7 z8 z6 I8 T
  39.     while (gb->bits_in_buffer <= 24)
    ' z. N$ Z+ t: s0 B" O
  40.     {" U7 v+ C3 R. H# Y) c  O$ w
  41.         if (gb->index < gb->bytestream_size)- V* n: c5 i! ]
  42.             gb->bits |= (gb->bytestream[gb->index++] << (24 - gb->bits_in_buffer));
    ! F6 e% ^( |! O# u5 F% _
  43.         gb->bits_in_buffer += 8;
    . e# s( \" }( {9 L3 ?
  44.     }. p1 d  p" d0 b, h- R' R. ?
  45. }/ L0 T* [2 Q$ t& A; v

  46. . ]5 {) ~; S" w
  47. static void init_get_bits(get_bits_context *gb, uint8_t *bytestream, int size)
    ' b, M, P, ?" Q
  48. {
    : U4 v" X, K4 x) w& t- K' W
  49.     gb->bytestream = malloc(size);
    & u& `1 I" r$ o9 _! Z
  50.     memcpy(gb->bytestream, bytestream, size);
    . E6 e# s% C  a/ E* g2 M; i
  51.     gb->bytestream_size = size;# H- f4 ^9 {# K) @1 T6 {$ |' c' j- N
  52.     gb->index = 0;1 {, f7 b: L7 D* }' e
  53.     gb->bits = 0;
    / c6 T) g$ q& ^8 w0 J+ ]$ k1 U
  54.     gb->bits_in_buffer = 0;
    / f, N/ S& {9 C. k' ^) `6 k
  55. : O! f! s2 g& O+ e) T
  56.     reload_bits(gb);/ G. h+ F" M' V
  57. }
    - E8 v; w+ S1 r- I! [
  58. % ~! M% U, p4 Y8 e/ P
  59. /* read bits without consuming them from the stream */6 K/ r& M5 R. s* K6 @  j
  60. static int view_bits(get_bits_context *gb, int count)! I& ?2 j% G7 k3 N* U& C
  61. {) H, n5 Y( a0 W# `2 |
  62.     if (count >= 24)
    ( _. _  y$ y3 c7 o2 j) ^
  63.         return -1;
    & ~7 Q6 R3 y' [
  64.     if (gb->bits_in_buffer < count); k/ j" R; z8 ?; t! J6 j
  65.         reload_bits(gb);5 t; O. ^3 w  T- a% R
  66.     return (gb->bits >> (32 - count));5 j! h1 ^& t. K( o  N
  67. }
    $ N5 L5 d( |; P! T

  68. # Y3 h' I5 U0 H% P7 T3 n0 _
  69. /* read and consume bits from the stream */: C, G( C5 x' r
  70. static int read_bits(get_bits_context *gb, int count)
    ; _: {: G' f% d+ b* P
  71. {
      i8 u% K2 Y+ e: B# [2 c
  72.     int value;
    , y" c$ B; G' S$ G
  73. 9 ^3 E, L1 C% v5 X- }
  74.     if (count >= 24)
    0 r1 q- E( |8 w; [# h6 d$ U- O
  75.         return -1;
    / u  N7 o. `0 l6 t$ R$ [$ R, o# p2 X9 S
  76. , j4 J! T* o4 K
  77.     value = view_bits(gb, count);8 G  Z  N# x0 `0 s6 r" g  s# d
  78.     gb->bits <<= count;
    , ]+ C" l7 ^+ V- A
  79.     gb->bits_in_buffer -= count;
      B0 E" U, R& w+ ~; x) w

  80. 0 A0 W( A  {4 [- |- n7 ^! K
  81.     return value;  M. q% p$ m, D. U( N- D5 t
  82. }/ c. M0 ?( N6 o
  83. # Z' c0 B0 M8 C$ Q
  84. static void delete_get_bits(get_bits_context *gb)9 ?9 @# h0 {- \/ i9 e% N
  85. {% I0 ^8 k, E$ r4 Y
  86.     free(gb->bytestream);
    , S1 @  F) X7 h
  87. }
    $ N+ B2 l" [; `2 N

  88. ; z  s: o% I3 u9 x/ f& j
  89. /*********************************************************************/
    - U) _4 H1 _" E: j

  90. 0 B6 c2 q5 B  W- B6 v5 ~/ r
  91. /* Bit writer stuff */
    6 z# K# z: K+ ^2 \/ z* f
  92. + ^& ~  L+ R8 C; m) z
  93. #define MAX_PUT_BITS_BYTES 63000
    - o2 L. n4 h) N- Z  J
  94. typedef struct! v4 |$ P2 e4 s! D6 R8 x0 p( ~
  95. {
    8 f3 z5 ^% ~& s0 f
  96.     uint8_t bytes[MAX_PUT_BITS_BYTES];6 W0 I' u3 c" V+ H7 H4 R9 I
  97.     int byte_index;! D3 A3 q% p# q/ s8 H# h) J
  98.     uint32_t bit_buffer;5 O! z0 {" n5 V. A
  99.     int bits_buffered;
    - D- e9 d4 Y6 m/ f0 t
  100. } put_bits_context;
    " }/ j; l# G2 z( @: {& f* h& m5 ~
  101. . s" Y/ j" M2 p; E8 L7 Z
  102. static void reset_put_bits(put_bits_context *pb)
    3 B3 y+ ^, V* p7 X7 [% n
  103. {
    8 \8 j: w" Y5 b+ f& o2 P
  104.     memset(pb->bytes, 0, MAX_PUT_BITS_BYTES);
    ( t5 x4 z0 V0 R: T
  105.     pb->byte_index = 0;1 ?& D/ s' n) {
  106.     pb->bit_buffer = 0;
    2 `7 q7 M* l- L- `& E, R7 a/ y
  107.     pb->bits_buffered = 0;6 [+ C, b- V  A, L/ l
  108. }1 f, Y" q1 Q+ |0 i' H1 A: a

  109. . C' `0 _/ I9 [4 s$ B/ f, n
  110. static put_bits_context *init_put_bits()
    3 o9 X& N# c7 ~  T: {
  111. {9 e3 I  j) h- w
  112.     put_bits_context *pb;8 K6 R; T) p; T- t" @2 H4 s5 [
  113. * |+ g- c" ~5 e8 G/ g2 U" ]
  114.     pb = malloc(sizeof(put_bits_context));
    ( m4 W! e7 N! F4 N3 m$ B( d6 J8 d1 A
  115.     reset_put_bits(pb);. x% O, j* O- y3 ^  V
  116. & Q4 k0 S- i- p& n) V0 h4 Y
  117.     return pb;
    $ b6 n: T1 g' X( S$ c/ Y# m
  118. }3 \4 H4 ?  N+ R4 Z) ?4 b3 G" j- {

  119. 7 Q# J! N( U& @
  120. static void put_bits(put_bits_context *pb, int bits, int count)9 _- {- \8 J5 n6 ?" P$ f4 {5 G1 \4 K
  121. {
    ( U" S; s' p3 ^9 x( y# u
  122.     pb->bit_buffer <<= count;8 H/ ^# p) C  o; @7 q
  123.     pb->bit_buffer |= (bits & (~(0xFFFFFFFF << count)));9 E$ G  r4 e* l0 E9 {
  124.     pb->bits_buffered += count;! g( I- @$ N( w2 T: L, o

  125. 2 N7 x  y+ O% b1 s* \, o  s
  126.     while (pb->bits_buffered >= 8)
    $ u9 n# u. j5 z1 m
  127.     {
    ; c" [; j: n3 ~! r0 Q5 V
  128.         pb->bytes[pb->byte_index++] = pb->bit_buffer >> (pb->bits_buffered - 8);
    8 Y* t, i) W0 l6 V$ X% l
  129.         pb->bit_buffer &= (~(0xFFFFFFFF << (pb->bits_buffered - 8)));6 T! ]3 ?/ ], H  P
  130.         pb->bits_buffered -= 8;
    1 G0 @. z3 A& B7 H% b
  131.     }
    2 j5 D' X$ J. Z5 r% C/ N4 g( g

  132. , ]8 }: `3 }4 X. p
  133.     if (pb->byte_index >= MAX_PUT_BITS_BYTES)# a$ z& t) k5 |
  134.     {
    + M8 @" @3 v; _. u" L
  135.         printf("HELP! Bit overflow\n");- g0 @" K8 |/ u7 I3 W( Q$ c: u2 B, }
  136.         exit(1);" `2 P! T3 N+ M2 ?
  137.     }
    + n  ~) \7 h/ X( f# M# t2 w0 l- F; F
  138. }( t' U6 D: z! ?8 A/ ^
  139. & D3 i' D; X# W7 C0 L  ?/ Q
  140. static void put_bits_flush(put_bits_context *pb)/ r* _2 |2 m( }$ v) c
  141. {  g+ Y! K; _3 p7 c' g7 X
  142.     if (pb->bits_buffered > 0). G0 `2 b+ Q' O4 i
  143.         pb->bytes[pb->byte_index++] = pb->bit_buffer << (8 - pb->bits_buffered);
    3 z( `" M' J$ `; w/ h! k
  144. }
    . \: F, o- i, `7 h. M7 Z# m  `/ j
  145. ' L) l. A3 |% e
  146. static void delete_put_bits(put_bits_context *pb)
    $ l* u9 i, C9 r
  147. {
    7 X) e+ G' ?% B( z+ Q/ |0 R7 |* R
  148.     free(pb->bytes);
    6 J& h( |) P* Q4 e
  149. }
    ! r) b" Q3 P% h

  150. . R: a/ P9 ]+ q. E
  151. /*********************************************************************/6 u/ ^# O: }( C9 d/ |, [

  152. ' J: k3 ]: v( d) e) t/ U( G) J8 E5 _
  153. /* RBT functions */
    * |) p5 R: k( U, s4 `

  154. + e$ K+ @1 o' Z
  155. #define PALETTE_COUNT 256* R+ t0 J' Y' `) T0 L7 r! D
  156. #define RBT_HEADER_SIZE 60
    " i# _4 k  `0 K
  157. #define UNKNOWN_TABLE_SIZE (1024+512)0 E: T, y; ^) V7 g) x4 [. A* G; c; Q. O
  158. #define SUBTITLE_THRESHOLD 0x700 Z5 t8 t+ c$ _3 i6 W
  159. #define MILLISECONDS_PER_FRAME 100
    2 C. [6 O3 G) |- I" l% E

  160. ' C) }  X% p* o- i
  161. /* VLC table */
    # V$ Z3 H) p- B/ L
  162. #define VLC_SIZE 4
    , S6 b2 V3 t# d5 Y- d
  163. static struct3 d  b: N4 V2 x" \( K
  164. {
      U5 _+ E+ |$ W" S* l
  165.     int count;0 W; X0 }+ Z' ]& G5 V9 ~
  166.     int value;2 F" e, B' q  K/ a
  167. } lzs_vlc_table[] =' ^/ C3 O0 A+ E
  168. {
    & r: {5 D+ _+ M
  169.     /* code length = 2 bits; value = 2 */5 M9 p1 [, _2 w/ q9 Z- ~
  170.     /* 0000 */ { 2, 2 },
    0 Z7 k9 b' p" ~2 O% b  a: f5 \4 T
  171.     /* 0001 */ { 2, 2 },7 v4 d5 `* g" \1 O1 O
  172.     /* 0010 */ { 2, 2 },
    ) s* K1 P+ E: l& u
  173.     /* 0011 */ { 2, 2 },+ @+ W9 b+ [/ l+ E# V) i# w. v! ]+ B
  174. ( _9 {, r; y8 {5 P
  175.     /* code length = 2 bits; value = 3 */' N6 _8 W* h. L
  176.     /* 0100 */ { 2, 3 },; [# \4 i9 ?. `) j' o
  177.     /* 0101 */ { 2, 3 },/ B$ O# b, q& B+ x6 x' r
  178.     /* 0110 */ { 2, 3 },
    # c8 C; Q) M# l: c9 z' g" b% _
  179.     /* 0111 */ { 2, 3 },
    8 \$ r; Z& K) H/ Q

  180. 6 r: [7 v: A- [$ V
  181.     /* code length = 2 bits; value = 4 */0 z- t  `9 b$ H8 N& k% o5 I& Q
  182.     /* 1000 */ { 2, 4 },( L1 Q! B* ]3 @. E
  183.     /* 1001 */ { 2, 4 },
    1 `5 w2 L0 Z# }9 x- Y0 A
  184.     /* 1010 */ { 2, 4 },% z9 d/ x0 X2 Q# f2 f
  185.     /* 1011 */ { 2, 4 },8 f) ~% B4 [2 e
  186. 5 D6 e2 P) L9 B- U2 @4 F
  187.     /* code length = 4 bits; value = 5 */
    ; P% g6 G: D; L8 [
  188.     /* 1100 */ { 4, 5 }," a/ q7 O1 J5 s0 `$ w+ P9 R

  189. 7 T1 k( J% i0 {2 C9 g' J4 {( \! v: D5 L
  190.     /* code length = 4 bits; value = 6 */" Y! o8 v) y, X: Z
  191.     /* 1101 */ { 4, 6 },
    6 K/ j  `% n, r1 R1 }$ F

  192. 0 n3 F9 c/ z2 j3 Y
  193.     /* code length = 4 bits; value = 7 */
    - `; Y, y) e5 b+ P4 Y8 [) h3 H0 K
  194.     /* 1110 */ { 4, 7 },: o3 f; S, \4 C/ b9 Q

  195. " w" O* C: R2 E0 A- }! L
  196.     /* special case */8 q9 V2 h8 c5 n% K* S* m
  197.     /* 1111 */ { 4, 8 }
    . x& q& Q$ f5 M; A
  198. };
    4 n* W8 E+ v) i( l( ?2 x, {2 b: Q
  199. 6 H/ w" e4 O9 X) F' [
  200. typedef struct4 k7 q7 z, D2 T1 C4 V" D+ W
  201. {
    ! r5 p' ~( h" l( |& ?- e
  202.     int version;: V+ @& r. N7 X# v
  203.     int width;
    , M0 n9 F. g7 T& u8 I6 Z% j( a
  204.     int height;
    ! b$ Q# |( r8 J/ i6 \# x" I
  205.     int frame_count;) p& l2 N" O7 {. J  ?6 ?
  206.     int audio_chunk_size;: J- j! B1 T4 i* e5 ]% _
  207.     uint8_t palette[PALETTE_COUNT * 3];7 ^) y6 e8 h: `- n/ b# _
  208.     off_t video_frame_size_table_offset;' J  ?3 p* e" ~- ^. p
  209.     uint8_t *video_frame_size_table;
    8 N; u6 J/ P% f' J, A2 ]5 G9 i  r
  210.     off_t frame_size_table_offset;6 \4 Z+ t. a, e4 L5 F' A3 }
  211.     uint8_t *frame_size_table;
    % X* A/ v$ U, D& Q; l/ J+ H
  212.     uint8_t *frame_load_buffer;
    % _9 j, P' h, @( v. B
  213.     int dump_frames;
    3 }! B! s8 B! i$ S; E& b, |
  214. / B; c0 P; X1 X$ N, i* P
  215.     /* subtitle library */
    - H$ _0 q' r) b" d# L
  216.     ASS_Library *ass_lib;* ]0 U) B; R% F/ [! O! ^/ \+ F
  217.     ASS_Renderer *ass_renderer;8 x0 F3 v. j% C% B5 j. w8 M
  218.     ASS_Track *ass_track;
    / m/ q1 g, [- B, |: h# f
  219. } rbt_dec_context;; g1 c* a2 v0 m. J5 v

  220. 2 b9 J7 z; I: h9 M  b9 b9 \
  221. static void dump_pnm_file(char *filename, rbt_dec_context *rbt,
    0 {5 n  C# j" u; a
  222.     uint8_t *image, int width, int height)0 C+ e3 a& ^) s! n: f, D$ O
  223. {
    0 [  `4 \$ I7 f# z* L) F( A
  224.     FILE *outfile;
    2 L, j+ a: C* ~$ M" @, Q0 X
  225.     uint8_t bytes[3];
    + T: ?: _1 j1 M# G$ P
  226.     int p;& D0 L) x2 s# c- W0 Y5 }
  227.     uint8_t pixel;
    % r! Z; D9 q7 I+ a) e8 I  K$ g. u8 i+ ^
  228. / N! d) h8 z+ z) p# G) x5 E6 g' c
  229.     outfile = fopen(filename, "wb");+ W( h+ H9 t) j! b: S
  230.     fprintf(outfile, "P6\n%d %d\n255\n", width, height);
    . k) K7 g! W' x
  231.     for (p = 0; p < width * height; p++)
    0 p2 X6 i+ w. [# t; d# S8 {
  232.     {3 y' V# g4 k5 i0 G# s+ I# n' O
  233.         pixel = image[p];$ [$ l# q& q, n6 A$ `
  234.         bytes[0] = rbt->palette[pixel*3+0];" q8 q- d/ h6 W" [- \
  235.         bytes[1] = rbt->palette[pixel*3+1];
    3 T7 }5 z% g9 Z( k$ r. S" {5 g' d
  236.         bytes[2] = rbt->palette[pixel*3+2];- ^0 |) ~/ G/ o# X
  237.         fwrite(bytes, 3, 1, outfile);
    . }. j- a. w1 U" U
  238.     }! |9 K% }5 G, `8 q( I8 K$ l
  239.     fclose(outfile);4 y. F7 b/ t- ?5 N  x/ l
  240. }" W8 R: `* P, k

  241. * t( G( H5 r0 p9 K, G: a
  242. static int load_and_copy_rbt_header(rbt_dec_context *rbt, FILE *inrbt_file, FILE *outrbt_file)& s" W& y  O2 j0 ^5 u3 G
  243. {' M( K' S, @; z4 k& b# j# S
  244.     uint8_t header[RBT_HEADER_SIZE];! T. |" b( z* h, V
  245.     int palette_data_size;
    + ^/ I4 l  |" |" c7 ^
  246.     uint8_t *palette_chunk;
    ( \: O! ^4 V; k& V
  247.     int unknown_chunk_size;
    - E5 @0 B  Y" `( T7 h; D
  248.     uint8_t *unknown_chunk;5 j( b! t2 }5 X$ X
  249.     uint8_t unknown_table[UNKNOWN_TABLE_SIZE];
    ) C) c. v( {# W3 ]" x
  250.     off_t padding_size;
    8 K/ ]. {, d, G
  251.     uint8_t *padding;9 z" M- U/ y& a* k6 q! ?
  252.     int i;$ }$ K! H* G7 g  ?
  253.     int frame_size;: S4 L  z2 m# n- F3 G# ^3 q8 \
  254.     int max_frame_size;
    * Q* ^7 j' S  |' |7 \1 o# @' q
  255.     int first_palette_index;) E; |. \1 o) Z% h+ W1 `3 @
  256.     int palette_count;
    # J! l# A5 i: G' a* ~# `
  257.     int palette_type;
    $ Q3 j& P% ^7 n4 R) u# @4 a9 }
  258.     int palette_index;) T7 I7 ?  Q8 w
  259. 4 I* y9 H2 k6 m$ D
  260.     fseek(inrbt_file, 0, SEEK_SET);
    9 b8 G+ `  R+ g  Y! E5 t
  261.     fseek(outrbt_file, 0, SEEK_SET);3 R% K6 a1 E1 p' _$ m8 e# G

  262. . w2 o  r5 n# A  P4 O# d3 e- j
  263.     /* load the header */! ^6 f# b8 `( D# ^1 a
  264.     if (fread(header, RBT_HEADER_SIZE, 1, inrbt_file) != 1)
    0 _- n% H1 e& @- y* c) T5 M
  265.     {" z$ s+ g& B) _
  266.         printf("problem reading initial RBT header\n");# {# b0 D4 i  W! W8 U2 V1 e
  267.         return 0;4 L0 |( o1 i( Z0 q
  268.     }& n6 n, S& b1 y7 D( @9 \1 o6 C

  269. . [1 K5 y0 X+ C
  270.     /* copy header to the output */
    ! Z. u, l8 y4 f( r
  271.     if (fwrite(header, RBT_HEADER_SIZE, 1, outrbt_file) != 1)
    / n4 T* M9 n" M
  272.     {
    0 v9 n/ C, v5 R; e6 H6 `5 \7 @5 M
  273.         printf("problem writing initial RBT header\n");/ n, a  }$ f- V! s
  274.         return 0;% m2 o9 `# F, W' s0 T! @7 D# r* `" _
  275.     }
    & \9 x! \! f. |) {

  276. ) j; A3 m0 l8 l+ Y8 u# H
  277.     rbt->version = LE_16(&header[6]);6 G& e! B. i& r: j$ z* E5 ~
  278.     rbt->audio_chunk_size = LE_16(&header[8]);0 v& x6 }- B7 O3 z4 T
  279.     rbt->frame_count = LE_16(&header[14]);  B+ E! o9 ]1 j) H) P

  280. 8 Y  k. @- C" P3 ^5 ^
  281.     /* transfer the unknown data, if it's there */
    & R: ~4 I9 I0 e0 ^! J" q6 O6 \# r* ^3 E
  282.     unknown_chunk_size = LE_16(&header[18]);. Y; k1 g- e0 K3 M  L# G6 V1 Y
  283.     if (unknown_chunk_size > 0)
    % L* f6 A" `4 R
  284.     {! X1 U1 j6 \6 h# E3 J
  285.         unknown_chunk = malloc(unknown_chunk_size);
    * B6 Z, f# A& w0 g( n
  286.         if (fread(unknown_chunk, unknown_chunk_size, 1, inrbt_file) != 1), a9 m. I8 c8 S$ o) A, Y/ f
  287.         {
    5 M4 S' @% r1 ^
  288.             printf("problem reading unknown data\n");5 z5 x+ g- v: Q7 V+ L
  289.             return 0;
    6 e* E* `/ z) \& v
  290.         }6 k* ]0 L" j+ k5 ?2 d2 e0 ?( o3 z
  291.         if (fwrite(unknown_chunk, unknown_chunk_size, 1, outrbt_file) != 1)
    - `+ u, w( z% I5 c8 f; @
  292.         {" r' W8 d1 w/ P4 h" f9 \/ Z
  293.             printf("problem writing unknown data\n");/ M4 t9 B  D' `9 L
  294.             return 0;2 ~  ^+ I# G7 N# G) Z
  295.         }  Q+ R; x5 O3 p6 b0 |
  296.         free(unknown_chunk);: I" B6 \- o5 F$ t
  297.     }$ z) u) V1 M  A4 P) T2 F4 o

  298. 2 F' y8 h( W. W5 Y% ~! L
  299.     /* transfer the palette chunk */! @" H$ s  v- b  l; s
  300.     palette_data_size = LE_16(&header[16]);) z4 b: R- E  p; R8 a. G( p- w
  301.     palette_chunk = malloc(palette_data_size);3 r# ^% t; X3 v
  302.     if (fread(palette_chunk, palette_data_size, 1, inrbt_file) != 1)
    ! P# Q) C  g- g0 ]2 i
  303.     {
    2 J- m! c  E+ l+ h  I
  304.         printf("problem reading palette\n");
    ' u% A0 J9 H& l+ x( e( G
  305.         return 0;1 M4 o+ w+ y+ d; n  b
  306.     }; E" b0 |( L4 v* N6 w
  307.     if (fwrite(palette_chunk, palette_data_size, 1, outrbt_file) != 1). Z# Y* t- S' M; n
  308.     {; d$ }+ }4 `! u! q
  309.         printf("problem writing palette\n");
    ; Z. b' G7 s: `) G, o
  310.         return 0;
    " v9 k; G0 \! F0 F4 {, n3 o
  311.     }
    % v8 S* U5 w+ k2 b
  312.     /* load the palette into the internal context */
    1 l; F  f* _8 t1 @
  313.     memset(rbt->palette, 0, PALETTE_COUNT * 3);
    7 N9 p6 C6 G: |+ Y
  314.     first_palette_index = palette_chunk[25];
    ' E6 o4 M: S9 `
  315.     palette_count = LE_16(&palette_chunk[29]);  z# q, F5 \6 d8 Z
  316.     palette_type = palette_chunk[32];
    * S4 o! ^9 o$ Q3 a1 j
  317.     palette_index = (palette_type == 0) ? 38 : 37;( K$ C2 }1 T' Z+ u: u3 g: D7 B, n& U
  318.     for (i = first_palette_index; i < first_palette_index + palette_count; i++)
    * h$ a: |5 {  {. ^5 c
  319.     {
    , g2 L1 ]4 D- S
  320.         rbt->palette[i*3+0] = palette_chunk[palette_index++];
    & I- s" E$ C6 ^( x- N
  321.         rbt->palette[i*3+1] = palette_chunk[palette_index++];
    % G7 [" D( \; A" x, j3 u
  322.         rbt->palette[i*3+2] = palette_chunk[palette_index++];$ D0 Z2 p' S( U8 o$ z8 O& @
  323.     }
    & G4 i; [+ T( u2 Y$ _: T
  324.     free(palette_chunk);' V( L% `$ @6 X8 @  _5 T
  325. 1 n% U# k2 Z( _5 [& Q# v8 z  M
  326.     /* copy the video frame size table (2 bytes per frame), as a placeholder */6 p$ n" a1 g6 T) G5 K3 ~- v8 f
  327.     rbt->video_frame_size_table = malloc(rbt->frame_count * sizeof(uint16_t));
    & o& _; p+ R- l9 f& `2 t, ?/ m7 R8 F8 e7 W
  328.     if (fread(rbt->video_frame_size_table, rbt->frame_count * sizeof(uint16_t), 1, inrbt_file) != 1)
    # p- l+ t5 j1 V5 O& X
  329.     {
    ! Q* ~; c# K) V% [6 E
  330.         printf("problem reading frame table\n");1 |. }+ u2 L$ Q  a
  331.         return 0;+ b- h( y  ~% _2 [% }7 m9 [
  332.     }5 b( I: u( [6 R' ^$ M/ e0 Z
  333.     rbt->video_frame_size_table_offset = ftell(outrbt_file);; \( l+ b" V$ L) {: m
  334.     if (fwrite(rbt->video_frame_size_table, rbt->frame_count * sizeof(uint16_t), 1, outrbt_file) != 1)
    8 m7 s6 h8 u9 O; {) X% @
  335.     {: X; ]) R2 t1 @6 a6 f8 l1 O
  336.         printf("problem writing frame table\n");
    ) E+ _7 E9 E. w8 {1 ]  F
  337.         return 0;
    & a  F( N3 g! l- j, r  r
  338.     }  F) P  Q# [3 R1 v) \
  339. % Z7 M( }& B4 W$ L* v+ ^
  340.     /* copy the frame size table (2 bytes per frame), as a placeholder */
    ; r5 S9 S4 X0 L1 i. B8 Q0 \
  341.     rbt->frame_size_table = malloc(rbt->frame_count * sizeof(uint16_t));
    % Z! x) `, L2 v: ~# l
  342.     if (fread(rbt->frame_size_table, rbt->frame_count * sizeof(uint16_t), 1, inrbt_file) != 1)' M  p( m! b. d+ ]/ V3 Y0 z& I
  343.     {+ [, B  }' f" H9 e6 t
  344.         printf("problem reading frame table\n");
    5 Q' m) g8 t- k. K9 i9 E# I7 ~
  345.         return 0;
    # O# F) o) N! y
  346.     }$ Y5 {* Z: U# O1 x3 J
  347.     rbt->frame_size_table_offset = ftell(outrbt_file);
    6 }7 u- q' C: T5 w+ f3 Y
  348.     if (fwrite(rbt->frame_size_table, rbt->frame_count * sizeof(uint16_t), 1, outrbt_file) != 1)" N9 R! w0 w  _7 t  E  A! _
  349.     {
    % ]! K. a+ q# A) [6 S
  350.         printf("problem writing frame table\n");
    8 W, H5 a' O0 U8 z; e$ \% ^
  351.         return 0;
    , h2 D, j! a$ O: E" @, t5 q+ ]1 H
  352.     }% z% F0 ~' D4 f! a1 w; G4 ^5 e4 v  _
  353. 3 u/ i: ~/ Y  r7 p% E9 ]1 `
  354.     /* find the max frame size */
    * M' S/ u3 z' j+ {8 ~* O5 t
  355.     max_frame_size = 0;
    / _5 @- }  L$ ]0 P
  356.     for (i = 0; i < rbt->frame_count; i++)
    7 c, D4 A1 L7 w7 M. D! C8 E
  357.     {
    , b* Z4 m; T8 i2 q3 ]% s
  358.         frame_size = LE_16(&rbt->frame_size_table[i*2]);
    8 V. B, F, J3 d. u: I
  359.         if (frame_size > max_frame_size)( y$ p# J8 D2 v0 f1 }
  360.             max_frame_size = frame_size;( ], @* K2 i7 t/ F% _
  361.     }5 J' a1 |2 \% F5 I
  362.     rbt->frame_load_buffer = malloc(max_frame_size);) ~9 {! F2 {8 I( ^" X
  363. ( h. u, E: h& e$ m9 h4 k% T
  364.     /* transfer the unknown table(s) */
    5 C7 l, E9 O3 T0 f/ u6 W& B
  365.     if (fread(unknown_table, UNKNOWN_TABLE_SIZE, 1, inrbt_file) != 1)
    1 e9 m9 R/ S) `* Z
  366.     {
    % B  r- _8 e) l* p, w
  367.         printf("problem reading unknown table\n");$ A6 \( ?8 q7 a+ R1 n: R
  368.         return 0;% E% _) L) M2 @2 |$ T7 o- f
  369.     }
    % _/ H4 q/ i! O" H# a
  370.     if (fwrite(unknown_table, UNKNOWN_TABLE_SIZE, 1, outrbt_file) != 1); @( `% r& _! a$ a2 ~$ F
  371.     {
    & ^; a+ I) |2 b/ g* J/ h! R
  372.         printf("problem writing unknown table\n");& E3 z% O/ Q7 i9 f8 D( ^, E# o
  373.         return 0;( ]: D4 n! a) }* ^2 M5 r
  374.     }+ p$ c6 _. b9 v2 ?! m( n

  375. ; I- l/ x& @; ~0 o
  376.     /* copy over padding */
    $ l, [# D* G$ t7 j# F6 d- T  h
  377.     padding_size = 0x800 - (ftell(inrbt_file) & 0x7FF);4 V  l1 @6 K; U# I7 h8 ~
  378.     if (padding_size)
    7 z9 Q6 i  h2 O) i# f% q+ C
  379.     {
    & U# s* O( }! X9 [
  380.         padding = malloc(padding_size);4 x' T* }7 J% ]  z
  381.         if (fread(padding, padding_size, 1, inrbt_file) != 1)
    6 T. r- [# r6 i
  382.         {: w" s+ z* G1 O( O( w
  383.             printf("problem reading padding\n");3 a+ f6 v& q( z
  384.             return 0;9 p3 P% C. r$ G
  385.         }$ L- _9 a: P4 E4 c( U- y" ?' L
  386.         if (fwrite(padding, padding_size, 1, outrbt_file) != 1)
    0 M1 r" p& l4 o
  387.         {% x4 B7 f; X( X9 m
  388.             printf("problem writing padding\n");
    2 u8 o# y$ L# Z" C: f
  389.             return 0;
    ' E: P; D! p2 r" q) D
  390.         }
    / {' N' y3 a( Q  E. C& O3 P& P) r
  391.         free(padding);
    1 a. Z/ W! i6 |" Z2 I
  392.     }
    3 t2 A$ ^5 C. @* ~9 M

  393. 8 M, F/ |5 I# B
  394.     return 1;  y7 `: w: j, C7 j* A" ^( C6 l
  395. }, U' a1 @7 s2 }3 h* F( D+ }

  396. 4 C8 d3 b' q/ h/ h* a
  397. static int get_lzs_back_ref_length(get_bits_context *gb)& k! F% W4 y* }  h8 h% `1 s% s
  398. {
    ' u/ |& a$ g: Q; q
  399.     int vlc;
    $ P, i% O) k  q7 c3 U2 w& G# c
  400.     int count;& b  E5 u  t% C9 g& @9 ^9 Y
  401.     int value;& k( K5 Z( X6 O# m
  402. ( F/ w, C3 _  [/ f# q: @4 A" r
  403.     vlc = view_bits(gb, VLC_SIZE);
    0 E6 J/ c8 r, k! D# s4 K' f  a) H8 r
  404.     count = lzs_vlc_table[vlc].count;
    $ F. q4 a8 M9 j- u4 R
  405.     value = lzs_vlc_table[vlc].value;! O; P( `' A' \* M* D2 M+ w4 j

  406. ! E) E2 }6 \0 Q. W
  407.     read_bits(gb, count);
    & l; B, Z/ y9 S3 X5 p) {
  408.     if (value == 8)9 Q& M1 C  Y2 J+ q0 k5 c
  409.     {
    " r( c8 F1 p3 g; z, [
  410.         do
    ! k: T8 i2 z6 S; K0 q: b
  411.         {
    7 d, Z( W1 ~# K8 G7 K
  412.             vlc = read_bits(gb, VLC_SIZE);+ l6 ~: b. G& t( {; d
  413.             value += vlc;4 i# s- i3 v% f
  414.         }
    0 j. c% }0 S- e1 E' D" B2 n
  415.         while (vlc == 0xF);
    $ @8 }& g$ L- X. h6 g/ A/ L
  416.     }
    , n+ ]1 V( b  h( j

  417. ( y; m6 A1 O' J$ k
  418.     return value;% r: k" X$ v: D% V4 n
  419. }0 y8 M: l' @5 O4 ]; x

  420. 8 W4 D; y( p) B0 J9 o
  421. static void compress_window(put_bits_context *pb, uint8_t *full_window,  s6 ^& n8 \: h0 _% d  g
  422.     int full_window_stride,9 T: V5 y6 i$ L  w3 z
  423.     int window_top, int window_bottom, int window_left, int window_right)! `4 b0 F8 [& ~8 A) d" q' V
  424. {
    7 Y- f" \; {# H, e3 U
  425.     int last_pixel;
    : A5 a7 H+ l! s/ X- N5 Z
  426.     int run_size;
    0 a: u. _- _/ g4 U& q# t
  427.     int x;
    1 i( f3 M$ j. T) {7 ]  O" f
  428.     int y;
    6 T/ B! A1 @( g+ N) c7 P# S
  429.     int start_index;
    * ~. w. G1 B% G- y
  430.     int end_index;: \8 p+ _. _. J7 a5 B$ @
  431.     int encode_last_run;# ~- r2 B9 d3 g- M" u" c$ I/ D

  432. 9 D' t) {% ^6 D$ m) X" P2 b5 A0 \/ ]
  433.     last_pixel = full_window[0];& k8 ^9 O+ o! b/ B/ ~7 W
  434.     run_size = 1;' z$ x  ^& M0 c; r) u9 Z
  435.     for (y = window_top; y <= window_bottom; y++)
    ' F* l6 G- y0 w5 k; a* G- Q& L
  436.     {
    1 O: F% G# V9 f6 z0 c6 v- D
  437.         start_index = y * full_window_stride + window_left;, U3 Q1 i2 A- R3 R6 a+ v" I3 h
  438.         if (y == window_top)
    / o/ q  k4 t$ f# Q, i9 j
  439.             start_index += 1;
    : _0 X  x5 Q9 C0 I
  440.         end_index = y * full_window_stride + window_right;! \8 n) h/ _$ W: Z% E
  441.         if (y == window_bottom)1 x! c: B. `7 {
  442.             encode_last_run = 1;8 c' F! Z5 P, H8 B
  443.         else; S; ?" p' I6 t
  444.             encode_last_run = 0;
    2 |. D6 m$ |8 b, U
  445.         for (x = start_index; x < end_index; x++)
    8 ~9 W. r* |' L+ d* w6 D
  446.         {
    % T1 L8 g3 v# Z5 L4 x- e
  447.             if (!encode_last_run && full_window[x] == last_pixel)9 O  m# A  N  j
  448.                 run_size++;
    4 n, I+ }9 \, G0 `+ R
  449.             else
    0 Z( X" ^5 c( u2 X1 ~' r
  450.             {1 Q' ~* F) j/ Z$ ~
  451.                 if (run_size == 1)0 L5 m; a% {; E
  452.                 {
    9 \) S. ]6 b9 P7 B0 d+ Q- J
  453.                     /* encode a 0 bit followed by raw pixel byte */
    ' R! I3 j- C6 I% Q
  454.                     put_bits(pb, 0, 1);
    - B6 q8 T1 X) p+ X  e
  455.                     put_bits(pb, last_pixel, 8);
    : ^- G& j, c/ c9 p* T
  456.                 }
    & i$ x$ P" [# D) p$ x/ F
  457.                 else if (run_size == 2)
      C$ d; K# f0 c1 u
  458.                 {
    / ^8 L/ T" E* C. a: K, s
  459.                     /* encode a 0 bit followed by raw pixel byte */
    7 C+ l' Q" f* ~0 E! T* @
  460.                     put_bits(pb, 0, 1);
    " e' o! q$ J4 h& b, q. G( w
  461.                     put_bits(pb, last_pixel, 8);
    5 j$ y) j; e3 c9 B( V- `
  462.                     put_bits(pb, 0, 1);
    9 R5 V' H# u% r) j% d
  463.                     put_bits(pb, last_pixel, 8);
    % X6 Q# m( `) Q4 |4 v
  464.                 }  h3 `& M& O8 X0 t9 {! w
  465.                 else
    0 q! Y% A6 r& ?
  466.                 {
    % X) G/ ~2 E0 h3 @3 f$ ?; E+ W
  467.                     /* encode a 0 bit followed by raw pixel byte */4 P2 Q0 T1 o8 X7 @
  468.                     put_bits(pb, 0, 1);; @! A7 P0 I4 _: c* }6 `, @+ n
  469.                     put_bits(pb, last_pixel, 8);- L9 G* \$ C0 [5 h
  470.                     run_size--;) M6 C( }% _5 u8 Y& r( R
  471.                     /* encode a run: a 1 bit, followed by a back reference
    2 }+ q$ @2 e" J1 q" M
  472.                      * offset (-1), followed by a length */) d+ _7 h8 s/ K% d; B. l2 w
  473.                     put_bits(pb, 1, 1);  c- U: H9 G, @1 D! e
  474.                     put_bits(pb, 1, 1);  /* 1 = 7-bit offset */
    # \, p. M  _. _# n$ ]3 R4 }
  475.                     put_bits(pb, 1, 7);& U' _/ i( R9 G7 I0 y8 n6 k
  476.                     if (run_size <= 4)- o, c) {* w+ ]2 o+ \" [( D. P
  477.                     {( P9 w  \' C: K
  478.                         /* lengths 2, 3, and 4 are 2 bits */. M. p7 e  I; [, }2 y
  479.                         put_bits(pb, run_size - 2, 2);
    4 @: ^& a/ u( n3 r8 k
  480.                     }* m& w. A4 H/ H/ N) H/ K+ V  D
  481.                     else if (run_size <= 7)
    3 k/ G. W) a3 d
  482.                     {
    ! \) k' H1 n8 D9 y
  483.                         /* lengths 5, 6, and 7 are 4 bits */
    - G3 }0 F+ H. l$ T2 Z$ T5 ?6 }8 [7 J) q
  484.                         put_bits(pb, run_size + 7, 4);) g4 b$ K* u. _) u' O- Q
  485.                     }
    5 T# H( Z$ a/ G8 `+ ^
  486.                     else
    0 H% q2 b4 y" M' `3 K
  487.                     {
    7 ]  ^- c7 o* D% W/ I
  488.                         /* arbitrary length; start by encoding 0xF which
    3 O7 b9 y4 W3 d( K
  489.                          * stands in for an initial version of 8 */
    6 M7 ^/ a" T1 o( }- s. j8 H
  490.                         put_bits(pb, 0xF, 4);
    + K8 ^' ]; X8 c* ^9 b# x
  491.                         run_size -= 8;
    ; I& D. y& w8 B9 X8 J1 Z/ ~
  492. 9 {. n. }. O/ U! Z) }( d0 I. Q
  493.                         /* encode blocks of 4 bits until run_size is 0 */4 e! I0 m+ p# P$ P, ?1 c* S" t4 Q# D
  494.                         while (run_size >= 0)
    " p  c; J* B2 L- V
  495.                         {
    % T  D+ {7 i# H* ^
  496.                             if (run_size >= 15)9 Y& o6 ]8 @1 r: ~# D
  497.                             {
    " p( c" |7 t0 L5 D) P% h9 W2 N
  498.                                 put_bits(pb, 0xF, 4);
    " h4 Q: `$ s, S. V2 h5 f
  499.                                 run_size -= 0xF;" U; A4 [8 l& S7 X6 p2 d, ~
  500.                             }
    0 L$ ]) m& l/ Z! M! A
  501.                             else7 j6 l9 f6 {* }7 r% G/ R
  502.                             {3 e" u0 ^2 u- O6 Y0 Y- ^  o+ q
  503.                                 put_bits(pb, run_size, 4);( L" q  J0 z- w* o% M; L' c
  504.                                 run_size = -1;8 J- e) u) y" t$ o' A
  505.                             }
    6 u* |( m9 V) q( k/ u& x
  506.                         }
    * S; `* @8 g& \5 u
  507.                     }" w; o$ p$ Z6 T* T
  508.                 }
    ( N; i, @7 F9 q4 U. V1 b! d
  509. + F+ m# `) z. H/ ~( f
  510.                 last_pixel = full_window[x];
    7 n2 }; a' f2 {" e* j: {
  511.                 run_size = 1;+ O4 E1 G# C! v+ v- A/ G2 Q

  512. 4 |) N1 n& g5 W! B
  513.                 /* this single x iteration was only here to close the final run */
      f- c& O1 t6 M! P
  514.                 if (y == window_bottom)
    4 t; g  N9 K6 p3 e; M& n8 q
  515.                     break;
    . j* l1 E4 l4 ]# u. w
  516.             }
    $ E) ]$ G& B, a0 @
  517.         }, B8 K# Y$ X3 r
  518.     }) y" ^* t5 C( ~5 W
  519. 8 }) ]1 h7 O+ o, V" \
  520.     /* close the bitstream by encoding a back reference with length 0 */5 Q$ y5 o4 t3 L3 s  n# s: F% O4 K( _
  521.     put_bits(pb, 1, 1);  /* back reference run */" N  Y2 ~" k$ H7 b- ^
  522.     put_bits(pb, 1, 1);  /* 1 = 7-bit offset */6 x: {- O! b! k, \# g" }9 S( ]
  523.     put_bits(pb, 0, 7);  /* length 0 */
      R6 f4 f) x1 K6 G& H3 y( R
  524. 3 M7 z3 P8 W7 S/ u
  525.     put_bits_flush(pb);
    ; }" _& p6 q8 ^
  526. }3 p6 V) G! A; G* ~% o% j$ {3 _
  527. 6 z  _, K7 Z# E
  528. /* compute Euclidean distance between an RGB color and the desired target */5 m1 h: Z2 n) ]& x6 q  k& h
  529. static int compute_rgb_distance(int r1, int r2, int g1, int g2, int b1, int b2)
    " x4 u8 M" S5 T# P& h
  530. {
    : o- O( a6 M' k' [8 c
  531.     return sqrt((r1 - r2) * (r1 - r2) +
    / j+ h2 O4 i: Q( E
  532.                 (g1 - g2) * (g1 - g2) +; v: M2 v  d3 x0 j  z
  533.                 (b1 - b2) * (b1 - b2));
    / h0 b2 f# s1 P5 J  l
  534. }$ ?: F- w0 |. n1 N1 F- V
  535. # H  o9 U3 `! G0 m; B' u$ v1 U& S& h
  536. static uint8_t find_nearest_color(rbt_dec_context *rbt, int r, int g, int b)
    . C5 d8 S1 M8 h
  537. {
    - T2 F1 O+ a1 o' c( B7 U
  538.     int i;3 U3 H6 C% G$ S( N3 @) Z
  539.     int nearest_distance;- [  N8 z( Y) J$ i0 O
  540.     int distance;
    1 l: X: H( r* l/ ]
  541.     int rp;( d0 w4 g3 w" a! b; T; s1 B1 M! p# `
  542.     int gp;* W8 \$ B2 v3 I) `8 j- v1 \- f  p$ ~
  543.     int bp;" G. F4 X2 t8 I; i" Z5 r% f
  544.     uint8_t palette_index;
    * I9 _! I$ G6 H1 I$ P& \
  545. - u$ W! i4 r+ L8 A" e( c" E2 j
  546.     nearest_distance = 999999999;7 B/ M& {( P  D3 v  m! M
  547.     palette_index = 0;9 u& `, |( ~; D2 }: \
  548.     for (i = 0; i < 256; i++)
    . S% U  @9 G) J
  549.     {
    . O6 [3 o: g1 B5 ^$ k- c4 c. Y
  550.         rp = rbt->palette[i * 3 + 0];: Y6 Z' J% Y. t6 G7 U! d
  551.         gp = rbt->palette[i * 3 + 1];
    8 _# _4 i# g9 S; C8 U+ Y  v7 @3 R
  552.         bp = rbt->palette[i * 3 + 2];4 p/ D  ~! P3 Z- w+ [' p; @
  553.         distance = compute_rgb_distance(r, rp, g, gp, b, bp);
    7 h5 P6 R0 g3 p, r4 A7 c: q
  554.         if (distance < nearest_distance)( g' G) p5 m7 e# I2 T
  555.         {
    3 v6 R6 R  F' k
  556.             nearest_distance = distance;
    & T" M; Y" z1 f8 g+ W
  557.             palette_index = i;# H& d) I' ?6 Y
  558.         }: ~$ P1 Q5 u. A* `2 F# h
  559.         /* can't get closer than 0; break early */
    0 U9 J$ Z6 E7 F! b& C, Z
  560.         if (distance == 0)
    3 i! F! Q6 |* N8 y& @+ E" a& R/ g
  561.             break;
    * Q& i* s  R& F, b' t. V: E
  562.     }
    7 m5 Z! N* X$ ?' c" @! @" d/ y

  563. 6 `# F, m% v$ q
  564.     return palette_index;1 \9 k) B5 m% {' `9 B
  565. }# i1 G1 [3 r; b+ a2 E
  566. - N  [4 P6 S2 h/ k9 \+ S
  567. static void subtitle_frame(rbt_dec_context *rbt, uint8_t *frame,
    5 h$ A( h! k. `' _7 H
  568.     int width, int height, int timestamp)
    : y8 Q$ K+ {8 y: J4 U
  569. {
    + a/ ]4 Y# z; l+ p( ^2 C1 f/ ~& `. @
  570.     ASS_Image *subtitles;
    ! h4 P; T% q, P" a
  571.     int detect_change;
    7 v( P, k, m6 T) E; t, @# A
  572.     uint8_t subtitle_pixel;
    " I7 N% q6 J' c% K1 g
  573.     int x, y;
    + k0 s" I7 k" v( H  u
  574.     uint8_t *frame_ptr;6 A9 I. C4 P& ]
  575.     uint8_t *subtitle_ptr;
    5 w1 k4 z; `  G2 O: ?9 a
  576. & F, ~2 i3 `; W3 ^, M4 T
  577.     /* ask library for the subtitle for this timestamp */2 F" T# S, R1 I, y( [
  578.     subtitles = ass_render_frame(rbt->ass_renderer, rbt->ass_track,; h% H; f  m- `8 j* q6 O) S
  579.         timestamp, &detect_change);
    & _! |: y: k! Z* I
  580. 4 N# m& a* b+ Q$ x7 R0 E0 T1 o* p. b. V8 R
  581.     /* render the list of subtitles onto the decoded frame */
    2 F; q9 k1 ]4 m0 ]  H
  582.     while (subtitles)
    - j! y/ y, T  s/ m: x
  583.     {
    $ {7 E9 P% ~' w; ?* t: Q1 F
  584.         /* palette components are only 6 bits, so shift an extra 2
    8 A" ]( G5 o6 `: m3 }/ B; _! _5 `  w
  585.          * bits off each component */
    5 m2 c% w7 S5 n8 L) M% X, [
  586.         subtitle_pixel = find_nearest_color(rbt,, K1 |. l' @8 D' u* y
  587.             (subtitles->color >> 10) & 0xFF,2 U# l  O/ l0 p1 d
  588.             (subtitles->color >> 18) & 0xFF,4 q. {. J1 x+ d2 ]+ J' O
  589.             (subtitles->color >> 26) & 0xFF);# c: z$ y0 U8 ~3 L7 f+ P, \" z
  590.         for (y = 0; y < subtitles->h; y++)3 ?* Y! k/ k" q
  591.         {* \! ^! N- ]2 o- z! @
  592.             subtitle_ptr = &subtitles->bitmap[y * subtitles->stride];
    " y* \* o. }. ^
  593.             frame_ptr = &frame[(subtitles->dst_y + y) * width + subtitles->dst_x];
    / {& T7 Q- J& Z) J5 |5 U
  594.             for (x = 0; x < subtitles->w; x++, frame_ptr++, subtitle_ptr++)' K% X# Y& y, q2 V$ S7 H# b3 V
  595.             {
    % W' g2 \2 T" [% L! q
  596.                 if (*subtitle_ptr >= SUBTITLE_THRESHOLD)8 z* I% h& s& M% x( ^& C0 j
  597.                     *frame_ptr = subtitle_pixel;
    / D( L2 U0 U9 T1 G; G
  598.             }
    & x' r3 h* h' h9 M  f+ g
  599.         }
    ) E3 d% G+ s5 J9 ~
  600.         subtitles = subtitles->next;! E6 G: w0 k/ n4 M- T
  601.     }. G5 f; h# N6 n4 o
  602. }2 t! S/ K- f1 {. b" M

  603. + ^2 B/ }) I1 p* [
  604. static int copy_frames(rbt_dec_context *rbt, FILE *inrbt_file, FILE *outrbt_file,
    & V# Q, F. L3 S" j+ _
  605.     int origin_x, int origin_y, int window_width, int window_height)
    5 s6 _( {0 R$ n
  606. {
    + y  j$ H- h8 f+ P/ T, i
  607.     int i;
    ; o* o) Y. w# w( A2 P
  608.     int j;
    . v2 s' h; o4 J, {7 y/ s$ `* N
  609.     int scale;
    6 o7 M2 m" A7 Q7 R8 B8 ?) y
  610.     int width;
    8 L# s  N4 {; X! m) v
  611.     int height;) h' L) b5 p+ [% H
  612.     int max_width;6 C4 [3 R9 J7 P/ Q, j
  613.     int max_height;
    * Z( K1 `) [# b. b: @
  614.     int frame_x;
    3 D* Y) K0 G% I/ O) C& |
  615.     int frame_y;
    % {2 N0 H- T6 f% Q! z- D
  616.     int fragment_count;. t+ ?! Z; W) E9 |1 l: k9 Z/ o/ G
  617.     int decoded_size;" f0 H# d- O2 |' o- E
  618.     uint8_t *decoded_frame;: j, c6 |, b! N0 Z
  619.     int fragment;  f' o* Q8 b/ Y# [+ e, z) |) M3 R
  620.     int fragment_compressed_size;
    . B7 H" p! g8 Q; c5 w8 t( K3 P
  621.     int fragment_decompressed_size;
    5 t0 T, z) \- l* o
  622.     int compression_type;
    9 ]# A! @6 w! K
  623.     int index;! i2 s; }& i" z5 N- \: g
  624.     int out_index;3 K5 R0 u$ ]/ j0 k1 |% a
  625.     get_bits_context gb;( C' ]( E0 W- v8 \6 j# R
  626.     int frame_size;& D$ r, r' J3 `1 ?, T
  627.     int video_frame_size;5 Q4 y. A+ f0 q+ T+ \# E3 o' @5 S' J. n
  628.     int audio_frame_size;
    ; v/ @" E" o( A- h) v7 ]8 [$ B
  629. 8 z; H& i, M2 y2 t4 v& W  ~3 |) \
  630.     int back_ref_offset_type;) s% @# e# v5 V* o" F0 m3 x  _9 b
  631.     int back_ref_offset;
    # v& B1 J- P6 H: }
  632.     int back_ref_length;6 }( {3 y# c9 J; I* c
  633.     int back_ref_start;
    ; N# z# F1 Q  O/ W* X
  634.     int back_ref_end;! H. O  l' O2 p* k( i
  635. 9 Z% z7 c/ u3 J; J
  636.     uint8_t *full_window;# C" T- E% U5 ^7 D" O5 i: U: d$ N/ R( h
  637.     int full_window_size;' R- f! y5 i6 k! R  Z
  638.     int y;
    3 F- {0 M: G" S! z, z3 {
  639.     int window_top;
    0 c$ V% }5 j% `5 |, \& H! Z) ?
  640.     int window_bottom;* X+ K7 m3 i* P
  641.     int window_left;2 p3 d! i% n  I1 O) p& D
  642.     int window_right;
    $ o6 W" `8 H3 p' `
  643.     int window_size;
    2 Y( S4 R' a1 w; ?) r( w$ x
  644. # Q1 r* s! T: n8 F7 ?
  645.     char filename[30];% C" q* _, H, W/ i- U/ T

  646. 4 S* ?1 t5 a0 y6 c' P, g5 b. v
  647.     put_bits_context *pb;" W$ }+ l; g7 G7 ^3 J

  648. * I" }; Q" e4 i( H) ^% B0 G
  649.     full_window_size = window_width * window_height;0 i/ D3 j. x/ l0 o0 j
  650.     full_window = malloc(full_window_size);
    6 ~0 N. O/ O3 |  n: o: ?9 ^8 S
  651.     pb = init_put_bits();0 {) F/ T) R4 a0 V/ t7 x# D- l

  652. 0 G. H8 S4 I5 b  Z: S
  653.     max_width = 0;5 o) u% X& \% s
  654.     max_height = 0;0 i+ @0 G. M* G7 e2 n; @
  655. ( j2 \/ r5 u8 Q  L* R8 b
  656.     for (i = 0; i < rbt->frame_count; i++)
    # i+ q: e5 o7 u2 @* S9 ^: v+ {
  657.     {9 O1 I) h0 K6 M4 q0 \9 H8 n3 }1 \
  658.         /* read the entire frame (includes audio and video) *// U" R" u1 o& u8 T. K0 ?: _6 N
  659.         frame_size = LE_16(&rbt->frame_size_table[i*2]);6 q  V2 Z5 X# c
  660.         video_frame_size = LE_16(&rbt->video_frame_size_table[i*2]);1 M9 t; T7 I1 I
  661.         audio_frame_size = frame_size - video_frame_size;
    : J; F9 M" W* m# E: m7 ?
  662.         if (fread(rbt->frame_load_buffer, frame_size, 1, inrbt_file) != 1)
    3 P# E7 G" r5 Z7 ]
  663.         {
    $ F% f5 \$ B7 J+ m
  664.             printf("problem reading frame %d\n", i);
    8 _% a( z6 b) I. @* v  y, [
  665.             return 0;# v: b3 w, J. ^8 B6 M5 K
  666.         }* Q- L' {& ]. n: Z/ e' Z, |

  667. 0 m8 q* l2 w. E% t! x) h
  668.         scale = rbt->frame_load_buffer[3];
      U3 U8 R3 S' f* i* d: ?* [9 \
  669.         width = LE_16(&rbt->frame_load_buffer[4]);
    ' M# J) k! H- ?- ?
  670.         if (max_width < width)
    ' ?& i/ K: i' l5 ]; X
  671.             max_width = width;
    ; C0 x  W( p( h$ s9 d5 q4 L
  672.         if (max_height < height)1 E6 B: g( G9 d) {2 P6 f: u
  673.             max_height = height;* t8 J/ a8 K7 f- p5 z, R
  674.         height = LE_16(&rbt->frame_load_buffer[6]);" x0 O( M" N, t, V& s
  675.         frame_x = LE_16(&rbt->frame_load_buffer[12]);
    5 k( Z& b$ w8 b' ^7 N
  676.         frame_y = LE_16(&rbt->frame_load_buffer[14]);+ f) k0 X( M: w( F& j; V8 A  I
  677.         fragment_count = LE_16(&rbt->frame_load_buffer[18]);
    " B% Z/ u2 ]( x, F
  678.         decoded_size = width * height;+ s6 R, c' f% y6 Q' n
  679. / x* {9 w3 r! Z( B) 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);
    - I7 f, A: E2 u  |& p

  681. 5 f  e8 W4 l6 K1 `% r! c
  682.         /* decode the frame */
    3 [4 C( [0 N. A. J' [2 G4 r) ^
  683.         decoded_frame = malloc(decoded_size);3 S+ ?2 v6 j7 R, y/ f3 }7 x& C
  684.         index = 24;
    ) y3 Z  ^' c2 ~6 \& l
  685.         out_index = 0;- k" {: t% i1 r8 S3 S; R7 U
  686.         for (fragment = 0; fragment < fragment_count; fragment++)
    " r# z" z9 U) E
  687.         {9 ?  A! j. |% d9 z5 C- b5 j; y$ r! |
  688.             fragment_compressed_size = LE_32(&rbt->frame_load_buffer[index]);
    0 {4 T7 n/ z6 e3 E3 V- H
  689.             index += 4;
    8 m2 _, T9 l$ z2 N8 ^& v4 E1 }4 ^
  690.             fragment_decompressed_size = LE_32(&rbt->frame_load_buffer[index]);
    4 P7 ]% ~) T  P9 H8 t) {
  691.             index += 4;
    9 r. M( g  j2 `+ q2 i5 }& B
  692.             compression_type = LE_16(&rbt->frame_load_buffer[index]);" x; S* G' z3 }7 n
  693.             index += 2;2 I) v4 O" Z$ a4 A* ~8 x" n. G

  694. ' x! O4 K9 E: B, y
  695.             if (compression_type == 0), k# e6 M5 i1 Y# h8 R+ H1 o/ D
  696.             {) k4 ], b: B. `* s% y1 i2 e
  697.                 init_get_bits(&gb, &rbt->frame_load_buffer[index],
    , v9 M) N* X6 }" D9 v
  698.                     fragment_compressed_size);
    0 t: C% J% r6 n! ]# N* F
  699. 5 j$ V! V' l/ m1 U5 g
  700.                 while (out_index < fragment_decompressed_size)
    4 H/ ~' x# x6 J
  701.                 {0 j, i4 N0 O1 x! u) v5 _
  702.                     if (read_bits(&gb, 1))/ A7 A1 @% y; n( ?; Q
  703.                     {
    8 @; D* d) ^3 A' T! \' Z
  704.                         /* decode back reference offset type */7 X6 u  z2 _6 }$ A: b, |
  705.                         back_ref_offset_type = read_bits(&gb, 1);( }' W) S6 n9 C/ U) J1 O4 l
  706. 4 C+ E+ p  \2 `) N/ i  o( d
  707.                         /* back reference offset is 7 or 11 bits */
    ( [6 K( M1 C9 e2 a- G0 X
  708.                         back_ref_offset = read_bits(&gb,; N# c% n5 a3 q- R4 v
  709.                             (back_ref_offset_type) ? 7 : 11);
    * i; i4 L/ t: o- O, D0 d  ]

  710. , [; d& Z* e& Z6 `( e8 {
  711.                         /* get the length of the back reference */1 N" l8 v5 ?+ y  D
  712.                         back_ref_length = get_lzs_back_ref_length(&gb);5 v( j8 z/ Z8 A4 q
  713.                         back_ref_start = out_index - back_ref_offset;9 ]! _/ @" X! ~! x0 Y
  714.                         back_ref_end = back_ref_start + back_ref_length;/ i& s$ k: e9 S& M. l% k

  715. ' D+ Y! s5 }7 j. a8 k' n! D
  716.                         /* copy the back reference, byte by byte */
    : K5 N" z4 b' M% Q* J! x: r6 \
  717.                         for (j = back_ref_start; j < back_ref_end; j++)/ [8 K2 t% F6 ^! m, Q
  718.                             decoded_frame[out_index++] = decoded_frame[j];
    3 @/ K7 [2 G- G& Q  n
  719.                     }1 ]( Q. [( b& f: r  m* B8 G0 i
  720.                     else; |( B, \1 @: z+ x/ c: H2 }3 V
  721.                     {# M3 E2 v! K1 ~" y. x, m$ g
  722.                         /* read raw pixel byte */
    1 y  {: K  l4 ~: @6 z! @
  723.                         decoded_frame[out_index++] = read_bits(&gb, 8) & 0xFF;
    . l4 y* W1 \' z7 H% a! _
  724.                     }4 Q$ y0 @3 w- V* C7 j6 x+ ~
  725.                 }
    & ?7 F2 W1 s  C& |6 u. y6 i% S
  726. 0 g$ d% O4 ]" x; [/ s
  727.                 delete_get_bits(&gb);
    % x# \; q7 ?( ?6 k/ h' Q9 D9 |
  728.             }+ b' S( N* X% g- z

  729. ( V5 G" Q; w7 K# @& Z
  730.             /* next fragment */( D* K8 g. S. t- w7 V6 E2 p
  731.             index += fragment_compressed_size;
    + e2 i% `, m2 K- g( }
  732.         }
    1 w  b- i7 y) \* v7 |/ L

  733. . V4 J# h5 Y9 O) I2 f" Y9 Y
  734.         if (rbt->dump_frames)7 u$ q0 p) h* x, r* r
  735.         {6 `  Y; N) p4 ^) C( }
  736.             /* dump the original frame */7 e( B5 N) {. ^2 {6 m, X; j& B) p
  737.             sprintf(filename, "original-frame-%03d.pnm", i);: x8 u; @. D4 A
  738.             dump_pnm_file(filename, rbt, decoded_frame, width, height);
    2 h4 ^! t# ?1 {' O* e1 ~
  739.         }  }  p4 {4 |1 P! H

  740. 0 f0 F4 b, ~" i( n+ {1 [9 N! Y0 Z! u
  741.         /* transfer the image onto the frame window */: _8 b, k3 v* u" M0 r
  742.         memset(full_window, 0xFF, full_window_size);
    6 i3 U8 n' G2 h# P- Z
  743.         index = 0;
    + x' L! g7 T2 j8 O. a
  744.         for (y = 0; y < height; y++)
    8 f4 W- n4 N2 P
  745.         {( h1 d% h& K! o
  746.             out_index = window_width * (frame_y + y) + frame_x;( V. U+ `0 F$ m5 Z% A% R) I2 V( J
  747.             memcpy(&full_window[out_index], &decoded_frame[index], width);
    # v3 t/ d- j0 l3 I0 f/ l, w( _
  748.             index += width;0 ^1 Y! c& h& {: w
  749.         }
    ( ~0 `3 T/ Q0 J5 [  p, d2 `
  750. 4 N" w( H0 ]! t7 b: T3 g3 i
  751.         /* write the subtitle */
    1 ?  r: e; N7 B  A) U; t% k9 X5 x
  752.         subtitle_frame(rbt, full_window, window_width, window_height,
    - q; S9 o$ V4 P) n; g
  753.             i * MILLISECONDS_PER_FRAME);2 k; U0 n  S; S* y" D4 U: [  z
  754. 3 L! p4 y( B8 y- f$ @
  755.         /* figure out the smallest change window */
    2 i6 f1 M. s& g/ C3 ]  f: D. F$ ?
  756.         window_top = frame_y;- I! l0 C: S- |( z* h1 T+ j; U3 G
  757.         window_bottom = window_height;, G. u/ N8 j, @+ k1 }- t
  758.         window_left = 0;. }' b+ ~; h! _/ u! l( l2 C
  759.         window_right = window_width;
    ( r  k5 |4 a& q+ S3 L1 F5 q9 `, a
  760.         window_size = (window_right - window_left) * (window_bottom - window_top);
    8 @: a0 d+ K7 j, P3 }! d0 h. Q

  761. ) q9 n% V8 L# e& _2 y
  762.         /* compress the frame */
    6 s  H+ a7 {% Y" F9 }5 G- W
  763.         reset_put_bits(pb);
    1 ?5 J2 L4 |9 P
  764.         compress_window(pb, full_window, window_width, window_top,7 R* P( u# n4 S3 t  ?. \( m
  765.             window_bottom, window_left, window_right);. Z: R7 b- b8 i3 X# x

  766. ! n# a& M! L6 J+ Y. p3 U5 }6 Y
  767.         if (rbt->dump_frames)
    2 Z. w) R, B# A( ^
  768.         {3 Q! ^4 Z" m7 o6 E( R& B/ l
  769.             /* dump the frame plotted onto the full window prior to encoding,
    3 W0 \5 O" u" Y6 b6 Q. `. [
  770.              * with subtitle */
    3 B# W3 i) o! y, [* o
  771.             sprintf(filename, "pre-encoding-frame-%03d.pnm", i);5 A5 ?5 K+ N" H7 d& P4 r
  772.             dump_pnm_file(filename, rbt, full_window, window_width, window_height);& R# \' ^  s1 I+ Z5 K2 X0 _
  773.         }+ ~, }' j' R$ ?9 Y( O( ~: c" A

  774. $ B* |- V1 a4 ]2 z
  775.         free(decoded_frame);
    1 U% _: B6 k9 K' n7 _8 s+ e# x) q% B

  776. 2 F! o6 \5 q% I5 A0 L! p, P5 Y: F
  777.         /* update the frame header */# I( T  r7 Q! R. Q) f2 o( e
  778.         /* width */. ?% b( J; O" u2 V
  779.         rbt->frame_load_buffer[4] = (window_right - window_left) & 0xFF;
    ' \9 A, ^  G0 g. d0 D4 k
  780.         rbt->frame_load_buffer[5] = (window_right - window_left) >> 8;* P6 |% U4 I4 q  R7 p
  781.         /* height */# A8 c$ U8 m3 e1 ^( [0 z
  782.         rbt->frame_load_buffer[6] = (window_bottom - window_top) & 0xFF;. \2 v; D4 o& F6 \8 `
  783.         rbt->frame_load_buffer[7] = (window_bottom - window_top) >> 8;
    % c  Z  P0 A4 M! D7 O
  784.         /* origin X */2 J; [! R/ v* x7 ^# @
  785.         rbt->frame_load_buffer[12] = window_left & 0xFF;
    ( f' Q8 P/ f7 n+ z
  786.         rbt->frame_load_buffer[13] = window_left >> 8;
    % C, g! q' L% h5 A. L
  787.         /* origin Y */
    + ^; f3 N2 _# w  _3 T7 R2 |( R
  788.         rbt->frame_load_buffer[14] = window_top & 0xFF;
    3 x+ g  w/ S- `0 \. m
  789.         rbt->frame_load_buffer[15] = window_top >> 8;: s, e( V+ ^% j2 a, F
  790.         /* fragment payload size */8 v* O2 v1 E" Z4 q
  791.         rbt->frame_load_buffer[16] = (pb->byte_index + 10) & 0xFF;, {& N; w) y! C) `0 L
  792.         rbt->frame_load_buffer[17] = (pb->byte_index + 10) >> 8;
    ( T9 b% Q' j- ?* f3 k
  793.         /* fragment count (1) */
    9 e( g6 H; C( P/ [; W- G" W  F
  794.         rbt->frame_load_buffer[18] = 1;+ U, z: t& x( f. D7 L2 h
  795.         rbt->frame_load_buffer[19] = 0;& p6 A1 G! Z8 G6 H

  796. 2 U# \! m5 p* w9 n( Z  \
  797.         /* update the fragment header */1 j$ s' C- e3 C
  798.         /* compressed size */6 j- R8 p! d: D0 q, x8 Y
  799.         rbt->frame_load_buffer[24 + 0] = (pb->byte_index >>  0) & 0xFF;
    # n5 J3 z; L2 M
  800.         rbt->frame_load_buffer[24 + 1] = (pb->byte_index >>  8) & 0xFF;, c  [" U; H* `# L0 C3 L! |+ z
  801.         rbt->frame_load_buffer[24 + 2] = (pb->byte_index >> 16) & 0xFF;- G! ~$ q# M) Z# J* s. o
  802.         rbt->frame_load_buffer[24 + 3] = (pb->byte_index >> 24) & 0xFF;
    & L. B' z. U' M9 ]6 r
  803.         /* decompressed size */# R  n  P8 `7 z" @% {+ Y
  804.         rbt->frame_load_buffer[24 + 4] = (window_size >>  0) & 0xFF;% ~. e9 b1 O- t. X
  805.         rbt->frame_load_buffer[24 + 5] = (window_size >>  8) & 0xFF;( G' Y# z- i1 s( j6 G' [7 O
  806.         rbt->frame_load_buffer[24 + 6] = (window_size >> 16) & 0xFF;, P8 F; }3 m" s; _) G% _
  807.         rbt->frame_load_buffer[24 + 7] = (window_size >> 24) & 0xFF;% u: V1 Q' ^( h+ }% M* {% y' C
  808.         /* compression format 0 */
    $ `9 G  b3 S/ C1 A" o8 D
  809.         rbt->frame_load_buffer[24 + 8] = 0;# t. ^; \, }. g* y
  810.         rbt->frame_load_buffer[24 + 9] = 0;) K- m" W8 R4 n6 y- k* U
  811. : P- x+ \* d$ M8 l9 A$ m6 Z
  812.         /* write the 24-byte frame header and the 10-byte fragment header */5 t1 i2 d1 ]& k* {# G+ D% B, t
  813.         if (fwrite(rbt->frame_load_buffer, 24 + 10, 1, outrbt_file) != 1)
    1 |" X3 l. x$ r" @9 v5 G2 V6 w( H
  814.         {. R" _+ K% G% O4 Z4 @9 B( x6 r; G
  815.             printf("problem writing frame %d\n", i);
    9 h, G5 ^3 k% n3 O8 Y' B
  816.             return 0;& D4 n3 X9 c$ |+ r& ?
  817.         }- a3 f! X3 D3 b, c
  818. 4 Y7 k* Q1 P2 m* y& _9 m+ L( R9 A
  819.         /* write the new compressed frame data */; ?( ~; |; g3 m1 D4 T
  820.         if (fwrite(pb->bytes, pb->byte_index, 1, outrbt_file) != 1)
    - D8 z5 Y6 |# p; O$ P
  821.         {: Z. Q8 [/ t  A" o; w: x
  822.             printf("problem writing frame %d\n", i);
    / R+ Y6 D5 ~2 U, }; V
  823.             return 0;/ ^; H8 h& B5 o$ n2 T
  824.         }- B0 u% g! R5 B: h2 t

  825. 7 N# F: ^# F6 p6 t/ @1 t
  826.         /* write the audio data */
    * r; u3 F* e& T! \- I* s! z
  827.         if (fwrite(&rbt->frame_load_buffer[video_frame_size], frame_size - video_frame_size, 1, outrbt_file) != 1)
    7 r6 b5 J: V1 u' J4 T7 a6 Z2 Q
  828.         {
    : j* y( j- e0 q' C0 y" I2 K/ ~# d
  829.             printf("problem writing frame %d\n", i);2 {6 J0 k7 n  c4 @* m
  830.             return 0;+ s' _7 D: d$ z: S
  831.         }! ~, B0 ?$ i1 U3 T9 D

  832. 6 ^! Z9 I1 Z; ^  u# @9 C
  833.         /* update the table entries */
      N7 o3 P) H2 d5 q4 v, |/ U9 W
  834.         video_frame_size = pb->byte_index + 24 + 10;
    7 V, H8 [! f5 x# B. [
  835.         frame_size = video_frame_size + audio_frame_size;
    $ S! _' W1 ~2 w$ I% C& X9 {4 }
  836.         rbt->frame_size_table[i*2+0] = frame_size & 0xFF;* G" ^! {$ C, W8 d" B& r/ a
  837.         rbt->frame_size_table[i*2+1] = frame_size >> 8;" }8 ]1 g/ r( A# i4 a2 j
  838.         rbt->video_frame_size_table[i*2+0] = video_frame_size & 0xFF;
    * ^6 |$ c! j4 t/ H
  839.         rbt->video_frame_size_table[i*2+1] = video_frame_size >> 8;1 F  d: l) [" \: t! d9 j
  840.     }
    5 w- U3 J( O& n; y1 @# m
  841. " l6 b, `# }* l8 `: v
  842.     printf("maximum dimensions seen are %dx%d\n", max_width, max_height);( q- ~. f* {0 @

  843. ; u) V. U2 s7 A  ?' B
  844.     delete_put_bits(pb);. @1 _$ t* H7 o" b! x
  845.     free(full_window);) P3 d2 ~2 g* c: Q
  846. ( i- @9 b+ V4 r5 |  i, q5 A
  847.     return 1;
    ' M3 q& `/ m: f5 x* I5 R3 c. x
  848. }- D0 S: D. O; [) t; j) Y
  849. ; c+ z" j" N  E, M& ^2 F, Y
  850. int main(int argc, char *argv[])) z) J# N" ]4 z) Y. J1 M
  851. {+ V4 Q+ `& W- j) \+ i7 x7 _9 x' G
  852.     char *subtitle_filename;4 p+ V0 T2 n+ I, {  r% i2 k+ \" A; n
  853.     FILE *subtitle_file;
    2 w6 v6 N7 K3 `4 z
  854.     char *inrbt_filename;6 `) o* G+ k+ _+ J4 j
  855.     FILE *inrbt_file;
    ) k1 s: Y- t1 F' ^" M+ i
  856.     char *outrbt_filename;7 m+ Y9 }- i5 R! a4 S
  857.     FILE *outrbt_file;
    0 r; Z$ M" M/ ~7 X0 G- S( w
  858.     rbt_dec_context rbt;
    & [' F; d  A4 [
  859.     int origin_x;! z- o# [- S% C( O7 L
  860.     int origin_y;
    $ _1 ?8 O8 Z) g' y$ Y& V9 N2 W- t
  861.     int window_width;
    % z" c9 {% j/ k' g( e- A8 t8 n
  862.     int window_height;
    . W: s: g+ a9 O4 d1 E" m: c% l
  863. ! u" A  y- z# {& v
  864.     /* testing the bit functions */- V# v' L- G/ Z
  865. #if 08 m( d9 b) U0 o& U& g% x+ b7 {
  866.     int i;
    ; k: G$ \; g6 r. N
  867.     uint8_t bytestream[] = { 0x55, 0xAA, 0x00, 0xAA, 0x55, 0x77, 0xFF, 0x1B, 0x70, 0x8F };* d3 ]; l  \8 {8 S) w8 B' G
  868.     int bytestream_size = 10;; k' z5 k+ I' O( \: v# P; b
  869.     get_bits_context gb;4 o! f6 i; P  v3 q6 y; Y
  870.     put_bits_context *pb;
    ; s3 r! B- r7 s0 V/ R
  871.     int bits;
    # L: I* Z$ Z$ N3 W( ?

  872. ' b4 v7 s& `8 p+ e8 d
  873.     init_get_bits(&gb, bytestream, bytestream_size);) T# ?! F" i9 m2 F+ m
  874.     pb = init_put_bits();
    5 h- V$ A  H% J5 R$ v9 O6 T. i

  875. 9 D& D# K' v! s: @$ L' ]* ^2 G
  876.     for (i = 1; i <= 12; i++)
    2 ~( `/ l. P7 k- M# M2 z5 \* x
  877.     {
    7 M0 K' J/ B: ?/ \1 o
  878.         bits = view_bits(&gb, i);
    5 j* T8 m- I; P9 u+ ?3 @5 S2 o
  879.         printf("view %d bits: %d\n", i, bits);
    - {. S: J4 m/ l; u/ h) V2 L
  880.         printf("read %d bits: %d\n", i, read_bits(&gb, i));
    : r; N' z  d# Y/ |$ G
  881.         put_bits(pb, bits, i);! O3 o0 q5 T# P6 }3 \# P
  882.     }* B/ R4 b' M% `
  883.     put_bits_flush(pb);* ]6 w$ ]6 v0 v8 {3 d$ a1 \
  884. 5 F/ S' b) |' U
  885.     printf("original bytestream:\n");' _8 O7 `7 i. ]& J  F
  886.     for (i = 0; i < bytestream_size; i++)+ O* k8 D$ Z( b
  887.         printf(" %02X", bytestream[i]);
      i- ?8 o5 B8 c/ d: G0 n6 D' S
  888.     printf("\nnewbytestream:\n");' A8 F. A6 W3 t4 e
  889.     for (i = 0; i < pb->byte_index; i++)) j0 F  W, x4 B& i, A. w6 ~
  890.         printf(" %02X", pb->bytes[i]);  X5 q, ~$ P) F+ W. T6 E0 l
  891.     printf("\n");, ]/ n7 D( @5 l$ `' A  k
  892. ' j+ F- F4 m+ _/ v- n2 J2 r, w$ A
  893.     delete_get_bits(&gb);0 Z. p4 o. t5 N- _1 o
  894.     free(pb);
    1 a9 p* J5 G+ g5 O6 a' B
  895. #endif
    , O! `% Z, O( v! J+ f4 u2 E) \6 G

  896. & ^4 Q4 J+ H0 a3 m: ?- H
  897.     /* validate the number of arguments */9 x5 q6 I2 K0 i
  898.     if (argc != 8 && argc != 9)1 Q3 `+ H* w/ c- k
  899.     {
    $ O" R; _9 _8 b' C
  900.         printf("USAGE: subtitle-rbt <subtitles.ass> <in.rbt> <out.rbt> <origin X> <origin Y> <width> <height> [dump_frames]\n");9 ~% Q" _' y, f( R" X4 J$ G9 S
  901.         return 1;( y( j  s* ~+ M/ K  j
  902.     }# ]# v7 A" Q: H
  903.     subtitle_filename = argv[1];
    " |/ S9 V! U; P2 _4 _$ J
  904.     inrbt_filename = argv[2];- D# F0 \( G. F. x% F4 ?' ]
  905.     outrbt_filename = argv[3];9 X, `; f9 K  S4 W+ T
  906.     origin_x = atoi(argv[4]);
    % Y$ r& A: v9 @( A# S) F4 Z0 }
  907.     origin_y = atoi(argv[5]);3 m7 I4 B& U; s
  908.     window_width = atoi(argv[6]);
    & Y3 a. ~9 r( L8 v# Z
  909.     window_height = atoi(argv[7]);
    : N- `# U5 u/ D/ K- c
  910.     rbt.dump_frames = 0;
    $ U( f% c: s1 n- c
  911.     if (argc == 9)( X. |, N" _& p8 y" L! X3 W
  912.         rbt.dump_frames = 1;
    5 _+ K6 V% j) s% B  P/ }  R
  913. : T& h1 \/ W! v# L
  914.     /* verify that the specified input files are valid */
    : a: B. P& g" }: D* ^0 U
  915.     subtitle_file = fopen(subtitle_filename, "r");2 X6 d. f+ ~  _9 O* s
  916.     if (!subtitle_file): J7 ?) L6 s# _* J- @/ P# Z& ^
  917.     {
    9 ~+ h9 v+ p( n5 }4 O6 u. ]
  918.         perror(subtitle_filename);
    0 p# h8 _, o/ }  b
  919.         return 1;
    . K- |5 @. l0 V8 e, {. }! x6 T
  920.     }
    / n  D" F8 X2 s/ d6 D6 {3 O
  921.     fclose(subtitle_file);
    / }# h7 w; z' b# l
  922.     inrbt_file = fopen(inrbt_filename, "rb");* G" g3 ^5 e' s6 G6 ^3 B
  923.     if (!inrbt_file)
    6 @, C# P& Q! V( J' Z
  924.     {+ [" t5 _/ r3 V$ ?% D( m
  925.         perror(inrbt_filename);
    ! B7 Q  g1 X' E# i9 _; b
  926.         return 1;
    " I& l4 K2 U3 V$ `. l1 B  m
  927.     }
    / ~3 f( f5 I8 i6 k
  928. * p8 E- ^+ _5 }# `4 _- n
  929.     /* initialize the subtitle support *// i* s6 I% ^, k
  930.     rbt.ass_lib = ass_library_init();4 M: x- `; ]) s  g; u1 e9 n: U
  931.     rbt.ass_renderer = ass_renderer_init(rbt.ass_lib);9 ~* U3 X' Q5 u  I: F: H8 }: B
  932.     rbt.ass_track = ass_read_file(rbt.ass_lib, subtitle_filename, "UTF-8");
    8 F7 j" f% v) I+ v# _
  933.     ass_set_frame_size(rbt.ass_renderer, window_width, window_height);* P' l9 }% [1 O# x/ p1 r7 k
  934.     ass_set_fonts(rbt.ass_renderer, NULL, NULL, 1, NULL, 1);8 X  |& _/ l; `0 j* U6 C6 j3 ^# O

  935. " }2 U3 b% I" r
  936.     /* open the output file */0 a* X* Q9 K+ k, L
  937.     outrbt_file = fopen(outrbt_filename, "wb");, f! r5 [- S- x4 w6 e7 p0 B# \
  938.     if (!outrbt_file)
    " B" n$ W* h% F' M' e- A
  939.     {
    6 h2 W/ b9 f4 W
  940.         perror(outrbt_filename);
    % P. n' I! Y/ ~* }. h5 q+ ?
  941.         return 1;, @4 z* F2 d( I0 c9 S& v6 }6 U
  942.     }
    + J) V$ p" f* R" T  B4 h
  943. 5 g9 c; f8 @: F
  944.     /* transfer header from input to output */# m1 c! ~/ g1 K5 c' z- F5 F# q
  945.     if (!load_and_copy_rbt_header(&rbt, inrbt_file, outrbt_file))* N& h7 E4 j# k5 r. Z' q
  946.         return 1;; c+ p% E# H! f5 k; H$ \

  947. ( U8 k" Q- c5 ^8 p
  948.     /* rewrite the frames */1 W  G2 \6 I! I9 b
  949.     if (!copy_frames(&rbt, inrbt_file, outrbt_file, origin_x, origin_y,7 I' N/ j# a6 S  Y4 H
  950.         window_width, window_height))
    . B7 `0 u( w4 u
  951.         return 1;' B4 Q* K! u& }! |; o' R8 t
  952. 4 E2 h4 w+ O. F$ R* `, _
  953.     /* write the modified frame size tables back to the file */% F* y7 n/ X! I% V6 _# b, m  l
  954.     fseek(outrbt_file, rbt.video_frame_size_table_offset, SEEK_SET);
    ( }. W9 D, q9 N% w% K* ~! W' U
  955.     fwrite(rbt.video_frame_size_table, rbt.frame_count * sizeof(uint16_t), 1, outrbt_file);1 R& x1 F5 l0 d- y$ [! u" Z  G
  956.     fseek(outrbt_file, rbt.frame_size_table_offset, SEEK_SET);1 i5 @. g7 C: k% J# I4 |6 Z
  957.     fwrite(rbt.frame_size_table, rbt.frame_count * sizeof(uint16_t), 1, outrbt_file);
    3 p; f; ~! ~# y9 X

  958. ( Z) N3 Z. u  s
  959.     /* finished with files */. L- q" P- B& K' D5 T1 C
  960.     fclose(inrbt_file);
    . G0 q7 w6 g6 _* P$ t/ ^5 ^( C
  961.     fclose(outrbt_file);
    6 K2 \) {0 w& s5 R
  962. 8 q: S/ Q( E5 ^
  963.     /* clean up subtitle library */+ w! v% R2 O: M
  964.     ass_free_track(rbt.ass_track);3 x) M" h5 T/ [3 y% d4 J( L; e! _
  965.     ass_renderer_done(rbt.ass_renderer);* }! [  e- g) Q# N* f, ?5 K! A' ]' P
  966.     ass_library_done(rbt.ass_lib);1 |+ V# f- |& H8 i' B4 y2 ^
  967.   i$ g  u7 z2 S1 B7 J) A, k2 H4 W
  968.     /* clean up */
    1 l! C) x& i/ s+ G( K* S: O
  969.     free(rbt.frame_load_buffer);
    / g$ ~/ M; \6 r; H( y$ T
  970.     free(rbt.video_frame_size_table);
    6 M. {$ n1 r  t
  971.     free(rbt.frame_size_table);. g2 B# @6 f) D* `( l

  972. ! u# k- J2 y0 S2 q$ I
  973.     return 0;
    6 Z6 D# e: U( i" |( g- Q
  974. }
复制代码

8 B9 J9 d/ I  ]2 n- S( v$ K
8 C# W. t- S1 u3 O4 }
/ @6 U4 u; k2 D2 f' M/ [% L. M& J: r& s3 e2 M8 O# P+ b
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 很美好很美好 很差劲很差劲
回复

使用道具 举报

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

使用道具 举报

板凳
 楼主| 发表于 2009-11-19 11:38 | 只看该作者
引用第1楼soring123于2009-11-19 11:09发表的  :
, [6 f  g! H$ _' P5 r8 v这游戏有字幕吗?

3 }1 @# z2 D" n  F好像没有字幕,我说的是给视频外挂字幕方式的汉化。% _. q9 ?' z7 D" |" v9 f
就像syberia2汉化版下面那行字一样。
回复 支持 反对

使用道具 举报

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

使用道具 举报

5#
 楼主| 发表于 2009-11-19 17:39 | 只看该作者
引用第3楼soring123于2009-11-19 17:07发表的  :+ C& l% h2 G/ O8 q( |
我记得是没字幕的 比较麻烦 都是视频的

0 k. ?1 V7 Y! p; ]给视频外挂字幕方式汉化也许能行。
. J  c5 Y  ]2 c要结合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日,是全球华人共同的冒险解谜类游戏家园。我们致力于提供各类冒险游戏资讯供大家学习交流。本站所有资源均不用于商业用途。

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