minirop / arc-reader

Allow you to read and extract files inside .arc files of the BGI visual novel engine (OverDrive/MangaGamer).
Other
34 stars 3 forks source link

Support for more recent CBG #1

Open rr- opened 9 years ago

rr- commented 9 years ago

Is there any chance of adding support for new CompressedBG___ graphics that are used in Magical Charming? AFAIK up until this line the format stays the same (meaning, it still has width/height, uses the hash_update to decrypt first piece of data etc.), but then it changes somehow. Namely, every image has less than 256 elements in the first array, making the program crash with a buffer overflow. Additionally, I saw procedures in the game that were used to read the old format; the procedure that is actually used starts all the same up until reading the 256 elements. Instead, it assigns bunch of variables, some constant string BF_Movie_______\x00, and proceeds to call other functions...

minirop commented 9 years ago

my code is a rewrite of a code written in D that I found years ago, I didn't know they changed the format. If you have knowledge I'm open. (I tried to reverse-engineer bgi.exe but failed)

rr- commented 9 years ago

I'm afraid that beyond what I've already stated + some minor useless bits, I can't be of any help. The code behind new format looks complicated and optimized for GPUs (lots of MMX and floating point arithmetic). I wonder if it's the case with just Magicha, and other games are less optimized? Also the things I discovered could be just a honeypot rather than real decryption routines.

I also looked at Westside Otanoshimi and indeed they have a tool for Magicha on CD 105, but all they offer is unlocking 100% CG through save modification.

Frankly, Magicha seems way over my level. Perhaps collecting info from other games that use new BGI versions could shed some light.

rr- commented 9 years ago

I found an implementation for the new format here: https://github.com/regomne/chinesize/blob/master/BGI/BGIunpack/CBG.h

I reimplemented it in arc_unpacker, fixing a few minor bugs along the way:

The second version should be much easier to read at expense of slower performance.

Here you can find test 8-, 24- and 32-bit images (note - if you plan on implementing it yourself, while being able to unpack all of these images should be a strong indicator it works, it doesn't guarantee to catch all possible bugs.)

The v2 format works like this:

  1. Read multipliers for DCT from encrypted data (after this point, everything uses unecrypted raw data)
  2. Build two Huffman trees
  3. Read basic block information (block sizes, offsets etc.)
  4. For each block:
    1. Decompress its data using the Huffman trees
    2. For each channel,
      1. Use decoded block data as input to JPEG discrete cosine transform
      2. Decode with DCT using the multipliers from point 1
      3. The output from DCT = image data for given channel.
  5. Alpha channel is encoded separately using a LZSS variant which involves funky bit reading.

Output from DCT transform for 8-bit images produces monochrome colors, but for 24-bit images it produces colors in YUV color space, so it needs to be converted manually to RGB.

Since the whole thing uses 8x8 blocks, before you start anything, you need to allocate image of size multiplied by 8x8, and after you're done with decompressing everything, you need to crop it back to original size.

minirop commented 9 years ago

thanks. I'll give it a try sooner or later. :+1: