I want to extract video from a bin file. Pスーパー海物語 IN JAPAN2 / Super Sea Story in Japan 2

Codecs, formats, encoding/decoding of game audio, video and music
Parasite
Posts: 48
Joined: Tue Oct 18, 2022 10:49 pm

I want to extract video from a bin file. Pスーパー海物語 IN JAPAN2 / Super Sea Story in Japan 2

Post by Parasite »

Games affected : Pスーパー海物語 IN JAPAN2 / Super Sea Story in Japan 2
Device : Android game
I would like to extract a video from a bin file, but I don't know how to do it.
If anyone is able to respond, we would appreciate your help.
-----
https://mega.nz/file/OY5FCI5I#uLEuaBsKe ... iJpZpYHjFs
--
https://mega.nz/file/CVIGnJJQ#ZWr-7pyw0 ... EzPzSl3xZI
atom0s
Posts: 250
Joined: Sat Dec 27, 2014 8:49 pm

Re: I want to extract video from a bin file. Pスーパー海物語 IN JAPAN2 / Super Sea Story in Japan 2

Post by atom0s »

Don't have time to work on this one for you, but will share the info needed for anyone else that may have time.

The .ogt files are actually textures, not video files. These are stored in a few different ways based on which ever compresses the best or fits the purpose of what the texture is for. (Meaning the pixel data storage.)

The files are loaded similarly to the sound files, where the ogtXX_add.bin files are used to tell the size of each file, and the ogtXX.bin file holds the combined file data. You walk the ogtXX.add.bin file two uint32_t's at a time to get each files block of data within the ogtXX.bin file.

Once they are extracted, the handling of the pixel data is done within libcmslib.so, specifically the two functions:
- CLoadOgt::AddTexture - Loads the file and prepares info based on the file header.
- CLoadOgt::add_texture - Loads the actual file texture data.

Each file has the same 16 byte header:

Code: Select all

struct ogtheader_t
{
  uint16_t header_size_;
  uint8_t texture_type_;
  uint8_t unk00; // Used as a block shift size when decompressing certain file types..
  uint16_t texture_width_;
  uint16_t texture_height_;
  uint32_t texture_data_size_;
  uint32_t sub_texture_;
};
The texture_type_ field tells the lib how the pixel data is stored. I don't have time to reverse these and make a tool to work for each so will just give a quick rundown based on looking at the function handling the field at a quick glance:

Type 0: Will require zlib to decompress.
Type 1: Will require zlib to decompress.
Type 2: Will require zlib to decompress.
Type 3: Will require zlib to decompress.
Type 5: Will require LZ4 to decompress.
Type 6: Will require LZ4 to decompress.
Type 20: Will require LZ4 to decompress.

All other types appear to be seen as invalid/error. This is the function handling the top-level part of the data:

Code: Select all

void __fastcall CLoadOgt::add_texture(ogtheader_t *a1, int **a2, _DWORD *a3, int a4)
{
  ogtheader_t *header; // x20
  unsigned int *v8; // x21
  __int64 Error; // x0
  unsigned __int64 *v10; // x1
  unsigned int texture_width; // w24
  unsigned int texture_height; // w25
  int v13; // w21
  unsigned int v14; // w22
  int *v15; // x9
  __int64 v16; // x8
  unsigned __int64 v17; // x24
  __int64 v18; // x10
  int *v19; // x26
  signed int v20; // w8
  __int64 v21; // x25
  void *v22; // x23
  __int64 v23; // x8
  int *v24; // x26
  signed int v25; // w8
  void *v26; // x25
  void *v27; // x24
  size_t v28; // w8
  void *v29; // x26
  __int64 v30; // x8
  uint8_t unk00; // w26
  size_t v32; // w27
  unsigned __int8 *v33; // x24
  unsigned __int64 *v34; // x1
  signed int v35; // w9
  __int64 v36; // x28
  void *v37; // x25
  __int64 v38; // x8
  int *v39; // x9
  __int64 v40; // x8
  unsigned __int64 v41; // x21
  __int64 v42; // x10
  __int64 v43; // x0
  int v44; // w28
  uint16_t v45; // w24
  __int64 v46; // x26
  __int64 v47; // x27
  int v48; // w5
  unsigned __int64 v49; // x2
  __int64 v50; // x0
  int v51; // w27
  int v52; // w25
  int v53; // w8
  int v54; // w25
  __int64 v55; // x26
  __int64 v56; // x27
  int v57; // w5
  unsigned __int64 v58; // x2
  __int64 v59; // x0
  int *v60; // x23
  int v61; // w28
  unsigned __int64 v62; // x2
  int v63; // w5
  unsigned __int64 v64; // x2
  int *v65; // x28
  int v66; // w26
  int v67; // w27
  unsigned __int64 v68; // x2
  int v69; // w5
  int v70; // w2
  int v71; // w8
  int v72; // w9
  int v73; // w10
  int *v74; // x12
  int v75; // w11
  _DWORD *v76; // x17
  __int64 v77; // x0
  int v78; // w1
  char *v79; // x18
  int v80; // w23
  void *v81; // [xsp+18h] [xbp-238h]
  int *v82; // [xsp+20h] [xbp-230h]
  void *v83; // [xsp+20h] [xbp-230h]
  void *v84; // [xsp+20h] [xbp-230h]
  int *v85; // [xsp+30h] [xbp-220h] BYREF
  int v86; // [xsp+38h] [xbp-218h]
  void *v87; // [xsp+48h] [xbp-208h]
  unsigned int v88; // [xsp+50h] [xbp-200h]
  __int64 v89; // [xsp+70h] [xbp-1E0h]
  __int64 v90; // [xsp+78h] [xbp-1D8h]
  __int64 v91; // [xsp+80h] [xbp-1D0h]
  _DWORD *v92; // [xsp+A0h] [xbp-1B0h] BYREF
  int v93; // [xsp+A8h] [xbp-1A8h]
  __int64 v94; // [xsp+B8h] [xbp-198h]
  int v95; // [xsp+C0h] [xbp-190h]
  __int64 v96; // [xsp+E0h] [xbp-170h]
  __int64 v97; // [xsp+E8h] [xbp-168h]
  __int64 v98; // [xsp+F0h] [xbp-160h]
  _DWORD *v99; // [xsp+110h] [xbp-140h] BYREF
  int v100; // [xsp+118h] [xbp-138h]
  __int64 v101; // [xsp+128h] [xbp-128h]
  int v102; // [xsp+130h] [xbp-120h]
  __int64 v103; // [xsp+150h] [xbp-100h]
  __int64 v104; // [xsp+158h] [xbp-F8h]
  __int64 v105; // [xsp+160h] [xbp-F0h]
  __int64 v106; // [xsp+180h] [xbp-D0h] BYREF
  __int64 v107; // [xsp+188h] [xbp-C8h] BYREF
  int v108; // [xsp+190h] [xbp-C0h]
  unsigned __int8 *v109; // [xsp+1A0h] [xbp-B0h]
  size_t v110; // [xsp+1A8h] [xbp-A8h]
  __int64 v111; // [xsp+1C8h] [xbp-88h]
  __int64 v112; // [xsp+1D0h] [xbp-80h]
  __int64 v113; // [xsp+1D8h] [xbp-78h]
  __int64 v114; // [xsp+1F8h] [xbp-58h]

  header = a1;
  v114 = *(_QWORD *)(_ReadStatusReg(ARM64_SYSREG(3, 3, 13, 0, 2)) + 40);
  do
    a1 = (ogtheader_t *)glGetError(a1);
  while ( (_DWORD)a1 );
  v8 = &a3[a4];
  glGenTextures(1LL, v8);
  Error = glBindTexture(3553LL, *v8);
  texture_width = header->texture_width_;
  texture_height = header->texture_height_;
  if ( texture_width == texture_height )
  {
    v13 = header->texture_height_;
    v14 = header->texture_width_;
    if ( ((texture_width + 0xFFFF) & texture_width) == 0 )
      goto LABEL_41;
  }
  if ( texture_width <= texture_height )
    v13 = header->texture_height_;
  else
    v13 = header->texture_width_;
  if ( ((v13 + 0xFFFF) & v13) == 0 )
    goto LABEL_40;
  if ( v13 >= 2 )
  {
    if ( v13 < 4 )
    {
      v13 = 4;
      v14 = 4;
      goto LABEL_41;
    }
    if ( v13 < 8 )
    {
      v13 = 8;
      v14 = 8;
      goto LABEL_41;
    }
    if ( v13 < 16 )
    {
      v13 = 16;
      v14 = 16;
      goto LABEL_41;
    }
    if ( v13 < 32 )
    {
      v13 = 32;
      v14 = 32;
      goto LABEL_41;
    }
    if ( v13 < 64 )
    {
      v13 = 64;
      v14 = 64;
      goto LABEL_41;
    }
    if ( v13 < 128 )
    {
      v13 = 128;
      v14 = 128;
      goto LABEL_41;
    }
    if ( v13 < 256 )
    {
      v13 = 256;
      v14 = 256;
      goto LABEL_41;
    }
    if ( v13 < 512 )
    {
      v13 = 512;
      v14 = 512;
      goto LABEL_41;
    }
    if ( v13 < 1024 )
    {
      v13 = 1024;
      v14 = 1024;
      goto LABEL_41;
    }
    if ( v13 < 2048 )
    {
      v13 = 2048;
      v14 = 2048;
      goto LABEL_41;
    }
    if ( v13 < 4096 )
    {
      v13 = 4096;
      v14 = 4096;
      goto LABEL_41;
    }
    if ( v13 < 0x2000 )
    {
      v13 = 0x2000;
      v14 = 0x2000;
      goto LABEL_41;
    }
    if ( v13 < 0x4000 )
    {
      v13 = 0x4000;
      v14 = 0x4000;
      goto LABEL_41;
    }
    if ( v13 >= 0x8000 )
      v13 = 0x10000;
    else
      v13 = 0x8000;
LABEL_40:
    v14 = v13;
    goto LABEL_41;
  }
  v13 = 2;
  v14 = 2;
LABEL_41:
  switch ( header->texture_type_ )
  {
    case 0u:
      v19 = *a2;
      v20 = 4 * v13 * v14 + 4096;
      v21 = v20;
      if ( 4 * v13 * v14 == -4096 )
      {
        v83 = 0LL;
        v22 = 0LL;
      }
      else
      {
        v107 = v20;
        if ( (unsigned int)v20 < 0x101 )
        {
          v43 = std::__node_alloc::_M_allocate((std::__node_alloc *)&v107, v10);
          v23 = v107;
          v22 = (void *)v43;
        }
        else
        {
          v22 = (void *)operator new(v20);
          v23 = v21;
        }
        v83 = (void *)v23;
      }
      memset(v22, 0, v21);
      v44 = *v19;
      v45 = header->texture_width_;
      v104 = 0LL;
      v105 = 0LL;
      v103 = 0LL;
      inflateInit_((int)&v99, "1.2.3", 112);
      v99 = v19 + 1;
      v100 = v44;
      v101 = (__int64)v22;
      v102 = (4 * v45) | 1;
      if ( (unsigned int)inflate((int)&v99, 0) != 1 )
      {
        v46 = (int)((4 * v14) | 1);
        v47 = (__int64)v22 + v46;
        do
        {
          v101 = v47;
          v102 = (4 * v45) | 1;
          v47 += v46;
        }
        while ( (unsigned int)inflate((int)&v99, 0) != 1 );
      }
      inflateEnd(&v99);
      CLoadOgt::FilterDecomp(
        (CLoadOgt *)v22,
        (unsigned __int8 *)header->texture_width_,
        header->texture_height_,
        32,
        4 * (v14 - header->texture_width_),
        v48);
      Error = glTexImage2D(3553LL, 0LL, 6408LL, v14, (unsigned int)v13, 0LL, 6408LL, 5121LL, v22);
      if ( !v22 )
        goto LABEL_119;
      if ( (unsigned __int64)v83 >= 0x101 )
        goto LABEL_86;
      Error = std::__node_alloc::_M_deallocate((std::__node_alloc *)v22, v83, v49);
      goto LABEL_119;
    case 1u:
      v24 = *a2;
      v25 = 3 * v13 * v14 + 4096;
      v26 = (void *)v25;
      if ( 3 * v13 * v14 == -4096 )
      {
        v27 = 0LL;
        v22 = 0LL;
      }
      else
      {
        v107 = v25;
        if ( (unsigned int)v25 < 0x101 )
        {
          v50 = std::__node_alloc::_M_allocate((std::__node_alloc *)&v107, v10);
          v27 = (void *)v107;
          v22 = (void *)v50;
        }
        else
        {
          v22 = (void *)operator new(v25);
          v27 = v26;
        }
      }
      memset(v22, 0, (size_t)v26);
      v51 = *v24;
      v52 = header->texture_width_;
      v97 = 0LL;
      v98 = 0LL;
      v96 = 0LL;
      inflateInit_((int)&v92, "1.2.3", 112);
      v53 = 3 * v52;
      v54 = 3 * v52 + 1;
      v92 = v24 + 1;
      v93 = v51;
      v94 = (__int64)v22;
      v95 = v53 + 1;
      if ( (unsigned int)inflate((int)&v92, 0) != 1 )
      {
        v55 = (int)(3 * v14 + 1);
        v56 = (__int64)v22 + v55;
        do
        {
          v94 = v56;
          v95 = v54;
          v56 += v55;
        }
        while ( (unsigned int)inflate((int)&v92, 0) != 1 );
      }
      inflateEnd(&v92);
      CLoadOgt::FilterDecomp(
        (CLoadOgt *)v22,
        (unsigned __int8 *)header->texture_width_,
        header->texture_height_,
        24,
        3 * (v14 - header->texture_width_),
        v57);
      Error = glTexImage2D(3553LL, 0LL, 6407LL, v14, (unsigned int)v13, 0LL, 6407LL, 5121LL, v22);
      if ( v22 )
      {
        if ( (unsigned __int64)v27 < 0x101 )
          Error = std::__node_alloc::_M_deallocate((std::__node_alloc *)v22, v27, v58);
        else
LABEL_86:
          operator delete(v22);
      }
      goto LABEL_119;
    case 2u:
      v28 = v14 * v13;
      if ( v14 * v13 )
      {
        v107 = (int)v28;
        if ( v28 < 0x101 )
        {
          v59 = std::__node_alloc::_M_allocate((std::__node_alloc *)&v107, v10);
          v30 = v107;
          v29 = (void *)v59;
        }
        else
        {
          v29 = (void *)operator new(v28);
          v30 = (int)(v14 * v13);
        }
        v84 = (void *)v30;
      }
      else
      {
        v84 = 0LL;
        v29 = 0LL;
      }
      memset(v29, 0, v14 * v13);
      v60 = *a2;
      v61 = *v60;
      v90 = 0LL;
      v91 = 0LL;
      v89 = 0LL;
      inflateInit_((int)&v85, "1.2.3", 112);
      v85 = v60;
      v86 = v61;
      v87 = v29;
      v88 = texture_height * texture_width + 4096;
      LODWORD(v60) = inflate((int)&v85, 0);
      inflateEnd(&v85);
      if ( (_DWORD)v60 == 1 )
      {
        CLoadOgt::FilterDecomp(
          (CLoadOgt *)v29,
          (unsigned __int8 *)header->texture_width_,
          header->texture_height_,
          8,
          v14 - header->texture_width_,
          v63);
        Error = glTexImage2D(3553LL, 0LL, 6406LL, v14, (unsigned int)v13, 0LL, 6406LL, 5121LL, v29);
        if ( v29 )
        {
          if ( (unsigned __int64)v84 < 0x101 )
            Error = std::__node_alloc::_M_deallocate((std::__node_alloc *)v29, v84, v64);
          else
            operator delete(v29);
        }
        goto LABEL_119;
      }
      if ( v29 )
      {
        if ( (unsigned __int64)v84 < 0x101 )
          std::__node_alloc::_M_deallocate((std::__node_alloc *)v29, v84, v62);
        else
          operator delete(v29);
      }
      return;
    case 3u:
      v82 = *a2;
      unk00 = header->unk00;
      v32 = texture_height * texture_width + 4096;
      v33 = (unsigned __int8 *)operator new(v32);
      memset(v33, 0, v32);
      v35 = 4 * v14 * v13;
      v36 = v35;
      if ( v14 * v13 )
      {
        v106 = v35;
        if ( (unsigned int)v35 < 0x101 )
        {
          v37 = (void *)std::__node_alloc::_M_allocate((std::__node_alloc *)&v106, v34);
          v38 = v106;
        }
        else
        {
          v37 = (void *)operator new(v35);
          v38 = v36;
        }
        v81 = (void *)v38;
      }
      else
      {
        v81 = 0LL;
        v37 = 0LL;
      }
      memset(v37, 0, v36);
      v65 = (int *)((char *)v82 + (4 << unk00));
      v66 = *v65;
      v112 = 0LL;
      v113 = 0LL;
      v111 = 0LL;
      inflateInit_((int)&v107, "1.2.3", 112);
      v107 = (__int64)(v65 + 1);
      v108 = v66;
      v109 = v33;
      v110 = v32;
      v67 = inflate((int)&v107, 0);
      inflateEnd(&v107);
      if ( v67 != 1 )
      {
        v80 = 1;
        if ( !v37 )
          goto LABEL_111;
        goto LABEL_108;
      }
      CLoadOgt::FilterDecomp(
        (CLoadOgt *)v33,
        (unsigned __int8 *)header->texture_width_,
        header->texture_height_,
        header->unk00,
        0,
        v69);
      v71 = header->texture_height_;
      if ( header->texture_height_ )
      {
        v72 = header->unk00;
        v73 = header->texture_width_;
        if ( header->texture_width_ )
        {
          v74 = *a2;
          v75 = 0;
          v76 = v37;
          do
          {
            v77 = 0LL;
            v78 = ((v73 * v72 + 8 * (((v73 * v72) & 7) != 0)) & 0x1FFFFF8) * v75;
            v79 = (char *)&v76[v14 - v73];
            do
            {
              v70 = v74[(unsigned __int8)((1 << v72) - 1) & (v33[v78 / 8] >> (8 - (v78 - (v70 & 0xF8)) - v72))];
              v78 += v72;
              v79 += 4;
              v76[v77++] = v70;
            }
            while ( (int)v77 < v73 );
            ++v75;
            v76 = v79;
          }
          while ( v75 < v71 );
        }
      }
      glTexImage2D(3553LL, 0LL, 6408LL, v14, (unsigned int)v13, 0LL, 6408LL, 5121LL, v37);
      v80 = 0;
      if ( v37 )
      {
LABEL_108:
        if ( (unsigned __int64)v81 < 0x101 )
          std::__node_alloc::_M_deallocate((std::__node_alloc *)v37, v81, v68);
        else
          operator delete(v37);
      }
LABEL_111:
      operator delete(v33);
      if ( !v80 )
      {
LABEL_119:
        a3[3] = v14;
        a3[4] = v13;
        a3[2] = header->texture_type_;
        do
          Error = glGetError(Error);
        while ( (_DWORD)Error );
      }
      return;
    case 5u:
    case 6u:
      do
        Error = glGetError(Error);
      while ( (_DWORD)Error );
      v15 = *a2;
      v16 = qword_1661C8;
      v17 = **a2;
      v14 = header->texture_width_;
      v13 = header->texture_height_;
      v18 = qword_1661D0 - qword_1661C8;
      if ( qword_1661D0 - qword_1661C8 < v17 )
      {
        LOBYTE(v99) = 0;
        if ( v17 != v18 )
        {
          if ( qword_1661D8 - qword_1661D0 >= v17 - v18 )
            std::vector<unsigned char>::_M_fill_insert_aux((int)&qword_1661C8, (void *)qword_1661D0, v17 - v18);
          else
            std::vector<unsigned char>::_M_insert_overflow(
              (int)&qword_1661C8,
              qword_1661D0,
              (int)&v99,
              (int)&v107,
              v17 - v18);
        }
        v15 = *a2;
        v16 = qword_1661C8;
      }
      LZ4_uncompress(v15 + 1, v16, (unsigned int)v17);
      Error = glCompressedTexImage2D(3553LL, 0LL, 36196LL, v14, (unsigned int)v13, 0LL, (unsigned int)v17, qword_1661C8);
      do
        Error = glGetError(Error);
      while ( (_DWORD)Error );
      goto LABEL_119;
    case 20u:
      v39 = *a2;
      v40 = qword_1661C8;
      v41 = **a2;
      v42 = qword_1661D0 - qword_1661C8;
      if ( qword_1661D0 - qword_1661C8 < v41 )
      {
        LOBYTE(v99) = 0;
        if ( v41 != v42 )
        {
          if ( qword_1661D8 - qword_1661D0 >= v41 - v42 )
            std::vector<unsigned char>::_M_fill_insert_aux((int)&qword_1661C8, (void *)qword_1661D0, v41 - v42);
          else
            std::vector<unsigned char>::_M_insert_overflow(
              (int)&qword_1661C8,
              qword_1661D0,
              (int)&v99,
              (int)&v107,
              v41 - v42);
        }
        v39 = *a2;
        v40 = qword_1661C8;
      }
      LZ4_uncompress(v39 + 1, v40, (unsigned int)v41);
      Error = glTexImage2D(3553LL, 0LL, 6408LL, texture_width, texture_height, 0LL, 6408LL, 5121LL, qword_1661C8);
      v13 = texture_height;
      v14 = texture_width;
      goto LABEL_119;
    default:
      goto LABEL_119;
  }
}
Parasite
Posts: 48
Joined: Tue Oct 18, 2022 10:49 pm

Re: I want to extract video from a bin file. Pスーパー海物語 IN JAPAN2 / Super Sea Story in Japan 2

Post by Parasite »

Thank you.
I look forward to the opportunity to do it sometime.