Jump to content

Ring: The Legend of the Nibelungen CNM video files (PC-DC)


PITITO

Recommended Posts

Well, it seems that I am opening this section with a request to see if it is possible to do.

I need help with this type of format of which I have two variants, one is the PC version and the other is the Dreamcast version.
My idea is to demux both versions to be able to mux the Dreamcast version with the audio of the PC version, since this audio is in my language.

I've found some information on this type of fmv, which seems to use the cin and cin2 codec on github, but I haven't been able to figure out how to create any tools.
I have also tried with ffmpeg, but it doesn't seem to support this format

I found this information about the codecs in a version of scummvm

https://github.com/Templier/scummvm/tree/ring/engines/ring/graphics/movies

And here I leave the same fmv of both versions (PC and DC)

CNM FILES.zip

Greetings and long live the modders

 

Link to comment
Share on other sites

  • Engineer

I'm sending pattern that contains some research from the link you provided and some of my own.

 

struct CINBuffer {
  u8 format;

  if (format == 0x5A) {
    u32 size;
    // This looks like adpcm stream
    padding[size];
  } else if (format == 0x54) {
    u32 bufferSize;
    u32 unk;
    u16 unk1;
    u16 unk2;
    u8 paletteSize;
    u16 palette[paletteSize + 1];
    padding[bufferSize];
  } else if (format == 0x53) {
    u32 bufferSize;
    u32 unk;
    u16 unk1;
    u16 unk2;
    u32 width;
    u32 height;
    padding[bufferSize];
  }
};

struct CIN {
  u8 channels;
  u8 bitsPerSample;
  u32 samplesPerSec;
  u32 chunkCount;
  u32 frameRate;
  u8 field_16;
  u32 width;
  u32 height;
  u8 field_1F;
  u32 field_20;
  u32 field_24;
  u32 field_28;
  u32 field_2C;
  u32 field_30;
  u32 field_34;
  u32 field_38;
  u32 field_3C;

  CINBuffer buffers[while($ < builtin::std::mem::size())];
};

struct CI2Buffer {
  u8 format;

  if (format == 0x5A) {
    u32 size;
    // This looks like adpcm stream
    padding[size];
  } else if (format == 0x54) {
    u32 bufferSize;
    u32 unk;
    padding[bufferSize];
  } else if (format == 0x55 || format == 0x53) {
    u32 bufferSize;
    u32 bufferSize2;
    u32 unk;
    u32 width;
    u32 height;
    u32 frameRate;
    u32 frameRate2;
    padding[19];
    padding[bufferSize];
  }
};

struct SoundConfig {
  u8 channels;
  u8 bitsPerSample;
  u32 samplesPerSec;
  u16 field_6;
  u32 field_8;
  u32 field_C;
};

struct CI2 {
  u32 chunkCount;
  u32 frameRate;
  u8 field_D;
  u32 width;
  u32 height;
  u8 field_19;
  u8 field_1A;
  u8 soundChannelCount;
  u32 controlTableSize;
  u32 field_20;
  u32 field_24;
  u32 field_28;
  padding[148];

  SoundConfig soundConfigs[soundChannelCount];
  u64 controlTable[controlTableSize];

  CI2Buffer buffers[while($ < builtin::std::mem::size())];
};

struct Format {
  u32 id;      // CNM\x20
  u32 version; // UNR v2, HBR v1

  if (version == 0x524248) {
    CIN cin;
  } else if (version == 0x524E55) {
    CI2 ci2;
  }
};

Format main @0;

PC is version 1 (CIN) and DC is version 2 (CI2), sound streams are very similar in both formats.

I believe from this pattern it should be easy to create tool to swap audio between them.

  • Like 1
  • Thanks 2
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...