[第4波]幽魂系列汉化的有关资料
本帖最后由 shane007 于 2021-1-2 13:56 编辑最近找到了一些和幽魂系列Phantasmagoria 有关的资料,
也许将来可以用于汉化。
和日文版有关的信息
http://anthonylarme.tripod.com/phantas/phintgtp.html
相关工具
http://anthonylarme.tripod.com/phantas/phcheats.html
-----------------------------------------------------------------------
2012/1/2更新
关于幽魂游戏的字幕
Phantasmagoria subtitles function discovered - ScummVM :: Forums
VMD文件
Subtitling Sierra VMD Files | Breaking Eggs And Making Omelettes (multimedia.cx)VMD - MultimediaWiki
字幕
Subtitling Sierra RBT Files | Breaking Eggs And Making Omelettes (multimedia.cx)
FFmpeg/subtitle-rbt.c at feature/VMD_encoder · multimediamike/FFmpeg · GitHub
/*
* subtitle-rbt.c
*by Mike Melanson (mike -at- multimedia.cx)
*
* build with this command:
* gcc -g -Wall subtitle-rbt.c -o subtitle-rbt -lm -lass
*/
#include <inttypes.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ass/ass.h>
#define LE_16(x) ((((uint8_t*)(x)) <<8) | ((uint8_t*)(x)))
#define LE_32(x) (((uint32_t)(((uint8_t*)(x))) << 24) |\
(((uint8_t*)(x))<< 16) |\
(((uint8_t*)(x))<<8) |\
((uint8_t*)(x)))
/*********************************************************************/
/* Bit reader stuff */
typedef struct
{
uint8_t *bytestream;
int bytestream_size;
int index;
uint32_t bits;
int bits_in_buffer;
} get_bits_context;
static inline void reload_bits(get_bits_context *gb)
{
while (gb->bits_in_buffer <= 24)
{
if (gb->index < gb->bytestream_size)
gb->bits |= (gb->bytestream << (24 - gb->bits_in_buffer));
gb->bits_in_buffer += 8;
}
}
static void init_get_bits(get_bits_context *gb, uint8_t *bytestream, int size)
{
gb->bytestream = malloc(size);
memcpy(gb->bytestream, bytestream, size);
gb->bytestream_size = size;
gb->index = 0;
gb->bits = 0;
gb->bits_in_buffer = 0;
reload_bits(gb);
}
/* read bits without consuming them from the stream */
static int view_bits(get_bits_context *gb, int count)
{
if (count >= 24)
return -1;
if (gb->bits_in_buffer < count)
reload_bits(gb);
return (gb->bits >> (32 - count));
}
/* read and consume bits from the stream */
static int read_bits(get_bits_context *gb, int count)
{
int value;
if (count >= 24)
return -1;
value = view_bits(gb, count);
gb->bits <<= count;
gb->bits_in_buffer -= count;
return value;
}
static void delete_get_bits(get_bits_context *gb)
{
free(gb->bytestream);
}
/*********************************************************************/
/* Bit writer stuff */
#define MAX_PUT_BITS_BYTES 63000
typedef struct
{
uint8_t bytes;
int byte_index;
uint32_t bit_buffer;
int bits_buffered;
} put_bits_context;
static void reset_put_bits(put_bits_context *pb)
{
memset(pb->bytes, 0, MAX_PUT_BITS_BYTES);
pb->byte_index = 0;
pb->bit_buffer = 0;
pb->bits_buffered = 0;
}
static put_bits_context *init_put_bits()
{
put_bits_context *pb;
pb = malloc(sizeof(put_bits_context));
reset_put_bits(pb);
return pb;
}
static void put_bits(put_bits_context *pb, int bits, int count)
{
pb->bit_buffer <<= count;
pb->bit_buffer |= (bits & (~(0xFFFFFFFF << count)));
pb->bits_buffered += count;
while (pb->bits_buffered >= 8)
{
pb->bytes = pb->bit_buffer >> (pb->bits_buffered - 8);
pb->bit_buffer &= (~(0xFFFFFFFF << (pb->bits_buffered - 8)));
pb->bits_buffered -= 8;
}
if (pb->byte_index >= MAX_PUT_BITS_BYTES)
{
printf("HELP! Bit overflow\n");
exit(1);
}
}
static void put_bits_flush(put_bits_context *pb)
{
if (pb->bits_buffered > 0)
pb->bytes = pb->bit_buffer << (8 - pb->bits_buffered);
}
static void delete_put_bits(put_bits_context *pb)
{
free(pb->bytes);
}
/*********************************************************************/
/* RBT functions */
#define PALETTE_COUNT 256
#define RBT_HEADER_SIZE 60
#define UNKNOWN_TABLE_SIZE (1024+512)
#define SUBTITLE_THRESHOLD 0x70
#define MILLISECONDS_PER_FRAME 100
/* VLC table */
#define VLC_SIZE 4
static struct
{
int count;
int value;
} lzs_vlc_table[] =
{
/* code length = 2 bits; value = 2 */
/* 0000 */ { 2, 2 },
/* 0001 */ { 2, 2 },
/* 0010 */ { 2, 2 },
/* 0011 */ { 2, 2 },
/* code length = 2 bits; value = 3 */
/* 0100 */ { 2, 3 },
/* 0101 */ { 2, 3 },
/* 0110 */ { 2, 3 },
/* 0111 */ { 2, 3 },
/* code length = 2 bits; value = 4 */
/* 1000 */ { 2, 4 },
/* 1001 */ { 2, 4 },
/* 1010 */ { 2, 4 },
/* 1011 */ { 2, 4 },
/* code length = 4 bits; value = 5 */
/* 1100 */ { 4, 5 },
/* code length = 4 bits; value = 6 */
/* 1101 */ { 4, 6 },
/* code length = 4 bits; value = 7 */
/* 1110 */ { 4, 7 },
/* special case */
/* 1111 */ { 4, 8 }
};
typedef struct
{
int version;
int width;
int height;
int frame_count;
int audio_chunk_size;
uint8_t palette;
off_t video_frame_size_table_offset;
uint8_t *video_frame_size_table;
off_t frame_size_table_offset;
uint8_t *frame_size_table;
uint8_t *frame_load_buffer;
int dump_frames;
/* subtitle library */
ASS_Library *ass_lib;
ASS_Renderer *ass_renderer;
ASS_Track *ass_track;
} rbt_dec_context;
static void dump_pnm_file(char *filename, rbt_dec_context *rbt,
uint8_t *image, int width, int height)
{
FILE *outfile;
uint8_t bytes;
int p;
uint8_t pixel;
outfile = fopen(filename, "wb");
fprintf(outfile, "P6\n%d %d\n255\n", width, height);
for (p = 0; p < width * height; p++)
{
pixel = image;
bytes = rbt->palette;
bytes = rbt->palette;
bytes = rbt->palette;
fwrite(bytes, 3, 1, outfile);
}
fclose(outfile);
}
static int load_and_copy_rbt_header(rbt_dec_context *rbt, FILE *inrbt_file, FILE *outrbt_file)
{
uint8_t header;
int palette_data_size;
uint8_t *palette_chunk;
int unknown_chunk_size;
uint8_t *unknown_chunk;
uint8_t unknown_table;
off_t padding_size;
uint8_t *padding;
int i;
int frame_size;
int max_frame_size;
int first_palette_index;
int palette_count;
int palette_type;
int palette_index;
fseek(inrbt_file, 0, SEEK_SET);
fseek(outrbt_file, 0, SEEK_SET);
/* load the header */
if (fread(header, RBT_HEADER_SIZE, 1, inrbt_file) != 1)
{
printf("problem reading initial RBT header\n");
return 0;
}
/* copy header to the output */
if (fwrite(header, RBT_HEADER_SIZE, 1, outrbt_file) != 1)
{
printf("problem writing initial RBT header\n");
return 0;
}
rbt->version = LE_16(&header);
rbt->audio_chunk_size = LE_16(&header);
rbt->frame_count = LE_16(&header);
/* transfer the unknown data, if it's there */
unknown_chunk_size = LE_16(&header);
if (unknown_chunk_size > 0)
{
unknown_chunk = malloc(unknown_chunk_size);
if (fread(unknown_chunk, unknown_chunk_size, 1, inrbt_file) != 1)
{
printf("problem reading unknown data\n");
return 0;
}
if (fwrite(unknown_chunk, unknown_chunk_size, 1, outrbt_file) != 1)
{
printf("problem writing unknown data\n");
return 0;
}
free(unknown_chunk);
}
/* transfer the palette chunk */
palette_data_size = LE_16(&header);
palette_chunk = malloc(palette_data_size);
if (fread(palette_chunk, palette_data_size, 1, inrbt_file) != 1)
{
printf("problem reading palette\n");
return 0;
}
if (fwrite(palette_chunk, palette_data_size, 1, outrbt_file) != 1)
{
printf("problem writing palette\n");
return 0;
}
/* load the palette into the internal context */
memset(rbt->palette, 0, PALETTE_COUNT * 3);
first_palette_index = palette_chunk;
palette_count = LE_16(&palette_chunk);
palette_type = palette_chunk;
palette_index = (palette_type == 0) ? 38 : 37;
for (i = first_palette_index; i < first_palette_index + palette_count; i++)
{
rbt->palette = palette_chunk;
rbt->palette = palette_chunk;
rbt->palette = palette_chunk;
}
free(palette_chunk);
/* copy the video frame size table (2 bytes per frame), as a placeholder */
rbt->video_frame_size_table = malloc(rbt->frame_count * sizeof(uint16_t));
if (fread(rbt->video_frame_size_table, rbt->frame_count * sizeof(uint16_t), 1, inrbt_file) != 1)
{
printf("problem reading frame table\n");
return 0;
}
rbt->video_frame_size_table_offset = ftell(outrbt_file);
if (fwrite(rbt->video_frame_size_table, rbt->frame_count * sizeof(uint16_t), 1, outrbt_file) != 1)
{
printf("problem writing frame table\n");
return 0;
}
/* copy the frame size table (2 bytes per frame), as a placeholder */
rbt->frame_size_table = malloc(rbt->frame_count * sizeof(uint16_t));
if (fread(rbt->frame_size_table, rbt->frame_count * sizeof(uint16_t), 1, inrbt_file) != 1)
{
printf("problem reading frame table\n");
return 0;
}
rbt->frame_size_table_offset = ftell(outrbt_file);
if (fwrite(rbt->frame_size_table, rbt->frame_count * sizeof(uint16_t), 1, outrbt_file) != 1)
{
printf("problem writing frame table\n");
return 0;
}
/* find the max frame size */
max_frame_size = 0;
for (i = 0; i < rbt->frame_count; i++)
{
frame_size = LE_16(&rbt->frame_size_table);
if (frame_size > max_frame_size)
max_frame_size = frame_size;
}
rbt->frame_load_buffer = malloc(max_frame_size);
/* transfer the unknown table(s) */
if (fread(unknown_table, UNKNOWN_TABLE_SIZE, 1, inrbt_file) != 1)
{
printf("problem reading unknown table\n");
return 0;
}
if (fwrite(unknown_table, UNKNOWN_TABLE_SIZE, 1, outrbt_file) != 1)
{
printf("problem writing unknown table\n");
return 0;
}
/* copy over padding */
padding_size = 0x800 - (ftell(inrbt_file) & 0x7FF);
if (padding_size)
{
padding = malloc(padding_size);
if (fread(padding, padding_size, 1, inrbt_file) != 1)
{
printf("problem reading padding\n");
return 0;
}
if (fwrite(padding, padding_size, 1, outrbt_file) != 1)
{
printf("problem writing padding\n");
return 0;
}
free(padding);
}
return 1;
}
static int get_lzs_back_ref_length(get_bits_context *gb)
{
int vlc;
int count;
int value;
vlc = view_bits(gb, VLC_SIZE);
count = lzs_vlc_table.count;
value = lzs_vlc_table.value;
read_bits(gb, count);
if (value == 8)
{
do
{
vlc = read_bits(gb, VLC_SIZE);
value += vlc;
}
while (vlc == 0xF);
}
return value;
}
static void compress_window(put_bits_context *pb, uint8_t *full_window,
int full_window_stride,
int window_top, int window_bottom, int window_left, int window_right)
{
int last_pixel;
int run_size;
int x;
int y;
int start_index;
int end_index;
int encode_last_run;
last_pixel = full_window;
run_size = 1;
for (y = window_top; y <= window_bottom; y++)
{
start_index = y * full_window_stride + window_left;
if (y == window_top)
start_index += 1;
end_index = y * full_window_stride + window_right;
if (y == window_bottom)
encode_last_run = 1;
else
encode_last_run = 0;
for (x = start_index; x < end_index; x++)
{
if (!encode_last_run && full_window == last_pixel)
run_size++;
else
{
if (run_size == 1)
{
/* encode a 0 bit followed by raw pixel byte */
put_bits(pb, 0, 1);
put_bits(pb, last_pixel, 8);
}
else if (run_size == 2)
{
/* encode a 0 bit followed by raw pixel byte */
put_bits(pb, 0, 1);
put_bits(pb, last_pixel, 8);
put_bits(pb, 0, 1);
put_bits(pb, last_pixel, 8);
}
else
{
/* encode a 0 bit followed by raw pixel byte */
put_bits(pb, 0, 1);
put_bits(pb, last_pixel, 8);
run_size--;
/* encode a run: a 1 bit, followed by a back reference
* offset (-1), followed by a length */
put_bits(pb, 1, 1);
put_bits(pb, 1, 1);/* 1 = 7-bit offset */
put_bits(pb, 1, 7);
if (run_size <= 4)
{
/* lengths 2, 3, and 4 are 2 bits */
put_bits(pb, run_size - 2, 2);
}
else if (run_size <= 7)
{
/* lengths 5, 6, and 7 are 4 bits */
put_bits(pb, run_size + 7, 4);
}
else
{
/* arbitrary length; start by encoding 0xF which
* stands in for an initial version of 8 */
put_bits(pb, 0xF, 4);
run_size -= 8;
/* encode blocks of 4 bits until run_size is 0 */
while (run_size >= 0)
{
if (run_size >= 15)
{
put_bits(pb, 0xF, 4);
run_size -= 0xF;
}
else
{
put_bits(pb, run_size, 4);
run_size = -1;
}
}
}
}
last_pixel = full_window;
run_size = 1;
/* this single x iteration was only here to close the final run */
if (y == window_bottom)
break;
}
}
}
/* close the bitstream by encoding a back reference with length 0 */
put_bits(pb, 1, 1);/* back reference run */
put_bits(pb, 1, 1);/* 1 = 7-bit offset */
put_bits(pb, 0, 7);/* length 0 */
put_bits_flush(pb);
}
/* compute Euclidean distance between an RGB color and the desired target */
static int compute_rgb_distance(int r1, int r2, int g1, int g2, int b1, int b2)
{
return sqrt((r1 - r2) * (r1 - r2) +
(g1 - g2) * (g1 - g2) +
(b1 - b2) * (b1 - b2));
}
static uint8_t find_nearest_color(rbt_dec_context *rbt, int r, int g, int b)
{
int i;
int nearest_distance;
int distance;
int rp;
int gp;
int bp;
uint8_t palette_index;
nearest_distance = 999999999;
palette_index = 0;
for (i = 0; i < 256; i++)
{
rp = rbt->palette;
gp = rbt->palette;
bp = rbt->palette;
distance = compute_rgb_distance(r, rp, g, gp, b, bp);
if (distance < nearest_distance)
{
nearest_distance = distance;
palette_index = i;
}
/* can't get closer than 0; break early */
if (distance == 0)
break;
}
return palette_index;
}
static void subtitle_frame(rbt_dec_context *rbt, uint8_t *frame,
int width, int height, int timestamp)
{
ASS_Image *subtitles;
int detect_change;
uint8_t subtitle_pixel;
int x, y;
uint8_t *frame_ptr;
uint8_t *subtitle_ptr;
/* ask library for the subtitle for this timestamp */
subtitles = ass_render_frame(rbt->ass_renderer, rbt->ass_track,
timestamp, &detect_change);
/* render the list of subtitles onto the decoded frame */
while (subtitles)
{
/* palette components are only 6 bits, so shift an extra 2
* bits off each component */
subtitle_pixel = find_nearest_color(rbt,
(subtitles->color >> 10) & 0xFF,
(subtitles->color >> 18) & 0xFF,
(subtitles->color >> 26) & 0xFF);
for (y = 0; y < subtitles->h; y++)
{
subtitle_ptr = &subtitles->bitmap;
frame_ptr = &frame[(subtitles->dst_y + y) * width + subtitles->dst_x];
for (x = 0; x < subtitles->w; x++, frame_ptr++, subtitle_ptr++)
{
if (*subtitle_ptr >= SUBTITLE_THRESHOLD)
*frame_ptr = subtitle_pixel;
}
}
subtitles = subtitles->next;
}
}
static int copy_frames(rbt_dec_context *rbt, FILE *inrbt_file, FILE *outrbt_file,
int origin_x, int origin_y, int window_width, int window_height)
{
int i;
int j;
int scale;
int width;
int height;
int max_width;
int max_height;
int frame_x;
int frame_y;
int fragment_count;
int decoded_size;
uint8_t *decoded_frame;
int fragment;
int fragment_compressed_size;
int fragment_decompressed_size;
int compression_type;
int index;
int out_index;
get_bits_context gb;
int frame_size;
int video_frame_size;
int audio_frame_size;
int back_ref_offset_type;
int back_ref_offset;
int back_ref_length;
int back_ref_start;
int back_ref_end;
uint8_t *full_window;
int full_window_size;
int y;
int window_top;
int window_bottom;
int window_left;
int window_right;
int window_size;
char filename;
put_bits_context *pb;
full_window_size = window_width * window_height;
full_window = malloc(full_window_size);
pb = init_put_bits();
max_width = 0;
max_height = 0;
for (i = 0; i < rbt->frame_count; i++)
{
/* read the entire frame (includes audio and video) */
frame_size = LE_16(&rbt->frame_size_table);
video_frame_size = LE_16(&rbt->video_frame_size_table);
audio_frame_size = frame_size - video_frame_size;
if (fread(rbt->frame_load_buffer, frame_size, 1, inrbt_file) != 1)
{
printf("problem reading frame %d\n", i);
return 0;
}
scale = rbt->frame_load_buffer;
width = LE_16(&rbt->frame_load_buffer);
if (max_width < width)
max_width = width;
if (max_height < height)
max_height = height;
height = LE_16(&rbt->frame_load_buffer);
frame_x = LE_16(&rbt->frame_load_buffer);
frame_y = LE_16(&rbt->frame_load_buffer);
fragment_count = LE_16(&rbt->frame_load_buffer);
decoded_size = width * height;
printf("processing frame %d: %d%%, %dx%d, origin @ (%d, %d), %d fragments\n", i, scale, width, height, frame_x, frame_y, fragment_count);
/* decode the frame */
decoded_frame = malloc(decoded_size);
index = 24;
out_index = 0;
for (fragment = 0; fragment < fragment_count; fragment++)
{
fragment_compressed_size = LE_32(&rbt->frame_load_buffer);
index += 4;
fragment_decompressed_size = LE_32(&rbt->frame_load_buffer);
index += 4;
compression_type = LE_16(&rbt->frame_load_buffer);
index += 2;
if (compression_type == 0)
{
init_get_bits(&gb, &rbt->frame_load_buffer,
fragment_compressed_size);
while (out_index < fragment_decompressed_size)
{
if (read_bits(&gb, 1))
{
/* decode back reference offset type */
back_ref_offset_type = read_bits(&gb, 1);
/* back reference offset is 7 or 11 bits */
back_ref_offset = read_bits(&gb,
(back_ref_offset_type) ? 7 : 11);
/* get the length of the back reference */
back_ref_length = get_lzs_back_ref_length(&gb);
back_ref_start = out_index - back_ref_offset;
back_ref_end = back_ref_start + back_ref_length;
/* copy the back reference, byte by byte */
for (j = back_ref_start; j < back_ref_end; j++)
decoded_frame = decoded_frame;
}
else
{
/* read raw pixel byte */
decoded_frame = read_bits(&gb, 8) & 0xFF;
}
}
delete_get_bits(&gb);
}
/* next fragment */
index += fragment_compressed_size;
}
if (rbt->dump_frames)
{
/* dump the original frame */
sprintf(filename, "original-frame-%03d.pnm", i);
dump_pnm_file(filename, rbt, decoded_frame, width, height);
}
/* transfer the image onto the frame window */
memset(full_window, 0xFF, full_window_size);
index = 0;
for (y = 0; y < height; y++)
{
out_index = window_width * (frame_y + y) + frame_x;
memcpy(&full_window, &decoded_frame, width);
index += width;
}
/* write the subtitle */
subtitle_frame(rbt, full_window, window_width, window_height,
i * MILLISECONDS_PER_FRAME);
/* figure out the smallest change window */
window_top = frame_y;
window_bottom = window_height;
window_left = 0;
window_right = window_width;
window_size = (window_right - window_left) * (window_bottom - window_top);
/* compress the frame */
reset_put_bits(pb);
compress_window(pb, full_window, window_width, window_top,
window_bottom, window_left, window_right);
if (rbt->dump_frames)
{
/* dump the frame plotted onto the full window prior to encoding,
* with subtitle */
sprintf(filename, "pre-encoding-frame-%03d.pnm", i);
dump_pnm_file(filename, rbt, full_window, window_width, window_height);
}
free(decoded_frame);
/* update the frame header */
/* width */
rbt->frame_load_buffer = (window_right - window_left) & 0xFF;
rbt->frame_load_buffer = (window_right - window_left) >> 8;
/* height */
rbt->frame_load_buffer = (window_bottom - window_top) & 0xFF;
rbt->frame_load_buffer = (window_bottom - window_top) >> 8;
/* origin X */
rbt->frame_load_buffer = window_left & 0xFF;
rbt->frame_load_buffer = window_left >> 8;
/* origin Y */
rbt->frame_load_buffer = window_top & 0xFF;
rbt->frame_load_buffer = window_top >> 8;
/* fragment payload size */
rbt->frame_load_buffer = (pb->byte_index + 10) & 0xFF;
rbt->frame_load_buffer = (pb->byte_index + 10) >> 8;
/* fragment count (1) */
rbt->frame_load_buffer = 1;
rbt->frame_load_buffer = 0;
/* update the fragment header */
/* compressed size */
rbt->frame_load_buffer = (pb->byte_index >>0) & 0xFF;
rbt->frame_load_buffer = (pb->byte_index >>8) & 0xFF;
rbt->frame_load_buffer = (pb->byte_index >> 16) & 0xFF;
rbt->frame_load_buffer = (pb->byte_index >> 24) & 0xFF;
/* decompressed size */
rbt->frame_load_buffer = (window_size >>0) & 0xFF;
rbt->frame_load_buffer = (window_size >>8) & 0xFF;
rbt->frame_load_buffer = (window_size >> 16) & 0xFF;
rbt->frame_load_buffer = (window_size >> 24) & 0xFF;
/* compression format 0 */
rbt->frame_load_buffer = 0;
rbt->frame_load_buffer = 0;
/* write the 24-byte frame header and the 10-byte fragment header */
if (fwrite(rbt->frame_load_buffer, 24 + 10, 1, outrbt_file) != 1)
{
printf("problem writing frame %d\n", i);
return 0;
}
/* write the new compressed frame data */
if (fwrite(pb->bytes, pb->byte_index, 1, outrbt_file) != 1)
{
printf("problem writing frame %d\n", i);
return 0;
}
/* write the audio data */
if (fwrite(&rbt->frame_load_buffer, frame_size - video_frame_size, 1, outrbt_file) != 1)
{
printf("problem writing frame %d\n", i);
return 0;
}
/* update the table entries */
video_frame_size = pb->byte_index + 24 + 10;
frame_size = video_frame_size + audio_frame_size;
rbt->frame_size_table = frame_size & 0xFF;
rbt->frame_size_table = frame_size >> 8;
rbt->video_frame_size_table = video_frame_size & 0xFF;
rbt->video_frame_size_table = video_frame_size >> 8;
}
printf("maximum dimensions seen are %dx%d\n", max_width, max_height);
delete_put_bits(pb);
free(full_window);
return 1;
}
int main(int argc, char *argv[])
{
char *subtitle_filename;
FILE *subtitle_file;
char *inrbt_filename;
FILE *inrbt_file;
char *outrbt_filename;
FILE *outrbt_file;
rbt_dec_context rbt;
int origin_x;
int origin_y;
int window_width;
int window_height;
/* testing the bit functions */
#if 0
int i;
uint8_t bytestream[] = { 0x55, 0xAA, 0x00, 0xAA, 0x55, 0x77, 0xFF, 0x1B, 0x70, 0x8F };
int bytestream_size = 10;
get_bits_context gb;
put_bits_context *pb;
int bits;
init_get_bits(&gb, bytestream, bytestream_size);
pb = init_put_bits();
for (i = 1; i <= 12; i++)
{
bits = view_bits(&gb, i);
printf("view %d bits: %d\n", i, bits);
printf("read %d bits: %d\n", i, read_bits(&gb, i));
put_bits(pb, bits, i);
}
put_bits_flush(pb);
printf("original bytestream:\n");
for (i = 0; i < bytestream_size; i++)
printf(" %02X", bytestream);
printf("\nnewbytestream:\n");
for (i = 0; i < pb->byte_index; i++)
printf(" %02X", pb->bytes);
printf("\n");
delete_get_bits(&gb);
free(pb);
#endif
/* validate the number of arguments */
if (argc != 8 && argc != 9)
{
printf("USAGE: subtitle-rbt <subtitles.ass> <in.rbt> <out.rbt> <origin X> <origin Y> <width> <height> \n");
return 1;
}
subtitle_filename = argv;
inrbt_filename = argv;
outrbt_filename = argv;
origin_x = atoi(argv);
origin_y = atoi(argv);
window_width = atoi(argv);
window_height = atoi(argv);
rbt.dump_frames = 0;
if (argc == 9)
rbt.dump_frames = 1;
/* verify that the specified input files are valid */
subtitle_file = fopen(subtitle_filename, "r");
if (!subtitle_file)
{
perror(subtitle_filename);
return 1;
}
fclose(subtitle_file);
inrbt_file = fopen(inrbt_filename, "rb");
if (!inrbt_file)
{
perror(inrbt_filename);
return 1;
}
/* initialize the subtitle support */
rbt.ass_lib = ass_library_init();
rbt.ass_renderer = ass_renderer_init(rbt.ass_lib);
rbt.ass_track = ass_read_file(rbt.ass_lib, subtitle_filename, "UTF-8");
ass_set_frame_size(rbt.ass_renderer, window_width, window_height);
ass_set_fonts(rbt.ass_renderer, NULL, NULL, 1, NULL, 1);
/* open the output file */
outrbt_file = fopen(outrbt_filename, "wb");
if (!outrbt_file)
{
perror(outrbt_filename);
return 1;
}
/* transfer header from input to output */
if (!load_and_copy_rbt_header(&rbt, inrbt_file, outrbt_file))
return 1;
/* rewrite the frames */
if (!copy_frames(&rbt, inrbt_file, outrbt_file, origin_x, origin_y,
window_width, window_height))
return 1;
/* write the modified frame size tables back to the file */
fseek(outrbt_file, rbt.video_frame_size_table_offset, SEEK_SET);
fwrite(rbt.video_frame_size_table, rbt.frame_count * sizeof(uint16_t), 1, outrbt_file);
fseek(outrbt_file, rbt.frame_size_table_offset, SEEK_SET);
fwrite(rbt.frame_size_table, rbt.frame_count * sizeof(uint16_t), 1, outrbt_file);
/* finished with files */
fclose(inrbt_file);
fclose(outrbt_file);
/* clean up subtitle library */
ass_free_track(rbt.ass_track);
ass_renderer_done(rbt.ass_renderer);
ass_library_done(rbt.ass_lib);
/* clean up */
free(rbt.frame_load_buffer);
free(rbt.video_frame_size_table);
free(rbt.frame_size_table);
return 0;
}
这游戏有字幕吗? 引用第1楼soring123于2009-11-19 11:09发表的:
这游戏有字幕吗?
好像没有字幕,我说的是给视频外挂字幕方式的汉化。
就像syberia2汉化版下面那行字一样。 我记得是没字幕的 比较麻烦 都是视频的 引用第3楼soring123于2009-11-19 17:07发表的:
我记得是没字幕的 比较麻烦 都是视频的
给视频外挂字幕方式汉化也许能行。
要结合dosbox和代理dll技术。 求汉化啊! 顶上来
页:
[1]