shane007 发表于 2009-11-18 23:56

[第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;
}



soring123 发表于 2009-11-19 11:09

这游戏有字幕吗?

shane007 发表于 2009-11-19 11:38

引用第1楼soring123于2009-11-19 11:09发表的:
这游戏有字幕吗?

好像没有字幕,我说的是给视频外挂字幕方式的汉化。
就像syberia2汉化版下面那行字一样。

soring123 发表于 2009-11-19 17:07

我记得是没字幕的 比较麻烦 都是视频的

shane007 发表于 2009-11-19 17:39

引用第3楼soring123于2009-11-19 17:07发表的:
我记得是没字幕的 比较麻烦 都是视频的

给视频外挂字幕方式汉化也许能行。
要结合dosbox和代理dll技术。

宿矢 发表于 2016-7-21 23:33

求汉化啊!

shane007 发表于 2021-1-2 13:50

顶上来
页: [1]
查看完整版本: [第4波]幽魂系列汉化的有关资料