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

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

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

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

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

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

本帖最后由 shane007 于 2021-1-2 13:56 编辑
: n5 O: g# H- F% D  A9 k
; W2 v$ M% b/ [  B4 R6 s) q最近找到了一些和幽魂系列Phantasmagoria 有关的资料,
2 {4 p% J/ n6 ]6 O也许将来可以用于汉化。
5 t! U/ ]6 G' D1 k& W
4 P7 [* N6 `8 b: ]+ W和日文版有关的信息/ G: {6 F4 d, q( k9 M' }
http://anthonylarme.tripod.com/phantas/phintgtp.html
  S: j$ m2 k1 w; u0 F$ R. S' b% _( T2 _* ]; |
相关工具
! Y# N- Q' @% z# ]" Hhttp://anthonylarme.tripod.com/phantas/phcheats.html
& q' ^, B- R" G' x) b5 j) P9 x) I-----------------------------------------------------------------------/ B7 V5 x1 G" j5 l  n! Y/ z
2012/1/2  更新
' V- g0 [1 g" t3 E8 B0 s4 s0 R关于幽魂游戏的字幕2 V& G3 L# ?: E! w4 ~
Phantasmagoria subtitles function discovered - ScummVM :: Forums: R8 F  E) U" t" w
5 \; p7 y8 W2 S/ d5 b% E* [
VMD文件: [7 v  u9 {& [1 {( b( Y" y
Subtitling Sierra VMD Files | Breaking Eggs And Making Omelettes (multimedia.cx)VMD - MultimediaWiki6 Z* C  h1 \, k; p0 g! S7 e

/ d( o2 A4 p0 O* f$ L* }字幕
' A/ e+ k+ f5 CSubtitling Sierra RBT Files | Breaking Eggs And Making Omelettes (multimedia.cx)7 i6 G* B; ?/ }( k3 {

/ T2 T- j, n& W- B+ T; h: {& e4 TFFmpeg/subtitle-rbt.c at feature/VMD_encoder · multimediamike/FFmpeg · GitHub) r. ^0 Z. O' A* I
  1. /*' u+ z4 P: f; a' k# |3 g( Y! c
  2. * subtitle-rbt.c$ l$ v) B! l: W* X- K- H+ U
  3. *  by Mike Melanson (mike -at- multimedia.cx)' k+ q* x0 T: w+ @
  4. *
    ' C: S$ Q+ c: V
  5. * build with this command:
    9 i5 w/ a, I' _' O1 H7 Y( Q( a
  6. *   gcc -g -Wall subtitle-rbt.c -o subtitle-rbt -lm -lass% D* k" [$ ~# s
  7. */; a( b: H' H  F- J8 q8 |% y7 `' k4 j- a
  8. ' _, ~  @5 D/ `0 |
  9. #include <inttypes.h>; D# d* |7 v1 [# M
  10. #include <math.h>
    * x& K7 b, n5 l. \
  11. #include <stdio.h>
    4 m; b8 `3 m5 |
  12. #include <stdlib.h>1 Q" Z& C$ B; \- k% Q/ X
  13. #include <string.h>; |" {4 F: T" W

  14. 6 `/ M9 T9 D$ C9 s3 J8 y
  15. #include <ass/ass.h>
    & _- t6 E2 y( _% O
  16. % R6 C4 |& n" K; u# Q% [
  17. #define LE_16(x) ((((uint8_t*)(x))[1] <<  8) | ((uint8_t*)(x))[0])+ x. Z; a1 H6 W  o  I, p

  18.   m& k' d" ~- S( @# G5 n# v( ~. N6 ?
  19. #define LE_32(x) (((uint32_t)(((uint8_t*)(x))[3]) << 24) |  \
    ; Y* h  j" q( v! R
  20.                              (((uint8_t*)(x))[2]  << 16) |  \/ V& X3 z7 N) w/ z0 R5 n$ M
  21.                              (((uint8_t*)(x))[1]  <<  8) |  \
    1 M, z, k; v! S# N. _
  22.                               ((uint8_t*)(x))[0])- n7 {9 B; ^" G( _% T) F4 v' \/ t2 U9 R
  23. : K- ?" |3 W' t* ?
  24. /*********************************************************************/$ _# Y7 H# f+ [; n; R8 v

  25. ( o" ]) j: e# ^3 J$ z1 E% _
  26. /* Bit reader stuff */3 i+ j7 s5 x4 x2 i; Q1 H3 e
  27.   z$ D! ]3 E$ w1 R- b
  28. typedef struct
    ) m# l* G- s  C& D5 r( N
  29. {  X3 \  m2 x5 i% l9 E5 |) p0 b
  30.     uint8_t *bytestream;
      \# E0 p* T6 L; H* |9 J2 b
  31.     int bytestream_size;
    4 o) F7 T+ b( b0 v8 k+ l- s2 X
  32.     int index;2 ?# H& Z" W- H6 O0 j
  33.     uint32_t bits;$ R5 X2 W( d* }2 p$ t6 w
  34.     int bits_in_buffer;
    % P( G9 \, |/ f
  35. } get_bits_context;
    2 K' n" d+ `9 l3 S$ n
  36. 5 k6 W0 D* g* T/ D8 z. A+ [
  37. static inline void reload_bits(get_bits_context *gb)5 Y% ?7 ]! r$ B
  38. {
    1 I# F: T' A, _# T: O$ \
  39.     while (gb->bits_in_buffer <= 24); w6 `" d2 B. V
  40.     {% _$ {( z* J1 }/ I1 F1 Z, h
  41.         if (gb->index < gb->bytestream_size)
    5 m0 K$ Z; Q- ?" G" @) `& x
  42.             gb->bits |= (gb->bytestream[gb->index++] << (24 - gb->bits_in_buffer));
    ! Q- ?$ }1 z9 t" N& f" X* ~
  43.         gb->bits_in_buffer += 8;
    9 F6 u! X" F" \
  44.     }
    9 g3 Z  s4 p8 {2 C0 m2 y0 E
  45. }
    , L" C9 d% A. k. l6 f* A; n

  46. 4 o5 `  m. X9 u& {9 n7 `
  47. static void init_get_bits(get_bits_context *gb, uint8_t *bytestream, int size)
    % S% n8 l. M9 D/ a# i4 j
  48. {
    4 [- e% h* P+ r! D0 D
  49.     gb->bytestream = malloc(size);" y+ j# A5 R5 {' h( K- {
  50.     memcpy(gb->bytestream, bytestream, size);
    4 m, l# a9 |- P4 R8 L- e& `
  51.     gb->bytestream_size = size;' X6 t2 q" U2 b/ ?* I. \9 u+ @/ o5 Y
  52.     gb->index = 0;
    9 z' Q  M& p8 O# O: s
  53.     gb->bits = 0;+ o7 b- ]7 S0 W% I& [$ O+ O
  54.     gb->bits_in_buffer = 0;
    - F9 R9 q2 V( b" G& _5 @. Z

  55. + l2 M: Q, }- c" n/ Z# N- x* b
  56.     reload_bits(gb);
    + W3 N" d4 Y( q- I7 G* @
  57. }
    . x; D8 ^* Z6 Q, a) H
  58. - Q2 Q! c) E/ W% n
  59. /* read bits without consuming them from the stream */
    ! |& S: p9 Z# ?6 x0 R
  60. static int view_bits(get_bits_context *gb, int count), a* t. C) ?2 X: m
  61. {
    ; n8 e6 z% ?) d8 }6 T
  62.     if (count >= 24)( O' {0 ~- z+ k
  63.         return -1;
    ! m0 y" D- ]4 }2 h7 x; [- i
  64.     if (gb->bits_in_buffer < count)  M: V7 n) y4 V( ~1 k
  65.         reload_bits(gb);3 @: b% I0 h- f# V, z, [5 d! O( F
  66.     return (gb->bits >> (32 - count));
    7 W! A5 _0 H7 r; y5 J  k
  67. }0 _7 h& B- h  V) Z& w5 D
  68. 8 v& N& C4 ?- f& P6 A8 y& i: Z
  69. /* read and consume bits from the stream */+ {1 _  Q! ]! e
  70. static int read_bits(get_bits_context *gb, int count)' K) i; w# M  T2 k. p" N  Q
  71. {- B8 f3 I+ \1 L2 {% K# w. F& z, Y: I
  72.     int value;3 d! x) E& s  `0 `, w, p  d/ O  c1 ~
  73. : L. s$ |! ^, z/ h! E: F- Z
  74.     if (count >= 24)- G5 A5 ~& e; V6 O. y" v9 H
  75.         return -1;
    # V6 x& _7 J& K4 |+ P! \
  76. * W& u  B) u: o* E% |2 _; X
  77.     value = view_bits(gb, count);
    : q+ S1 [! z/ O
  78.     gb->bits <<= count;
    2 K) L" q" R$ ~/ E
  79.     gb->bits_in_buffer -= count;
    / T' Q5 _3 u9 n" w+ f# l1 k

  80. # x, X: [( S6 D5 C; R0 \+ S3 R
  81.     return value;% I& _  b( ]! ?, e8 F
  82. }
    % H: ~- I3 n  G; j9 W
  83. 8 ~( d* J+ P: ]; }/ L
  84. static void delete_get_bits(get_bits_context *gb)
    : T9 X2 ]* e- k, r& \
  85. {1 x, ?. R/ v- i. x2 P+ R" G! `& I
  86.     free(gb->bytestream);
    3 L- ~) Y3 v8 ~3 z
  87. }
    3 T, l6 A$ R$ h% B# u" b
  88. 8 W0 c6 {7 g/ R! u/ H
  89. /*********************************************************************/
    % C- Y( g2 J* T

  90. . t! S  V7 {4 X  J6 X
  91. /* Bit writer stuff */
    - }, U5 Z8 Z5 C* }) [/ V! R

  92. 8 m5 H+ C0 ?1 s! l& }
  93. #define MAX_PUT_BITS_BYTES 63000
    % f0 g) T1 b) `" h; I# Y
  94. typedef struct
    ! @/ h3 ]- L1 r2 D
  95. {' Q8 I+ h* j. ~- x6 Q
  96.     uint8_t bytes[MAX_PUT_BITS_BYTES];. a2 `: w" z2 M  ?3 [, n
  97.     int byte_index;
    3 a# J! a/ u8 `/ n2 Q" x: |
  98.     uint32_t bit_buffer;
    # g+ ]) p. r4 B% u: @' t, ^# Y3 g
  99.     int bits_buffered;" p% o  g1 v, H' \* e
  100. } put_bits_context;* r6 r, a8 c0 s# J1 W. _& ^
  101. $ w2 |( O: N) F8 P+ L' P9 X
  102. static void reset_put_bits(put_bits_context *pb). b$ `6 S4 D4 j
  103. {/ r8 G- c8 n* P# S7 [6 B
  104.     memset(pb->bytes, 0, MAX_PUT_BITS_BYTES);
    ( k) s, G+ @+ E7 F6 J- n
  105.     pb->byte_index = 0;
    & N5 K0 J% s: V3 Z, a4 J2 p" v- }! C
  106.     pb->bit_buffer = 0;
    0 G$ w: E; ^6 x/ I+ Z' U& b
  107.     pb->bits_buffered = 0;
    / D' b1 g- T. x/ Y  t2 M. _* j
  108. }
    # j- j3 R* A$ B7 c. [1 y7 F6 g

  109. 0 ^8 T8 |, s& c9 O0 Q; u0 l" {7 F
  110. static put_bits_context *init_put_bits()
    ! Q# [: S+ _# D
  111. {6 j/ \/ L5 o" C8 f
  112.     put_bits_context *pb;
      p3 s( t2 C# A9 ]6 F1 v
  113. 4 M& O" `+ f: \
  114.     pb = malloc(sizeof(put_bits_context));
    $ {2 J& s. Y" B- s2 |
  115.     reset_put_bits(pb);
    3 `$ O; }, }) f7 F8 ]

  116. 7 }$ D9 S6 z( J' s
  117.     return pb;) ]+ y; a1 I' I9 |9 Y3 }, o
  118. }+ s! E% W- [7 z. Z- P4 ?7 X* L0 }
  119. # x! z" z! N% y! Z- v3 M
  120. static void put_bits(put_bits_context *pb, int bits, int count)( y! V, u; U8 n, c2 w
  121. {
    / z& G% k/ g+ {* X. d! ~9 i. J
  122.     pb->bit_buffer <<= count;
    - ]6 ^6 C0 Q. H$ n4 @* X
  123.     pb->bit_buffer |= (bits & (~(0xFFFFFFFF << count)));+ Z. o" s; l. t% r
  124.     pb->bits_buffered += count;0 \# g- d8 P2 v

  125. ! j: X: o+ q. o! V; }" l, H
  126.     while (pb->bits_buffered >= 8)- l. |( @. \  O) t
  127.     {% _& D7 U( w" E
  128.         pb->bytes[pb->byte_index++] = pb->bit_buffer >> (pb->bits_buffered - 8);$ P8 b' I+ d. g# g0 W5 a
  129.         pb->bit_buffer &= (~(0xFFFFFFFF << (pb->bits_buffered - 8)));8 Z$ o; i3 H" J* {* o0 t' T; O
  130.         pb->bits_buffered -= 8;7 i/ F3 ^! s& s. t/ T
  131.     }+ Y( @) P' J/ S+ w0 h% U

  132. ' X) g1 u* v" \& ~9 f% \
  133.     if (pb->byte_index >= MAX_PUT_BITS_BYTES)
    3 y; s8 y8 R! R  _3 T
  134.     {
    0 Z, A3 [% I; ]7 N, ?
  135.         printf("HELP! Bit overflow\n");' }  s* H  X7 Z6 {8 q; a
  136.         exit(1);
    5 Y. }# C, n  y% ^
  137.     }
    - p6 s) X" f! D* S3 d
  138. }& q& [6 r! q5 J$ V) ?$ U  u. C( [
  139. , f' j+ p7 k5 b7 R
  140. static void put_bits_flush(put_bits_context *pb)
    ' Q! D$ L, _( ?1 r) d0 M
  141. {: M: }6 z% F1 \' U
  142.     if (pb->bits_buffered > 0)1 x- ?; b. y/ Y5 s! u( u& v
  143.         pb->bytes[pb->byte_index++] = pb->bit_buffer << (8 - pb->bits_buffered);
    ) H& h. ~! D9 p: {
  144. }
    ( z" [, G$ Y3 |
  145. 4 O1 B0 d& q7 q
  146. static void delete_put_bits(put_bits_context *pb)
    $ k+ j/ n% A! V  ?' v
  147. {
    + {% X5 @+ k4 R7 ]3 V4 r8 g
  148.     free(pb->bytes);6 _8 f# L% ]7 m7 E+ D  n; w
  149. }5 x; }' m+ M- E# @- U8 z

  150. ; E7 \+ W! E0 }
  151. /*********************************************************************/
    - _( X% ?, X, B
  152. * O% _  B3 z6 E) N. h
  153. /* RBT functions */+ [! x* \! d6 s" }3 Y6 h
  154. ' _/ j# f+ H/ u. T
  155. #define PALETTE_COUNT 2564 g/ @; o( m; i* `
  156. #define RBT_HEADER_SIZE 60
    ' C  Y8 @3 F+ G5 |( k
  157. #define UNKNOWN_TABLE_SIZE (1024+512)
    # E+ Q! g" k/ P  r" v( S
  158. #define SUBTITLE_THRESHOLD 0x70; e4 k1 o3 Z4 b7 C4 P
  159. #define MILLISECONDS_PER_FRAME 100* M0 s1 \3 H/ r# U4 s( `, E/ ]

  160. - \3 N+ d/ m& H& E0 n, Q- {
  161. /* VLC table */6 j( E! N/ s, W3 W: _! _0 r) ]: O" ~, `
  162. #define VLC_SIZE 49 N( z% Z$ {1 P5 ^  n1 X. u. O
  163. static struct
    ) ]# n& Y8 W* h. E) H
  164. {
    0 U, |. ^/ D- G6 I
  165.     int count;2 y' V2 s, S% F8 r3 R* E, j
  166.     int value;
    # E8 G8 y. P$ T- v" Y8 ~6 U
  167. } lzs_vlc_table[] =: r: h. F3 f5 |& F( H: Q
  168. {* c9 T% k, l0 T4 `, G
  169.     /* code length = 2 bits; value = 2 */
    - \- s% T0 Z+ }0 R+ t6 N
  170.     /* 0000 */ { 2, 2 },
    8 k% W+ R8 y4 d& [6 }* A& m9 L
  171.     /* 0001 */ { 2, 2 },1 r/ `% C! Y' `; t9 A4 L$ {
  172.     /* 0010 */ { 2, 2 },
    5 O* R7 g! S; h
  173.     /* 0011 */ { 2, 2 },
    0 J1 }) L( x$ B3 |7 Z
  174. " A  C: g* A2 e* `; v! o4 B
  175.     /* code length = 2 bits; value = 3 */
    ( i. e1 N5 z. w; p0 o2 ?; g5 ]# W- B
  176.     /* 0100 */ { 2, 3 },; K; t6 O+ I* r6 z7 r8 V5 `# c
  177.     /* 0101 */ { 2, 3 },
    2 f% y: g$ u) P1 S1 \/ j  O
  178.     /* 0110 */ { 2, 3 },3 T! Z/ \& p; }8 {" N+ _) h! U2 F
  179.     /* 0111 */ { 2, 3 },9 q5 I6 E+ {; L1 f9 o
  180. . ]" X! x+ I( A, L! _5 u
  181.     /* code length = 2 bits; value = 4 */
    ! S( j* \! \0 ?, z2 Q6 l) r& f
  182.     /* 1000 */ { 2, 4 },% y" q5 g, s4 a1 X8 q9 }) y
  183.     /* 1001 */ { 2, 4 },. L  c; K5 b( O: S) i) @- ~; N" P
  184.     /* 1010 */ { 2, 4 }," R+ B4 q2 c3 E$ U/ f' S
  185.     /* 1011 */ { 2, 4 },
    0 B3 s% i! d. n3 G. Q

  186. 1 R6 H: ^* I! O9 I: R
  187.     /* code length = 4 bits; value = 5 */0 D- w3 A; V) u
  188.     /* 1100 */ { 4, 5 },
    / t) p) h) c4 W/ s( k$ R* P4 \$ s, h

  189. * \  Z* t, k5 T. n6 P& H# \
  190.     /* code length = 4 bits; value = 6 */
    5 F/ U% e* B1 A: q% A0 O
  191.     /* 1101 */ { 4, 6 },
    1 x" T# O+ a, B0 S2 h- [. `* q3 |

  192. 5 H' Y! m1 E$ ~& w( m+ ^
  193.     /* code length = 4 bits; value = 7 */* |$ c/ O0 i9 H# z. m
  194.     /* 1110 */ { 4, 7 },; w7 a0 d8 i/ Q/ @0 k

  195. ; `% b- z2 y- |
  196.     /* special case */
    7 \4 L6 W2 X: O1 w6 \" M5 J/ E
  197.     /* 1111 */ { 4, 8 }+ |( J( }3 D: Q! G
  198. };" e3 t1 N& P4 j9 M) `' A7 t) x
  199. 6 w* D7 n- a9 A
  200. typedef struct& g- T! C% Z' e7 e
  201. {
    3 l7 u7 Z4 q( H6 C) h% D
  202.     int version;
    5 X2 Z! _" d& }; n1 {3 W
  203.     int width;
    , b$ H2 ]( S; w! @0 D8 R- u
  204.     int height;1 m! a* ?/ o8 D5 V' Z
  205.     int frame_count;
    8 y9 z: J. m% O) e
  206.     int audio_chunk_size;
    1 w- `9 l' B- `" [
  207.     uint8_t palette[PALETTE_COUNT * 3];
    - C$ j/ X% C9 Z: I" {% d+ O
  208.     off_t video_frame_size_table_offset;5 P; F8 `: G. I  b7 I
  209.     uint8_t *video_frame_size_table;
    $ m1 O6 j+ ]. D1 a  w. C* d
  210.     off_t frame_size_table_offset;2 e1 R6 F: G" w! L; J
  211.     uint8_t *frame_size_table;
    ( q$ Q) @' U5 j0 f& B
  212.     uint8_t *frame_load_buffer;
    4 n3 v) ?: j  W, r9 s
  213.     int dump_frames;
    # M! g1 H% I  s( L$ @

  214.   c( E+ J3 r) q" g1 K0 B: k9 `" i
  215.     /* subtitle library */) F5 E! T2 K- ]/ m
  216.     ASS_Library *ass_lib;9 B) i! C: o. Q! c2 U( S
  217.     ASS_Renderer *ass_renderer;" d+ v8 n& q# g8 l, a" H
  218.     ASS_Track *ass_track;
    ! E3 j% O0 U) @" O7 o' Q
  219. } rbt_dec_context;
    8 W1 n/ u6 l. S7 P- V4 u5 [
  220. 3 ^; t0 n% [( x2 [! B1 \
  221. static void dump_pnm_file(char *filename, rbt_dec_context *rbt,+ D  S' U9 @: U+ h- S% G
  222.     uint8_t *image, int width, int height)
    3 @) [9 S# G0 m7 Q' ?4 w9 M
  223. {
    " J3 w5 u9 \- B% J# Z
  224.     FILE *outfile;4 f8 ~( `/ [9 o( _. S/ O
  225.     uint8_t bytes[3];
    7 M- O$ ~* A3 }
  226.     int p;  x8 ?; [& ]" V5 ~
  227.     uint8_t pixel;! h9 v) z& s% j0 Q8 I1 p; A1 P
  228. 4 N" ]+ a+ l* h% R* o' p" i8 ^. Z6 ~
  229.     outfile = fopen(filename, "wb");
    % R5 |3 f0 w0 _' m
  230.     fprintf(outfile, "P6\n%d %d\n255\n", width, height);# c' s8 }  p0 O# r  O/ e' M8 Y, Z3 p2 C+ |5 T
  231.     for (p = 0; p < width * height; p++)5 Z, P- w+ o* Q1 s' b- N  W
  232.     {
    " @- t8 s* }' S% U2 `
  233.         pixel = image[p];- S4 R: y, t; k; O! E
  234.         bytes[0] = rbt->palette[pixel*3+0];
    ' r- e+ O+ Q: }7 D4 t! v, _" l
  235.         bytes[1] = rbt->palette[pixel*3+1];
    - j: T% D0 o6 K9 Y) u( i
  236.         bytes[2] = rbt->palette[pixel*3+2];
    / t& @" \/ |7 u9 p
  237.         fwrite(bytes, 3, 1, outfile);+ U) B7 G- d# K8 O: Q
  238.     }. U$ G, l( P; D& M3 ]. C; d
  239.     fclose(outfile);8 z( O6 @: {. n4 N3 ~% s0 U# J- A3 \
  240. }
    5 [4 x2 o2 E/ O; b+ h: G8 F0 I- U
  241. + L3 U, b. c& H% l1 O1 {3 D4 a1 I
  242. static int load_and_copy_rbt_header(rbt_dec_context *rbt, FILE *inrbt_file, FILE *outrbt_file)
    - I( v6 Z9 y7 q" o; J
  243. {
    , l6 H/ l- h; j" D9 q9 S
  244.     uint8_t header[RBT_HEADER_SIZE];
    ) x- |3 G: D7 @& Z" C
  245.     int palette_data_size;
    7 O. s2 l% I, x4 V+ T/ c5 F8 _( n8 F
  246.     uint8_t *palette_chunk;
    " ~2 f4 M, S+ i6 A9 ?; `% z2 [
  247.     int unknown_chunk_size;
    ! u0 n& n. a9 E( C
  248.     uint8_t *unknown_chunk;+ ~/ S; v" r9 X5 w0 w$ p8 S7 w  a4 ^
  249.     uint8_t unknown_table[UNKNOWN_TABLE_SIZE];
    , _. W* k4 {/ R  [3 o
  250.     off_t padding_size;
    4 `, w" M1 n% d# n* D/ L
  251.     uint8_t *padding;2 d# j7 j7 i4 m( `5 B
  252.     int i;7 `; y* {& X4 o' P
  253.     int frame_size;
      h& ^* B, M0 j( k& q/ R
  254.     int max_frame_size;
    / W7 d2 x& n- s. r+ o1 w" i6 _: a
  255.     int first_palette_index;
    - m- r7 Y: `$ N8 U/ S1 _
  256.     int palette_count;: \/ I5 M  o5 Y$ G% ]# V* W
  257.     int palette_type;: W0 F" b/ l# M) b* W; f
  258.     int palette_index;
    ! k& O! u2 X5 a5 V

  259. 7 `7 D3 u! \2 Z) @( T6 l
  260.     fseek(inrbt_file, 0, SEEK_SET);
    ) C! |4 L+ W* T1 @) T
  261.     fseek(outrbt_file, 0, SEEK_SET);
    + r9 q: G6 s4 T8 k+ _2 K
  262. 1 U( y% N" I; j# H4 K7 |
  263.     /* load the header */
    , ?' _! m, C+ y: n
  264.     if (fread(header, RBT_HEADER_SIZE, 1, inrbt_file) != 1)
    4 A: i4 }4 K1 ]& P9 `2 t
  265.     {' P7 x7 K  ^# {: T  @- d
  266.         printf("problem reading initial RBT header\n");
    9 x0 d* a0 Z4 t0 w/ x
  267.         return 0;
    & m$ A' e  ^. _4 k+ v3 o% I
  268.     }
      h7 Z7 R  [3 j1 D/ D2 \
  269. ( {. {# v* B, O2 {$ V: q
  270.     /* copy header to the output */1 U) v' ?4 v4 v# C1 J8 u; a
  271.     if (fwrite(header, RBT_HEADER_SIZE, 1, outrbt_file) != 1)1 }: B2 y7 u! |5 `% j# N
  272.     {
    . q! Q! A: C. n( U, J9 x6 D
  273.         printf("problem writing initial RBT header\n");8 H2 L: y6 a+ e0 M4 x" W
  274.         return 0;/ O" F. Q2 S1 H
  275.     }
    # m" |, {7 R8 D6 L5 R8 A
  276.   [- H& G" E6 p: K4 O0 E
  277.     rbt->version = LE_16(&header[6]);
    9 \' ^* a  A- _% F- }
  278.     rbt->audio_chunk_size = LE_16(&header[8]);+ U! ~9 j2 D3 u. y. k/ a
  279.     rbt->frame_count = LE_16(&header[14]);
    & H0 j/ _9 j  ^4 s
  280. 6 {% x/ k$ r- A& U% e
  281.     /* transfer the unknown data, if it's there */1 f+ \# p" q3 g9 K
  282.     unknown_chunk_size = LE_16(&header[18]);
    ' E8 d+ x: \. Q, L0 M
  283.     if (unknown_chunk_size > 0)
    4 P  S% ^- z% K+ i/ E! j$ R( r
  284.     {
    # z: K- W4 m( x2 m
  285.         unknown_chunk = malloc(unknown_chunk_size);
    2 j' [# U, I# X
  286.         if (fread(unknown_chunk, unknown_chunk_size, 1, inrbt_file) != 1)
    & V# [& d9 y) O  e7 s
  287.         {3 Y$ U* m0 [3 P0 D5 `; Z
  288.             printf("problem reading unknown data\n");+ L* Z. X  f2 c$ s8 C. u
  289.             return 0;1 C$ U( T0 H9 y  B- @
  290.         }
    & m8 ?  k9 }. e% ^* w
  291.         if (fwrite(unknown_chunk, unknown_chunk_size, 1, outrbt_file) != 1)" z9 p) h* W3 W: A% N
  292.         {$ I- L( ?  n) ?6 J/ U4 j& A* G& N' r% ]
  293.             printf("problem writing unknown data\n");; c9 t6 R. g9 i! U4 |7 z0 Z
  294.             return 0;
    ! I" E( u& [2 c3 t" _
  295.         }
    " ?, [4 D% t$ W' I/ ?
  296.         free(unknown_chunk);4 r: p0 b% N3 l% C; ]
  297.     }) C. K& E; E* a- V
  298. 6 Z+ X6 _1 ^, o( o
  299.     /* transfer the palette chunk */3 h+ h( T/ k3 X) ]
  300.     palette_data_size = LE_16(&header[16]);7 j5 X, Q' [5 |! b6 A( c
  301.     palette_chunk = malloc(palette_data_size);
    $ l4 Z: o! Z* D( Y! E9 ?
  302.     if (fread(palette_chunk, palette_data_size, 1, inrbt_file) != 1)
    3 y; t( S7 J$ n4 `1 m: l+ f
  303.     {
    ' |- \7 U4 S9 w. r1 q& n5 A
  304.         printf("problem reading palette\n");7 T8 }% L  Z* ^$ @
  305.         return 0;( X/ t! O" J! O4 i7 c% L: \$ F
  306.     }
    6 w% r8 Q' e9 B1 K* ~' j
  307.     if (fwrite(palette_chunk, palette_data_size, 1, outrbt_file) != 1)
    % Z5 P! T! T! X4 B% o4 f0 e& X
  308.     {( x# K9 i, {* r, H
  309.         printf("problem writing palette\n");
    6 b6 [( z# [( p0 w% ^8 _. j
  310.         return 0;* r* ^  H7 P3 }' I# @; ~
  311.     }& P. z& E7 T/ e- z0 V
  312.     /* load the palette into the internal context */; G  N8 _5 E4 D  ]5 i& ?
  313.     memset(rbt->palette, 0, PALETTE_COUNT * 3);
    ' t+ U/ T5 ]: u
  314.     first_palette_index = palette_chunk[25];
    " c  W6 W5 ]3 P- L, n
  315.     palette_count = LE_16(&palette_chunk[29]);" L' p9 o/ ?0 X
  316.     palette_type = palette_chunk[32];
    . }/ P! |  w# V4 v. _- A
  317.     palette_index = (palette_type == 0) ? 38 : 37;
    , h& P3 R/ I: d* H! B; _8 U
  318.     for (i = first_palette_index; i < first_palette_index + palette_count; i++)
    ( }( S& U( d$ Z
  319.     {$ r9 p7 @- S2 W6 b$ T1 y3 K
  320.         rbt->palette[i*3+0] = palette_chunk[palette_index++];6 l# J( \* n! H/ B6 w5 a
  321.         rbt->palette[i*3+1] = palette_chunk[palette_index++];4 p, K, c) z  h% g4 A' p
  322.         rbt->palette[i*3+2] = palette_chunk[palette_index++];
    8 e" j1 k: B! C1 S9 W3 Q5 r0 `" i* I+ z
  323.     }
    - Y( t# h9 M* M, Y5 X
  324.     free(palette_chunk);
    3 f7 n1 u- a3 o" E5 Y

  325.   h2 m! l0 R6 x$ v
  326.     /* copy the video frame size table (2 bytes per frame), as a placeholder */
    ; d/ d1 p7 w+ K3 k3 V, H" @4 I- Y
  327.     rbt->video_frame_size_table = malloc(rbt->frame_count * sizeof(uint16_t));' |( z. g  Z& @. q/ v# e
  328.     if (fread(rbt->video_frame_size_table, rbt->frame_count * sizeof(uint16_t), 1, inrbt_file) != 1)
    3 @0 q5 G% {: d" C/ a" @; K$ H5 l
  329.     {/ @7 i4 j2 \* P+ x) A
  330.         printf("problem reading frame table\n");
    ) P# ^+ q$ x$ f: E2 F
  331.         return 0;# p0 t5 D: }. }; @, M1 ?7 |
  332.     }  c' l/ Z6 \2 O: R$ m, \
  333.     rbt->video_frame_size_table_offset = ftell(outrbt_file);
    - e' G& B$ C3 }9 w. n' _5 q( l
  334.     if (fwrite(rbt->video_frame_size_table, rbt->frame_count * sizeof(uint16_t), 1, outrbt_file) != 1)3 P: ]; R# q, B/ T4 w- k( N# a
  335.     {
    ) q+ ?8 d6 t+ T; b' P4 Q1 Z0 w
  336.         printf("problem writing frame table\n");4 d' V( O/ S2 W! d
  337.         return 0;6 r3 n# I5 y5 T7 y% R! F+ x7 k
  338.     }
    " S4 H, h3 e7 U/ x

  339. 6 M0 `* Q5 k  Q  z* N
  340.     /* copy the frame size table (2 bytes per frame), as a placeholder */
    ! S+ G+ O9 ~5 x7 _2 y
  341.     rbt->frame_size_table = malloc(rbt->frame_count * sizeof(uint16_t));* g& k8 s4 H0 j
  342.     if (fread(rbt->frame_size_table, rbt->frame_count * sizeof(uint16_t), 1, inrbt_file) != 1)# u5 q- g: i2 D$ q
  343.     {9 L% a1 S  s3 ]$ Y0 n
  344.         printf("problem reading frame table\n");
    / e0 S# T" Y+ r# F, U/ o6 g1 K" L6 I
  345.         return 0;& I) z; z$ x1 l! w
  346.     }) F( h" u& ^0 p* ?/ K
  347.     rbt->frame_size_table_offset = ftell(outrbt_file);; ?6 b3 }  n' q  X
  348.     if (fwrite(rbt->frame_size_table, rbt->frame_count * sizeof(uint16_t), 1, outrbt_file) != 1)
    . T- P+ ]+ ~; T' F+ E" N
  349.     {
    ' u2 ?9 n0 B& o2 `
  350.         printf("problem writing frame table\n");) P, L; e  e$ V. ~& Z
  351.         return 0;: D  N+ a/ i! R+ J0 N
  352.     }. _) z0 o& v: u, r; n( j

  353. 0 y8 Q' x; [8 f
  354.     /* find the max frame size */' A- J$ }  T6 X" I0 F% N; B  o7 w
  355.     max_frame_size = 0;
    % N- J' E" U  V" U5 m6 Z3 _: b
  356.     for (i = 0; i < rbt->frame_count; i++). V2 n8 I% x9 ]2 g, k" T( }
  357.     {
    ( ~# _* |6 M% P
  358.         frame_size = LE_16(&rbt->frame_size_table[i*2]);
    1 H$ ~+ ^% x; y8 D7 U4 |( X
  359.         if (frame_size > max_frame_size)# [, D1 x7 r# e8 K/ i9 r+ ]
  360.             max_frame_size = frame_size;; _- W: j+ b# e& g2 G, w' \
  361.     }6 X# W8 X6 g+ w6 P& ^/ n
  362.     rbt->frame_load_buffer = malloc(max_frame_size);
    ; O+ ?" b6 t: N5 R7 k  f7 \

  363. ) W9 _- O. l6 _1 @- I& ]; M; u4 @# d' E
  364.     /* transfer the unknown table(s) */
    ) s5 @# x* t4 Z, D" D
  365.     if (fread(unknown_table, UNKNOWN_TABLE_SIZE, 1, inrbt_file) != 1)9 r+ \) V0 @6 t6 L" }5 [
  366.     {) B& Z4 j# U: ^9 `3 E/ Z
  367.         printf("problem reading unknown table\n");; Z9 a9 M2 J+ {6 x4 F
  368.         return 0;
    / K# j6 A9 J/ X; R  z# p9 @
  369.     }
    " }& `: [4 b, q' p9 N2 ?; T3 a, ^7 I( Q
  370.     if (fwrite(unknown_table, UNKNOWN_TABLE_SIZE, 1, outrbt_file) != 1)
    6 _4 D, z! X% a. R* I/ a) n% c
  371.     {. E, }( V: L" }* e7 f3 e
  372.         printf("problem writing unknown table\n");
    - k8 P5 q# e' r, V  G7 l0 h/ o
  373.         return 0;
    # k7 r1 X- h0 u2 ?7 R/ L$ {
  374.     }7 q& D: Q) A  U) C* X' v+ K

  375. - Q& ]% P4 s8 i6 i
  376.     /* copy over padding */
    6 i1 k( |2 @8 Z
  377.     padding_size = 0x800 - (ftell(inrbt_file) & 0x7FF);
    & y2 f* L; J( e) M  q
  378.     if (padding_size)# O' ?$ B4 x: r: `
  379.     {; k4 z% G3 m: y. V  d
  380.         padding = malloc(padding_size);* Z# {( q, C2 S' ]5 E8 m' w
  381.         if (fread(padding, padding_size, 1, inrbt_file) != 1)3 d1 B+ e, H' J
  382.         {
    # S# o/ \' l$ N- F* Z" U
  383.             printf("problem reading padding\n");
    8 s! U! G: n, F( E$ ^
  384.             return 0;5 g$ G2 Z7 j4 j# ]! U
  385.         }4 P' E8 l$ N( b3 U! }
  386.         if (fwrite(padding, padding_size, 1, outrbt_file) != 1)
    2 x& A# v" G; @# ]& ~
  387.         {
    ( X1 T, @2 U% }( u6 V
  388.             printf("problem writing padding\n");
    ; k0 |8 k; z! S, B
  389.             return 0;
    1 C5 t) w" O0 D" r
  390.         }
    # o! U% [- i" ?& q( B
  391.         free(padding);1 u- h* v; T' }
  392.     }1 g; Y& p- E9 w$ m8 G' F) v' n. q' `

  393. & o% z( n) a" \# C
  394.     return 1;! [7 Z1 ^2 ?0 Z5 m( j( Q
  395. }
    5 Q$ @+ |7 z; F( j' D8 G. m

  396. + J  ^$ y% f1 }8 R# O
  397. static int get_lzs_back_ref_length(get_bits_context *gb)& y/ S7 v& G# I& R
  398. {: v  l; K9 e' V8 w4 P- V6 d# B- [
  399.     int vlc;$ U; X8 o5 \; q% b: b* U7 a  K& U+ u0 ~
  400.     int count;
    7 ^; W7 j9 J/ V+ a
  401.     int value;
    5 k! I& T: u( [) y) a7 q

  402. ; ?4 d! Y- N7 s. x
  403.     vlc = view_bits(gb, VLC_SIZE);
    - }$ {6 R0 M9 R5 K
  404.     count = lzs_vlc_table[vlc].count;
    5 k5 Z1 ^2 p) p- B  l7 i2 I2 z3 }
  405.     value = lzs_vlc_table[vlc].value;
    2 f1 P0 Z* H" Z4 Y: q0 F

  406. , R3 Z% n  D4 I+ z) M
  407.     read_bits(gb, count);
    & H8 b# b/ O/ [! |' V- M# a8 C6 Q
  408.     if (value == 8)( f' o8 n9 s/ o
  409.     {/ ~; z( e( A" ~7 M: v
  410.         do% l5 \+ I3 [/ }% h1 u
  411.         {2 }; a' g7 H4 l& X
  412.             vlc = read_bits(gb, VLC_SIZE);# j! I% Z' m3 b4 A! x% e0 t
  413.             value += vlc;
    6 O# t  ^' F$ C% Z6 a* u# b: z1 j
  414.         }( g3 d' T3 v) L# Q7 A
  415.         while (vlc == 0xF);
    4 \- i4 a- {( G; f  l
  416.     }
    5 b% C" V  M6 ?$ l% j

  417. / t; m! S$ C2 K5 l0 }, D1 b' O
  418.     return value;0 s! t( X& I8 M- U: ?
  419. }1 x4 ^1 b; [9 r

  420. , j8 j1 @1 W! @: h
  421. static void compress_window(put_bits_context *pb, uint8_t *full_window,* t5 f  E( b8 v6 @
  422.     int full_window_stride,0 o5 W6 O% I. H$ e& ^: U5 u
  423.     int window_top, int window_bottom, int window_left, int window_right)6 G5 `8 `! l% N3 }
  424. {7 D3 d, R) m. _4 q
  425.     int last_pixel;
    : q" @. p% ~' x( A5 K( Q# j
  426.     int run_size;  u/ H* U" ^+ _0 v/ q7 @# t
  427.     int x;; Q' e3 P$ C! d9 v, u
  428.     int y;
    ) u6 ]/ U2 @/ g; u- Q0 O1 W% o
  429.     int start_index;/ D6 }# P' z) u; L  r* }
  430.     int end_index;$ p4 M4 {2 k+ {2 U# F
  431.     int encode_last_run;
    7 f( c2 B1 M4 C! a2 N
  432. 0 g& M, y/ k2 p+ {8 X: C  T9 p
  433.     last_pixel = full_window[0];; g6 {, \: W7 j1 \. I3 K( |
  434.     run_size = 1;! O  {6 H( a& d. R/ p5 v
  435.     for (y = window_top; y <= window_bottom; y++)
    # }# d5 v0 _$ [. y- b6 S1 t2 m
  436.     {
    5 b8 \7 W% q! V. C) L
  437.         start_index = y * full_window_stride + window_left;' r9 n/ H8 z2 \! p5 T
  438.         if (y == window_top)+ W0 J& L- v) X5 N, \
  439.             start_index += 1;
    0 \: U' _! r' Z( Z
  440.         end_index = y * full_window_stride + window_right;6 O2 T2 ^* ^5 F# P1 U
  441.         if (y == window_bottom)$ G0 h+ {, v0 d4 y" I$ ~) ~) a# n
  442.             encode_last_run = 1;. L5 H: n, w5 h! q$ B& z3 ?
  443.         else6 |  ~  t$ z3 @9 q; q9 R
  444.             encode_last_run = 0;
    & @9 O0 C& M% x2 j% {' E2 U
  445.         for (x = start_index; x < end_index; x++)
    5 G) `6 Y, z/ ]" \
  446.         {4 D; }+ \$ p, |! L" o
  447.             if (!encode_last_run && full_window[x] == last_pixel)! K' F! C) Y5 V) E8 I$ v
  448.                 run_size++;# ]: q) A* q; e3 Y
  449.             else
    4 |/ d  A5 A" m2 I" e+ b
  450.             {5 O) Z% t8 m2 d' q: M: ], c( U
  451.                 if (run_size == 1)# O9 t+ b* |3 U7 s, }3 }' c
  452.                 {
    " F5 f+ B9 o/ X! y7 p
  453.                     /* encode a 0 bit followed by raw pixel byte */
    / {% z7 }9 `; k- ?
  454.                     put_bits(pb, 0, 1);6 Y. M6 ]5 q, w* \9 W8 p. x7 Z& Z
  455.                     put_bits(pb, last_pixel, 8);
    # T( y. q9 u% |' Q8 }1 D8 S
  456.                 }
    0 \! I4 u* h* T7 ]9 K$ Y
  457.                 else if (run_size == 2)
    0 m; ~3 _4 b6 F' m3 d5 s
  458.                 {& y5 S" _' `/ N
  459.                     /* encode a 0 bit followed by raw pixel byte */' ^% Z- S7 d1 v6 C
  460.                     put_bits(pb, 0, 1);
    # b1 L2 F7 x' k9 F
  461.                     put_bits(pb, last_pixel, 8);: X" H: G; ^7 a4 w" f
  462.                     put_bits(pb, 0, 1);* H/ p& r1 o4 ?. p7 ~
  463.                     put_bits(pb, last_pixel, 8);, a0 n" l% R% u$ S; Z/ b7 x8 u6 g8 x
  464.                 }
    9 F# Q; [: v1 U/ e. Z  g: c+ U
  465.                 else3 q4 }: M2 b; k3 w8 k4 H
  466.                 {
    - @$ a- ?6 }% W+ I3 ^
  467.                     /* encode a 0 bit followed by raw pixel byte */
    & p6 O( {' f4 i5 L% H/ C/ \
  468.                     put_bits(pb, 0, 1);) g6 T) V( Q. t" L% h+ l
  469.                     put_bits(pb, last_pixel, 8);1 c7 ^! H6 y: F1 v$ N. O3 T+ h7 Z
  470.                     run_size--;
    : p) X5 Q1 G/ T4 D% F8 u
  471.                     /* encode a run: a 1 bit, followed by a back reference5 \; Q! t! d, n6 n$ U9 b
  472.                      * offset (-1), followed by a length */4 d* j- t; a8 R5 U( S
  473.                     put_bits(pb, 1, 1);6 L' P( Q# f% s8 g8 t' U
  474.                     put_bits(pb, 1, 1);  /* 1 = 7-bit offset */
    5 T4 T0 o3 C2 U, @" ^/ y( w
  475.                     put_bits(pb, 1, 7);6 }; T  V% M. o  P$ A5 @6 O
  476.                     if (run_size <= 4)3 \+ h; V# G8 {5 ]
  477.                     {
    : \6 L2 A- h3 s4 t3 L! p; D& t
  478.                         /* lengths 2, 3, and 4 are 2 bits */% v2 n% \: z" f1 g# ^9 Z
  479.                         put_bits(pb, run_size - 2, 2);
    ( }( ^5 w" Q* R0 g6 q; o3 S! \5 U
  480.                     }1 T8 z  G0 p- A2 m$ r
  481.                     else if (run_size <= 7): z0 s, x" w& J' b. `" G
  482.                     {
    7 U4 n/ D* y( C+ p) x: I
  483.                         /* lengths 5, 6, and 7 are 4 bits */0 j4 D% @6 g$ s- ?
  484.                         put_bits(pb, run_size + 7, 4);
    2 g; }5 o' Z8 ^6 u/ _8 q
  485.                     }
    : l) ~8 J: k( \# j
  486.                     else
    4 A* ]" I4 m: a
  487.                     {
    + A8 z- Q, [) y2 p8 B1 E+ {/ y) r6 |
  488.                         /* arbitrary length; start by encoding 0xF which
    7 u% {5 q/ D& S! _/ o6 Z% l
  489.                          * stands in for an initial version of 8 */5 q% _3 l" [; m$ o" l8 p
  490.                         put_bits(pb, 0xF, 4);
    , H, ?1 s% W# d- a' H8 u. k
  491.                         run_size -= 8;$ E4 i! g" T+ T( {" m3 u5 ^' M
  492. ' ^+ l; j- C9 F+ ^* Y
  493.                         /* encode blocks of 4 bits until run_size is 0 */
    ( T# b$ G0 }6 b0 ~' F6 V
  494.                         while (run_size >= 0). Y3 m/ |! J  e$ p1 \
  495.                         {
    7 ^1 {( u: g% c5 p
  496.                             if (run_size >= 15)4 D0 P: u6 Z: P* {6 W/ b% a
  497.                             {2 j9 V2 O- P$ C" K2 h9 T. T6 t
  498.                                 put_bits(pb, 0xF, 4);" t9 P1 q4 ?2 t( o5 q
  499.                                 run_size -= 0xF;
    - `, x/ S, `* \- i# E$ m9 b/ h
  500.                             }- o1 J4 U' T: p& `- i: ^# g
  501.                             else( d4 F4 K9 `8 D8 z" f6 B5 n; u9 J
  502.                             {/ V1 b0 E( i$ p5 d2 p, {
  503.                                 put_bits(pb, run_size, 4);
    : R5 W9 t6 |! N
  504.                                 run_size = -1;: j' P& m' g, h$ e5 O5 x
  505.                             }
    - }8 x: P, }5 ~- C9 g
  506.                         }
    + {3 O7 v( v/ I4 t
  507.                     }
    : C9 q; ?3 Z+ n3 h/ W
  508.                 }
    8 b8 R, p; P1 p. J6 T" L* W  F

  509. : N( _8 |& R7 y
  510.                 last_pixel = full_window[x];
      v3 W( N, a/ H! ^6 {4 H0 A
  511.                 run_size = 1;
    3 ^2 x4 g  m$ Q5 w+ U
  512. / y- |. a# I3 Q
  513.                 /* this single x iteration was only here to close the final run */: d9 N( u6 u, ?' g& E
  514.                 if (y == window_bottom)8 s: o- F9 r+ E& A: g7 q# m0 K4 o
  515.                     break;- ~- j. ?+ N6 i8 R2 d" I
  516.             }
    4 E7 T& _. k/ G4 K) v3 {" |
  517.         }
    6 `: L4 `/ j3 Q1 b; T: u3 l9 \
  518.     }$ I0 F% ]. ]+ Z7 b6 c' ]

  519. , v4 E# j: }5 A
  520.     /* close the bitstream by encoding a back reference with length 0 */1 O2 I5 \  w# [: H- t4 v
  521.     put_bits(pb, 1, 1);  /* back reference run */1 ^9 D3 \: }4 T
  522.     put_bits(pb, 1, 1);  /* 1 = 7-bit offset */
    ' U1 b% S, T  m. N! g5 u
  523.     put_bits(pb, 0, 7);  /* length 0 */9 ^& p7 h+ t; }
  524. % r' d/ W: H6 U6 _
  525.     put_bits_flush(pb);
    / [0 C5 A0 T% [* w0 f& f
  526. }
    4 [% u* w0 _7 ?4 X
  527.   d( r; ^. g. s) t7 W9 R) V
  528. /* compute Euclidean distance between an RGB color and the desired target */: t( [+ Y! x# F5 y$ ^) T
  529. static int compute_rgb_distance(int r1, int r2, int g1, int g2, int b1, int b2)8 l- p6 z2 r" p4 F
  530. {' O5 ]; m7 v1 Z- s! A& _$ ~
  531.     return sqrt((r1 - r2) * (r1 - r2) +
    ) V0 P* {/ _" c
  532.                 (g1 - g2) * (g1 - g2) +
    3 V0 I+ g( h" k0 |$ K& L) E
  533.                 (b1 - b2) * (b1 - b2));9 G4 S. P; k8 g& ^: j& G# o/ P7 ^
  534. }4 H" c% q/ m# V
  535. 4 z3 a  c3 ?9 y( x9 G8 Z% E
  536. static uint8_t find_nearest_color(rbt_dec_context *rbt, int r, int g, int b); R/ @; @' z) Y  \. C  @' Q6 r
  537. {; W/ c3 k2 R* C
  538.     int i;; U3 z, d" A4 _2 V+ [" ?8 A( j
  539.     int nearest_distance;
    8 P; r; S9 l* d  z, I! P2 h
  540.     int distance;, i; d: w. u7 }0 U; C
  541.     int rp;& }8 i7 j0 R' S5 l4 X4 Q" W
  542.     int gp;/ ~" I3 z5 V* j' _3 {1 E
  543.     int bp;
    0 C, P3 K  w6 g
  544.     uint8_t palette_index;
    8 s. O' a+ ^5 ?9 Q8 t
  545. & C2 c$ D' L  ~3 f- T4 y
  546.     nearest_distance = 999999999;
    9 k) S2 [/ I5 l) f
  547.     palette_index = 0;
    6 {0 N" {8 }/ G
  548.     for (i = 0; i < 256; i++)
    : `% b: F5 R8 w" L1 E) \- P* J
  549.     {
    + B. B$ }  L0 g/ S
  550.         rp = rbt->palette[i * 3 + 0];
    # X7 ]% {$ D/ ]- U$ w/ u$ ^* H2 w7 l
  551.         gp = rbt->palette[i * 3 + 1];
    ; ^) I+ ~, k' o' V
  552.         bp = rbt->palette[i * 3 + 2];
    4 ^# j7 y0 U$ S9 D
  553.         distance = compute_rgb_distance(r, rp, g, gp, b, bp);5 H8 Z3 u7 Y! J
  554.         if (distance < nearest_distance), [& ^- D; n- I
  555.         {: d# k* h) U- g2 ~6 x5 V! D
  556.             nearest_distance = distance;
    $ k4 o. i  H+ R
  557.             palette_index = i;% ], z/ W0 J4 V% u9 k' q
  558.         }
    3 u, H$ m% }- f+ |
  559.         /* can't get closer than 0; break early */
    * L2 {% n0 \- N( M% Y
  560.         if (distance == 0)- ?( w# T. c; A
  561.             break;
    4 C2 m) P0 `* j0 {
  562.     }4 F; W5 g$ u( W7 Y+ {

  563. 1 w, l9 Z) v& w0 F- b& S
  564.     return palette_index;' Z( v4 U! t  f! F* J( X. s. v; C
  565. }
    6 p3 L: c5 G+ }) r8 N2 {
  566. " m: ~! `9 `8 j3 }
  567. static void subtitle_frame(rbt_dec_context *rbt, uint8_t *frame,  f; x% g) h; V7 G2 t! |% F
  568.     int width, int height, int timestamp)
    . I% o9 Q+ Y7 O) X) V
  569. {1 f' o5 x. z" m  I! R
  570.     ASS_Image *subtitles;
    ' m8 N0 \8 Z3 Q
  571.     int detect_change;2 Z6 S5 `) ]5 Y5 v% ?5 }  {" P2 s
  572.     uint8_t subtitle_pixel;! A  ]; z' O- @
  573.     int x, y;% p, I5 s+ x; @
  574.     uint8_t *frame_ptr;
    % T1 v0 }5 x. y" k2 {
  575.     uint8_t *subtitle_ptr;% s" e2 f' y; B8 o, O/ Q

  576. # E- c& w& x% i! r3 `* Z
  577.     /* ask library for the subtitle for this timestamp */
    ; {+ J5 u" l8 @: U; E4 Z. `
  578.     subtitles = ass_render_frame(rbt->ass_renderer, rbt->ass_track,
    - n  m  r. i# s: C% `* M; R- A# M
  579.         timestamp, &detect_change);2 @* n: z9 ^1 ]8 ^

  580. 5 _0 [9 i1 u! O
  581.     /* render the list of subtitles onto the decoded frame */3 e$ U5 o. ~1 I0 x8 N- v; Z
  582.     while (subtitles)
    . c7 X5 U, I0 p2 i
  583.     {, C2 D/ Z' C- W8 {
  584.         /* palette components are only 6 bits, so shift an extra 2
    / ~3 `$ S: c7 Q1 |" [
  585.          * bits off each component */& V4 n) {- C$ c$ L3 E; P
  586.         subtitle_pixel = find_nearest_color(rbt,
    2 t) g( r0 ]- `; c. K  P. w9 Q7 K
  587.             (subtitles->color >> 10) & 0xFF,
    ) J. t& e3 Q: C1 l
  588.             (subtitles->color >> 18) & 0xFF,0 ]# w) \) Y; l0 v2 J/ j- q. Z5 O. u
  589.             (subtitles->color >> 26) & 0xFF);; U2 y* p. m4 J9 c9 a/ H) H
  590.         for (y = 0; y < subtitles->h; y++)3 g* J9 G$ N$ w/ \: \' s2 L
  591.         {3 [# ^! m* l" u
  592.             subtitle_ptr = &subtitles->bitmap[y * subtitles->stride];
    6 U' H0 u% x2 a
  593.             frame_ptr = &frame[(subtitles->dst_y + y) * width + subtitles->dst_x];
    # p$ b- \4 H* M4 W6 o
  594.             for (x = 0; x < subtitles->w; x++, frame_ptr++, subtitle_ptr++)
    $ @8 W) K0 E4 }3 }$ S
  595.             {- v  ^& }0 A+ p4 u: p0 g8 |5 z/ k) }
  596.                 if (*subtitle_ptr >= SUBTITLE_THRESHOLD)$ W; U3 m3 @9 M5 ]
  597.                     *frame_ptr = subtitle_pixel;
    " I6 G2 D6 I8 {3 g0 i
  598.             }
    1 @3 v. k* J5 L6 C# W
  599.         }
    : `) u5 y* a* v7 r6 B! c
  600.         subtitles = subtitles->next;
    7 y7 h0 o! ~( w7 v
  601.     }
    0 E' m2 g- z2 Y; h
  602. }
    6 n  h( @3 [/ @1 t/ W( {

  603. + z7 a& {. a/ E5 ^" E8 ~$ ]" C! t
  604. static int copy_frames(rbt_dec_context *rbt, FILE *inrbt_file, FILE *outrbt_file,7 j/ E- j4 n9 ~* k
  605.     int origin_x, int origin_y, int window_width, int window_height)
    9 [; n- ?# R/ q0 [- H
  606. {0 y& Z4 c5 p& f' Y
  607.     int i;( |9 p' u* W2 B+ _0 Q! l
  608.     int j;
    ) r2 w3 C! ^# I) e7 F7 b
  609.     int scale;' d4 j+ B: Q( k% b  j+ h- R! K
  610.     int width;- u4 ?# m0 L4 e' Y8 m+ g6 x0 }
  611.     int height;" E7 O" z: j+ [2 D- E# S' O3 F/ U, Y
  612.     int max_width;
    / J& C) s0 o! \+ ~' G
  613.     int max_height;% P9 p) u$ z4 N: t$ Q
  614.     int frame_x;
    # Y3 K% g0 k) A1 E
  615.     int frame_y;9 a4 D& V2 c' e/ n9 E; V7 }
  616.     int fragment_count;9 |3 f9 ~! Z; e- Q! N' x( d6 i5 B
  617.     int decoded_size;) Q; p4 \8 N0 J' }5 R2 o9 t
  618.     uint8_t *decoded_frame;  F! D$ y3 F" d9 h, V, s
  619.     int fragment;6 G. _5 ^5 a4 `/ r; I
  620.     int fragment_compressed_size;" W* w7 {: a* K& U7 W: t: Z
  621.     int fragment_decompressed_size;
    ; S* b& K& i' W
  622.     int compression_type;
    : i  p* r1 Q6 p0 V7 J- q' a
  623.     int index;9 X" s6 b/ N9 l) K- [
  624.     int out_index;
    + _/ v& `  e9 W% W5 b. [* Z8 j
  625.     get_bits_context gb;
    / j  B' F  F; D! ~& d8 u
  626.     int frame_size;
    ) s0 r4 R4 b' P3 y8 C
  627.     int video_frame_size;
    ! M0 Y5 S1 S& w! A1 Q  i
  628.     int audio_frame_size;/ Y( E: J( I: j
  629. 7 Z* p- i( Z5 C: f: H" {4 P* g
  630.     int back_ref_offset_type;- t6 i2 h$ t" ~$ |$ w! Q
  631.     int back_ref_offset;# G5 n' A( `0 U/ Y# l8 p, r
  632.     int back_ref_length;
    ) O! J& ~) q/ g! y" e% W
  633.     int back_ref_start;9 z; K: w3 D' z8 s) f
  634.     int back_ref_end;- D! J7 L8 s( Z

  635. - Q, e5 ^( c  _3 X5 E7 e; x
  636.     uint8_t *full_window;; r) R+ T) t- t% c7 s
  637.     int full_window_size;
    : e3 l7 N5 i0 H4 g" ]( ~
  638.     int y;
    : J3 o/ p4 e$ F' V/ s% k
  639.     int window_top;$ Z+ s/ X% P. @' i$ S
  640.     int window_bottom;
    7 Q( P5 z* N# x6 y  B# k
  641.     int window_left;
    5 C8 ]- a" h3 r2 D, j: V/ ~
  642.     int window_right;
    5 f  R0 }! \3 p9 i) B$ w' {
  643.     int window_size;
    7 B5 F4 h  j, W

  644. 9 Q( k8 h( m0 B
  645.     char filename[30];8 p) h0 C- ^! j, O7 n4 P
  646. % e6 g. m* d; {/ L# }8 k
  647.     put_bits_context *pb;& v9 q7 K. L! }9 V- D

  648. * a/ l0 j5 L& L% L7 j$ H8 P0 q
  649.     full_window_size = window_width * window_height;
    * z8 E, C5 u. t6 z! C. v2 F
  650.     full_window = malloc(full_window_size);. P# Y( {" g" s* M# i  S
  651.     pb = init_put_bits();9 [+ t2 l% x( l3 ?0 R

  652. + \# ^, z, K* H! y4 {1 ~
  653.     max_width = 0;* @% n/ S5 f! `' S# z
  654.     max_height = 0;2 r4 T: q* O" r& ]% ?7 I$ e
  655. ) ?4 j: W# [- y8 z
  656.     for (i = 0; i < rbt->frame_count; i++)
    ) [  R( x* i' e
  657.     {
    ) k% d1 W( V1 p) u) `# p3 m" I
  658.         /* read the entire frame (includes audio and video) */
    4 H7 u$ y; ^" O' P+ C7 C/ L5 c0 ]
  659.         frame_size = LE_16(&rbt->frame_size_table[i*2]);
    8 Z8 Y6 a+ ]- t* i
  660.         video_frame_size = LE_16(&rbt->video_frame_size_table[i*2]);
      \% S$ s5 W, D, ^+ p; s. r
  661.         audio_frame_size = frame_size - video_frame_size;2 f  R2 z$ Q2 u3 L, p& J
  662.         if (fread(rbt->frame_load_buffer, frame_size, 1, inrbt_file) != 1)
    / L( O; o+ L# @8 p; i8 r7 ?* K
  663.         {
    + K- P5 q# I( R8 N! R  X1 B
  664.             printf("problem reading frame %d\n", i);! a* D6 g) [/ k% S7 ]
  665.             return 0;
    9 F* [$ T9 x  a% P7 ~
  666.         }( K# {& e+ _7 j5 w
  667. 5 p. N7 L$ d- g9 O
  668.         scale = rbt->frame_load_buffer[3];
    # m1 r( j- c3 t8 v+ f, b2 v+ V; m
  669.         width = LE_16(&rbt->frame_load_buffer[4]);3 b6 z8 h) v) x0 i7 Q( C
  670.         if (max_width < width)6 G2 P% m; U- _3 J
  671.             max_width = width;
    ' S& `3 O  I5 m, Y& b6 ]. {) }
  672.         if (max_height < height)
    , G0 o: \  y/ c  S9 k+ m  G: g5 w
  673.             max_height = height;
    - d% F9 s0 ~! Y3 Q0 X
  674.         height = LE_16(&rbt->frame_load_buffer[6]);9 X/ F$ s- C) T0 x
  675.         frame_x = LE_16(&rbt->frame_load_buffer[12]);8 e. T7 k% w7 b, U$ u
  676.         frame_y = LE_16(&rbt->frame_load_buffer[14]);$ n' Q0 `; B: e1 C
  677.         fragment_count = LE_16(&rbt->frame_load_buffer[18]);3 [, |5 g3 N/ b+ U3 ~- N
  678.         decoded_size = width * height;9 G: e0 O, p) f/ @: d0 s: x
  679. / u, }/ N# ~6 d2 i7 _
  680.         printf("processing frame %d: %d%%, %dx%d, origin @ (%d, %d), %d fragments\n", i, scale, width, height, frame_x, frame_y, fragment_count);
    & P9 r+ q% t' x5 s2 j" M8 T0 d+ g
  681. ( [: d* [. W3 D+ ~! N
  682.         /* decode the frame */
    + ~- A9 S! X' Y3 L2 ^6 k' L+ w; v
  683.         decoded_frame = malloc(decoded_size);' Z! L9 Q: o9 Y; O- _
  684.         index = 24;! {" N: _3 o, i3 Y# f! m# V
  685.         out_index = 0;. d8 i, u% f( A! O/ Z
  686.         for (fragment = 0; fragment < fragment_count; fragment++)0 k: D& l+ J+ P9 {8 P2 G
  687.         {
    ) F: _; ?, e* G( ?7 D! c! A
  688.             fragment_compressed_size = LE_32(&rbt->frame_load_buffer[index]);
    3 X* o( `7 C( a$ G6 J
  689.             index += 4;+ W1 Z! }& T. @/ `' Y; o3 w
  690.             fragment_decompressed_size = LE_32(&rbt->frame_load_buffer[index]);
    7 M7 L$ ^/ o7 [% w6 F" L& y9 x
  691.             index += 4;4 W& J* J( i1 O3 \& v9 s  w1 M' O; k
  692.             compression_type = LE_16(&rbt->frame_load_buffer[index]);
    ( Z! \% O" o) _
  693.             index += 2;9 u# c( z) m1 r: ^1 }2 w

  694. & O6 y: c4 |% g* w$ H$ K
  695.             if (compression_type == 0)
    1 T6 a9 `; H5 V6 }1 Y& a7 ~$ i
  696.             {* a% s% F4 y' R) ~
  697.                 init_get_bits(&gb, &rbt->frame_load_buffer[index],+ ?2 X& R$ N; t4 S0 C
  698.                     fragment_compressed_size);
    6 k3 v4 ]( U8 {0 u9 d

  699. 2 k; X, c; a2 A% j+ `4 K$ J* U
  700.                 while (out_index < fragment_decompressed_size)
    , M1 b( o1 x9 b7 }: F5 U# c
  701.                 {
    8 c4 v! j; k& e: I
  702.                     if (read_bits(&gb, 1))
    8 b+ T7 v$ z9 T" g5 i+ s
  703.                     {# J% V- H2 N6 H+ W
  704.                         /* decode back reference offset type */( ~: g- t8 T2 m
  705.                         back_ref_offset_type = read_bits(&gb, 1);# d) X. n$ x/ K. Q
  706. + ~( B6 c, ~% I+ I! V
  707.                         /* back reference offset is 7 or 11 bits */
    5 `0 |7 ^6 Y4 V6 w. g5 R' B
  708.                         back_ref_offset = read_bits(&gb,
    $ v% e( c) A' `; _' J5 W
  709.                             (back_ref_offset_type) ? 7 : 11);8 h/ T7 ^/ @" s

  710. # o4 L+ C6 H. Z5 n. Y9 G
  711.                         /* get the length of the back reference */
    2 m8 l6 {+ [* v; m4 t
  712.                         back_ref_length = get_lzs_back_ref_length(&gb);$ t3 q* N" t5 a
  713.                         back_ref_start = out_index - back_ref_offset;
    ' y. ~* m+ n- r$ n+ M# x) ^
  714.                         back_ref_end = back_ref_start + back_ref_length;
    4 R( {- V4 H8 Z8 Y! U

  715. 9 B& y  U0 w+ t" H; U. T
  716.                         /* copy the back reference, byte by byte */
    9 ?& E9 c1 a9 ^6 S$ e% T& d
  717.                         for (j = back_ref_start; j < back_ref_end; j++)2 t+ q% i: v8 g  ~
  718.                             decoded_frame[out_index++] = decoded_frame[j];, R3 J. [/ Y2 x- x& S
  719.                     }
    0 L  V" N  J" H$ w& h1 o9 u) ?
  720.                     else7 T4 Q( d4 j  m: _
  721.                     {/ Q$ t+ \9 j, i+ l4 T2 Q7 a
  722.                         /* read raw pixel byte */1 c+ l) ?' a1 i7 ~
  723.                         decoded_frame[out_index++] = read_bits(&gb, 8) & 0xFF;9 S* a, B, O% W
  724.                     }
    ) `, u, L/ v5 Z6 c% L* b
  725.                 }) g; p* D! I; i7 \  |% S5 P& D4 ]
  726. * b: b: s9 o" I6 \9 l# ^
  727.                 delete_get_bits(&gb);
    ' [7 P9 [+ C( w% S; Z1 o. Q; o
  728.             }2 `+ ^4 a7 x" f9 t# e1 P8 `

  729. 3 S% g8 ~9 d% X4 d5 R
  730.             /* next fragment */
    1 F! Y- d" d& E: G. w( J& `$ v; W
  731.             index += fragment_compressed_size;$ O  w, W& x/ t* u. k& {
  732.         }
    , u1 L/ g; [$ e1 [& m& P+ }0 E
  733. : o  U/ Y- m- s' {, u5 @: Z( X
  734.         if (rbt->dump_frames)% b5 T9 R; j; x( Y
  735.         {
    . j1 w$ d; Y4 l" r- m0 r
  736.             /* dump the original frame */# N* f9 [& |+ c; v3 m+ |
  737.             sprintf(filename, "original-frame-%03d.pnm", i);
    , l  f: u6 H9 ^# [9 z# B7 e+ D* E
  738.             dump_pnm_file(filename, rbt, decoded_frame, width, height);- {6 B$ h, R2 p7 l
  739.         }
    1 b; T% [; z  k1 W3 d9 K# v
  740. : i, g7 ~( \: U5 X/ m! Y
  741.         /* transfer the image onto the frame window */
    ' Y' f' X: o# s4 G6 p
  742.         memset(full_window, 0xFF, full_window_size);3 h) q/ w  S4 T; j2 s5 q
  743.         index = 0;
    , r- k' X( Q* j4 C, ?: X1 I# b
  744.         for (y = 0; y < height; y++)
    " f9 x1 K9 e, y$ P3 V0 [, I
  745.         {; a* i8 S# c: v8 i! e- L
  746.             out_index = window_width * (frame_y + y) + frame_x;
    8 @$ I# w0 F8 A, o
  747.             memcpy(&full_window[out_index], &decoded_frame[index], width);
    * X( K; G& C3 j9 c
  748.             index += width;
    9 n( O& [( m7 B1 G: U1 |
  749.         }: r3 f! v: l- g& A1 @; P# _- u+ j

  750. 3 r5 }, M9 R+ R7 W( `
  751.         /* write the subtitle */
    ) ?+ @# `0 s: x% K" h2 ?
  752.         subtitle_frame(rbt, full_window, window_width, window_height,, o8 f0 E9 M$ \% e9 O( l( \
  753.             i * MILLISECONDS_PER_FRAME);( v' M1 a/ r- o, O$ d$ T
  754. & ]  h7 j7 k; k" v$ m) x! g
  755.         /* figure out the smallest change window */
    . v2 F% d' |9 Q. ~1 r
  756.         window_top = frame_y;
    " u' f+ y- x: i
  757.         window_bottom = window_height;5 N# Y) V4 H& g' |5 |8 X
  758.         window_left = 0;
    1 y. y6 [; c5 F
  759.         window_right = window_width;; v- u/ k1 M1 m- H) r
  760.         window_size = (window_right - window_left) * (window_bottom - window_top);
    + i% L  \8 _' ^

  761. 2 L; g+ J& T8 k/ M$ _
  762.         /* compress the frame */
    , a$ y) ?3 @; L& u  _* H4 o# J% g* H
  763.         reset_put_bits(pb);, N. b8 R& b$ Y! v8 t
  764.         compress_window(pb, full_window, window_width, window_top,
    ' Z; p+ m% [0 K( A" P
  765.             window_bottom, window_left, window_right);, |# `$ Y/ u1 p' C9 l
  766. ) A! }4 R) k  A2 t5 S0 j
  767.         if (rbt->dump_frames): k2 v$ J, A8 B/ _( W3 Y
  768.         {
    ! ?( R9 e5 k  E& ]5 G
  769.             /* dump the frame plotted onto the full window prior to encoding,; u6 q* @9 O2 B2 S; I) _5 ~
  770.              * with subtitle */
    8 D2 |" e( y( Q9 O- t% t
  771.             sprintf(filename, "pre-encoding-frame-%03d.pnm", i);, y+ j# F* u) S* i$ c
  772.             dump_pnm_file(filename, rbt, full_window, window_width, window_height);: d: Z# S% f. `3 `. A6 n9 k1 N
  773.         }
    . _% C5 G4 V, f  M5 W6 c
  774. 2 }8 w* m3 m: |2 E
  775.         free(decoded_frame);1 h7 x9 {9 t8 ~
  776. & Q2 j5 v' p4 X- l$ w: C6 O4 p
  777.         /* update the frame header */
    & x) E! x7 `) Q7 i, x8 P; x
  778.         /* width */
    2 }( l) u3 r) R1 e
  779.         rbt->frame_load_buffer[4] = (window_right - window_left) & 0xFF;& F( \( a8 {1 n! t- Z- i! A
  780.         rbt->frame_load_buffer[5] = (window_right - window_left) >> 8;
    ! |1 ~1 P/ Q2 L$ v
  781.         /* height */( G# P, ~6 o) o9 B3 e
  782.         rbt->frame_load_buffer[6] = (window_bottom - window_top) & 0xFF;
    & j4 E3 [" `6 H) v) H2 n; M
  783.         rbt->frame_load_buffer[7] = (window_bottom - window_top) >> 8;7 l. ]# H0 A/ J1 B( p
  784.         /* origin X */
    ) O( g$ Z# t& ]4 c& d; e6 h) K1 z
  785.         rbt->frame_load_buffer[12] = window_left & 0xFF;
    + ?2 S* C* N6 e, j$ \
  786.         rbt->frame_load_buffer[13] = window_left >> 8;
    3 Y6 s0 X! I2 m9 g3 U1 k( c' o
  787.         /* origin Y */
    # C0 a$ v  f8 q7 y0 r7 _* E
  788.         rbt->frame_load_buffer[14] = window_top & 0xFF;
    / }# X- X' D5 S
  789.         rbt->frame_load_buffer[15] = window_top >> 8;  x" C8 M0 [. Q: p
  790.         /* fragment payload size */+ L& t8 d; ~% U+ [
  791.         rbt->frame_load_buffer[16] = (pb->byte_index + 10) & 0xFF;
    % f2 e7 I6 t+ D% y6 Z) r0 i7 l
  792.         rbt->frame_load_buffer[17] = (pb->byte_index + 10) >> 8;
    4 U. X  H: i' l8 t7 a
  793.         /* fragment count (1) */# U; m# p8 x7 B1 C, g9 D' }9 W, }
  794.         rbt->frame_load_buffer[18] = 1;
    + r% x) V! l6 l  w! _4 S1 h! ]: G. \
  795.         rbt->frame_load_buffer[19] = 0;* Z6 M6 \8 Y% ?; s6 d7 H
  796. 2 L' o6 i  [" k( f& i. T6 K& i
  797.         /* update the fragment header */6 A6 d& a# B- q
  798.         /* compressed size */
    6 ~1 l, _4 h0 q( ]1 R; v
  799.         rbt->frame_load_buffer[24 + 0] = (pb->byte_index >>  0) & 0xFF;5 t+ s" W$ `- B4 \7 o
  800.         rbt->frame_load_buffer[24 + 1] = (pb->byte_index >>  8) & 0xFF;
    & D( J, F" ~* a; A# t; F
  801.         rbt->frame_load_buffer[24 + 2] = (pb->byte_index >> 16) & 0xFF;- V/ W4 D" z' E+ Y& h) D
  802.         rbt->frame_load_buffer[24 + 3] = (pb->byte_index >> 24) & 0xFF;& `3 ^! e" c) [( V
  803.         /* decompressed size */
    9 Y  A" m! g2 u
  804.         rbt->frame_load_buffer[24 + 4] = (window_size >>  0) & 0xFF;
    ' G; z: w. a+ X8 c8 {
  805.         rbt->frame_load_buffer[24 + 5] = (window_size >>  8) & 0xFF;, ?# N) ?/ a' W, P  N
  806.         rbt->frame_load_buffer[24 + 6] = (window_size >> 16) & 0xFF;8 @* Y( }- q* j" M# \/ ]
  807.         rbt->frame_load_buffer[24 + 7] = (window_size >> 24) & 0xFF;
    9 ]9 u5 Z% }& ^% d# a
  808.         /* compression format 0 */
    3 v, f9 W3 K( @
  809.         rbt->frame_load_buffer[24 + 8] = 0;
    2 p+ C7 z, H) b4 M( H5 x+ R' E. i
  810.         rbt->frame_load_buffer[24 + 9] = 0;* S6 z& D8 v2 i9 H' M
  811. 5 H* I9 a- \: \4 P; J
  812.         /* write the 24-byte frame header and the 10-byte fragment header */
    3 O4 L! T# K9 k! [, u8 t2 G9 ?- U! E2 v
  813.         if (fwrite(rbt->frame_load_buffer, 24 + 10, 1, outrbt_file) != 1)
    & b7 c# q- {# h' F' T( d7 ~
  814.         {: Z8 h% G1 w% {1 }4 [# W
  815.             printf("problem writing frame %d\n", i);
    . P8 z- Y* \2 j% E6 Z1 ^. @, H5 T" ~
  816.             return 0;0 |' t" b) C6 d0 q
  817.         }6 Y5 j+ `" `' f# A) Y
  818. + G" Y% p- R* J  E
  819.         /* write the new compressed frame data */
    9 Z6 R7 m+ @0 |. ~7 X3 X/ x8 n1 g
  820.         if (fwrite(pb->bytes, pb->byte_index, 1, outrbt_file) != 1)
    ! R7 |  o, M/ c& F1 W" a8 k
  821.         {
    * e6 Z. K" ?  z
  822.             printf("problem writing frame %d\n", i);
    ( J  [" o( R1 b5 u- \/ d# J- B
  823.             return 0;
    + r3 T* [# K, e8 P" U; ]
  824.         }
    ; ~3 q" Y8 m; `5 I
  825. 2 ^, Z& m- T+ H0 K- B+ U0 q
  826.         /* write the audio data *// A' i: V4 B, Q1 w3 r& S
  827.         if (fwrite(&rbt->frame_load_buffer[video_frame_size], frame_size - video_frame_size, 1, outrbt_file) != 1)
      J& R' D/ \: D& m. r
  828.         {1 U1 V! P" t  H2 ]7 S
  829.             printf("problem writing frame %d\n", i);" [! E& L# D+ X& y) i/ m
  830.             return 0;
    . w3 P: B: ^' R7 z% g  ?
  831.         }+ a. L# V6 ~- T& X3 e' Q

  832. * ~& H4 W2 l+ L- n+ E
  833.         /* update the table entries */8 g! M; C, E- {
  834.         video_frame_size = pb->byte_index + 24 + 10;% ~  o5 _0 s4 o& A, H5 T
  835.         frame_size = video_frame_size + audio_frame_size;" j! I# V0 N  ^4 }
  836.         rbt->frame_size_table[i*2+0] = frame_size & 0xFF;
    : k1 z9 T2 c8 L+ ?8 f' I5 d  e
  837.         rbt->frame_size_table[i*2+1] = frame_size >> 8;5 Q8 T/ O$ M0 w* Z/ _2 k7 @9 V
  838.         rbt->video_frame_size_table[i*2+0] = video_frame_size & 0xFF;; Z% D+ y6 A, Z: v; H; L
  839.         rbt->video_frame_size_table[i*2+1] = video_frame_size >> 8;3 @, I5 y1 [9 x* s8 O/ F
  840.     }
    2 l9 D% v0 M9 f, G$ J

  841. 0 @8 O' G9 @) a5 B6 ]0 ~" F4 E
  842.     printf("maximum dimensions seen are %dx%d\n", max_width, max_height);
    ' p9 [' M; c" _% g8 X
  843. 1 l% {8 p+ t" z+ S6 I. x  B
  844.     delete_put_bits(pb);7 P0 }4 W0 V2 C6 n; g, r
  845.     free(full_window);8 W  J, k, O8 k0 }! ~! M. t) R

  846. 5 D5 g' g( N; n) j9 M
  847.     return 1;) D/ v9 n) Z4 `  t' g
  848. }
    5 h8 k) ?, m" P6 B3 T, P

  849. , L, U/ |+ w3 L
  850. int main(int argc, char *argv[])/ I) K" Y9 \% |% ^0 a8 G5 @
  851. {
    9 C$ ]7 L9 r% @1 W. z2 _( @
  852.     char *subtitle_filename;& e6 L( P$ e8 r6 B  a
  853.     FILE *subtitle_file;
    , V5 M9 B$ |4 d, }- M% n8 p
  854.     char *inrbt_filename;* b8 }  h+ D* L) d$ ^6 B) J
  855.     FILE *inrbt_file;7 u2 _1 B$ @: P9 r( y& v- M
  856.     char *outrbt_filename;
    4 I  p% g! ~# K
  857.     FILE *outrbt_file;
    0 o7 b7 v0 J7 s6 u& R
  858.     rbt_dec_context rbt;
    # y& T# t! R9 p4 k) B7 i% c5 u
  859.     int origin_x;4 }# D% D: R8 o( V) T  c8 {
  860.     int origin_y;
    $ ^& n, k, F# t( b
  861.     int window_width;2 u! p$ b) B  B. C
  862.     int window_height;
    8 A* L% d: C- u7 Y6 |" \4 I! i

  863. - ]1 `6 M7 d- W+ P/ S
  864.     /* testing the bit functions */" v4 g3 a& P2 K7 p
  865. #if 0
    9 W6 Z$ ~( c& v9 _6 @+ K
  866.     int i;7 E$ ]3 n- q5 L8 X( P( A$ D
  867.     uint8_t bytestream[] = { 0x55, 0xAA, 0x00, 0xAA, 0x55, 0x77, 0xFF, 0x1B, 0x70, 0x8F };  ^: V3 i* I7 B1 o3 c" T0 [
  868.     int bytestream_size = 10;
    ; |- {. g+ K3 c
  869.     get_bits_context gb;
    / D/ F8 r4 U& @+ G# j- A- i
  870.     put_bits_context *pb;6 d8 q8 y; k' T1 U' r. G6 k1 Y, I. n
  871.     int bits;/ v6 z7 `; Z  D! s- t! d9 [0 D: ^

  872. : c7 q( l. Y; H& e5 Y* z
  873.     init_get_bits(&gb, bytestream, bytestream_size);
    5 f+ S9 S. p3 ?* ~$ n$ h6 s3 L
  874.     pb = init_put_bits();- p  |( {% E) p& ~

  875. 0 c9 Z1 S# q. y4 n% Z( w
  876.     for (i = 1; i <= 12; i++)7 E; G! O$ t$ a
  877.     {
    * ?( b1 n+ L% Z7 Z
  878.         bits = view_bits(&gb, i);. M# x0 w5 C0 Z
  879.         printf("view %d bits: %d\n", i, bits);* n+ P( A- A2 r9 P! H& Z" O9 ^5 G
  880.         printf("read %d bits: %d\n", i, read_bits(&gb, i));
    9 [8 U% ~4 L, }- I+ Q
  881.         put_bits(pb, bits, i);
    3 X& s+ H  k' S6 V+ `5 e4 z6 F
  882.     }
      s1 K5 y! s2 P# p# E( v% N
  883.     put_bits_flush(pb);3 r# W' [4 y' c/ B1 j

  884. / c2 \9 s3 ~( M" N! g% H0 V( m* H
  885.     printf("original bytestream:\n");8 {0 B; [, f8 y& Z' J
  886.     for (i = 0; i < bytestream_size; i++)/ R/ a2 T0 z3 F8 P% ^  a7 `) d- z
  887.         printf(" %02X", bytestream[i]);$ z" r- l- ?  ~* P
  888.     printf("\nnewbytestream:\n");4 W# `$ U' d6 G- N
  889.     for (i = 0; i < pb->byte_index; i++)
    , T" [( O. T$ o* \' ?  _5 \
  890.         printf(" %02X", pb->bytes[i]);  H. I: S4 [; I3 s
  891.     printf("\n");7 V+ w- p! h( C0 h
  892. + d! K$ e& G  I0 a; S/ e
  893.     delete_get_bits(&gb);% U2 J5 B0 k4 j- J3 f' S" y
  894.     free(pb);
    1 }, _$ h% Q; Y
  895. #endif- R7 k3 d+ C" ]+ l! u. D0 q; i
  896. 2 x7 v3 U  J# V0 w4 I& x  j0 e" ?' ?
  897.     /* validate the number of arguments */8 B, G0 L$ M8 R: i- W
  898.     if (argc != 8 && argc != 9)% p0 k/ Z1 F- G/ z7 ?) F* S8 z
  899.     {' d7 r" C: {) }' z  z+ H
  900.         printf("USAGE: subtitle-rbt <subtitles.ass> <in.rbt> <out.rbt> <origin X> <origin Y> <width> <height> [dump_frames]\n");7 @2 j3 H% V: G( h% R* u
  901.         return 1;
    % k, @) u' |1 m7 N1 u8 q
  902.     }7 m. Q9 ?' O' P  X3 I0 Q% L
  903.     subtitle_filename = argv[1];
    ' y; }9 X: l6 w" r* `- s; `1 f
  904.     inrbt_filename = argv[2];
    ; P5 F6 q) @2 b# Z' Z: s
  905.     outrbt_filename = argv[3];, {# d1 }/ O& O, r* ~  o& d2 j
  906.     origin_x = atoi(argv[4]);* I" v0 y4 d9 n& s; Z7 p1 d/ E$ Z
  907.     origin_y = atoi(argv[5]);% ]; j( @1 O3 d9 n
  908.     window_width = atoi(argv[6]);
    ' h8 x" y6 T) j
  909.     window_height = atoi(argv[7]);8 T7 x! Y7 b$ G0 R
  910.     rbt.dump_frames = 0;  q# c' \  C: d4 e5 n0 i% f
  911.     if (argc == 9)
    , \3 |' L& u- J# s- E8 W& a
  912.         rbt.dump_frames = 1;5 U' g1 u0 e* s7 s6 f+ c+ f8 Z( Y
  913. 0 K9 a6 t' K; O
  914.     /* verify that the specified input files are valid */
    ) Q7 `' ?  Q1 T' c% G
  915.     subtitle_file = fopen(subtitle_filename, "r");  a* X& P8 u- K) s4 L* ?
  916.     if (!subtitle_file)3 @) Y6 q) e  c
  917.     {' f# u) ~  |. v4 D+ a* z+ \. J9 w/ l
  918.         perror(subtitle_filename);* d6 \; x* \( Y' {. Z1 F
  919.         return 1;
    3 q6 X4 `; _2 x  N" A, h
  920.     }7 ?7 J, r3 S3 p" V
  921.     fclose(subtitle_file);7 R: [6 Y' d7 X4 |0 u  k
  922.     inrbt_file = fopen(inrbt_filename, "rb");0 R2 V5 S5 T: I# A
  923.     if (!inrbt_file)5 m1 |$ V5 r) Y2 E% M! v3 S0 }) s
  924.     {6 t8 v9 p0 }9 e+ k% I& V
  925.         perror(inrbt_filename);2 b9 Z3 s5 V& r5 U: d
  926.         return 1;) \$ r+ ~, G# j- F/ H
  927.     }
    + A3 ~8 \  n7 v0 J

  928.   T7 x, D/ w: y8 ?6 g
  929.     /* initialize the subtitle support */' j7 R* [; d1 T! U/ K1 r7 T8 o
  930.     rbt.ass_lib = ass_library_init();+ D% D. Y( g2 q- Z; f
  931.     rbt.ass_renderer = ass_renderer_init(rbt.ass_lib);
    0 B/ [2 a  E. {) Y0 v
  932.     rbt.ass_track = ass_read_file(rbt.ass_lib, subtitle_filename, "UTF-8");+ |+ F9 L* N2 a* _2 X' e9 H: P
  933.     ass_set_frame_size(rbt.ass_renderer, window_width, window_height);
    1 B4 g4 ~  Y* E6 o; I4 q5 q/ b
  934.     ass_set_fonts(rbt.ass_renderer, NULL, NULL, 1, NULL, 1);7 P4 R1 W% k, Y+ p- u1 m. M& }

  935. 5 K2 ?5 @/ h/ C3 I' L9 s
  936.     /* open the output file */3 X4 H% N( l9 S. ]8 B
  937.     outrbt_file = fopen(outrbt_filename, "wb");! e# o( O  P9 \' H- d3 y: q
  938.     if (!outrbt_file)
      b8 N; n2 d+ _, {
  939.     {
    1 g0 g8 v) N0 ^  u& O" ~. O5 s  `
  940.         perror(outrbt_filename);
    & N( {7 i: N, x3 M2 D! x* |% ?9 P7 u; c
  941.         return 1;; _, J# s/ G* Z* i7 t  D& J' g# z
  942.     }
    , j1 Y! I) Z$ v8 y$ [# v& p; W' x
  943. / j$ n7 {& Y& Z4 B! K
  944.     /* transfer header from input to output *// q) J: K1 E" h
  945.     if (!load_and_copy_rbt_header(&rbt, inrbt_file, outrbt_file)), ~+ p0 a+ |: {0 K: k+ F) e
  946.         return 1;
    . ?9 t; M- O: ?. E! a- ~- ~

  947. % o1 ]3 ^  ^, r6 o6 ~
  948.     /* rewrite the frames */
    ! c  ^$ w$ r& U: |1 ~
  949.     if (!copy_frames(&rbt, inrbt_file, outrbt_file, origin_x, origin_y,+ J0 s8 v0 {2 W  _7 }( H
  950.         window_width, window_height))
    6 Z, s& d4 l' S9 H  T
  951.         return 1;" K6 j( ?7 P" H4 Q0 t; T
  952. 1 c* i; F- ?5 t$ a" w: l  O2 r/ f
  953.     /* write the modified frame size tables back to the file */$ X6 q0 e1 Q! I) P3 q) e! |9 J
  954.     fseek(outrbt_file, rbt.video_frame_size_table_offset, SEEK_SET);4 K$ @4 |) Z& t: M& p( o
  955.     fwrite(rbt.video_frame_size_table, rbt.frame_count * sizeof(uint16_t), 1, outrbt_file);6 u4 J6 D' H  ^2 l8 `2 ^& ?. x
  956.     fseek(outrbt_file, rbt.frame_size_table_offset, SEEK_SET);4 M/ Q7 r7 u& T: q  k$ Z) P5 L  O6 D
  957.     fwrite(rbt.frame_size_table, rbt.frame_count * sizeof(uint16_t), 1, outrbt_file);( p/ v- q6 R' ?- H

  958. 3 Q9 z4 x, P, \  X/ ^- r# p' ]
  959.     /* finished with files */
    % m! r( L; \2 T' K& T
  960.     fclose(inrbt_file);
      D# R. w7 {  N/ K3 ?8 g8 Z
  961.     fclose(outrbt_file);) @5 v# Y5 I3 u" Q1 g
  962. " Y" M) F- g$ X9 r  w7 `
  963.     /* clean up subtitle library */
    & q- e; S3 B6 j  |6 o
  964.     ass_free_track(rbt.ass_track);9 z% F% b( H, `: b! U
  965.     ass_renderer_done(rbt.ass_renderer);' b% B5 g. s# l
  966.     ass_library_done(rbt.ass_lib);
    : Q3 ~( {, k0 M+ Q+ X
  967. 6 x) n; \! M5 V6 ?6 W
  968.     /* clean up *// F# L; d' |% V- `% ], v; N
  969.     free(rbt.frame_load_buffer);# M+ \% l: t, ], }/ `
  970.     free(rbt.video_frame_size_table);( u$ V3 e  d% R7 I# ^5 h
  971.     free(rbt.frame_size_table);
    9 J* E0 P6 K$ p( F

  972. ) n0 V- E& b+ S, J! H  {
  973.     return 0;
    ) ^/ q$ r; z7 ]3 |/ r
  974. }
复制代码
! C) B/ e- E; Q- Z8 O, a
& p' a+ x7 i1 R8 z# q& I. G* K# X
# F$ T+ t  z0 b" s
: Q1 U' k- W! h1 K  Z/ q
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 很美好很美好 很差劲很差劲
回复

使用道具 举报

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

使用道具 举报

板凳
 楼主| 发表于 2009-11-19 11:38 | 只看该作者
引用第1楼soring123于2009-11-19 11:09发表的  :/ w9 `5 f0 B4 m3 Z
这游戏有字幕吗?

+ m" @& s3 \- Z3 M! D好像没有字幕,我说的是给视频外挂字幕方式的汉化。  F/ ^$ [- j; t; p) X
就像syberia2汉化版下面那行字一样。
回复 支持 反对

使用道具 举报

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

使用道具 举报

5#
 楼主| 发表于 2009-11-19 17:39 | 只看该作者
引用第3楼soring123于2009-11-19 17:07发表的  :7 I/ h/ w# L6 @* ^# ], y' _' n* G
我记得是没字幕的 比较麻烦 都是视频的

/ [5 o5 N2 Z- P" Y, [' ^给视频外挂字幕方式汉化也许能行。* ]2 _* d4 h0 Q8 w& X5 ~
要结合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日,是全球华人共同的冒险解谜类游戏家园。我们致力于提供各类冒险游戏资讯供大家学习交流。本站所有资源均不用于商业用途。

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