/yukatool2

New and fresh version of yukatool, rewritten from the ground up to be much faster and more maintainable than its predecessor

Primary LanguageC#GNU General Public License v3.0GPL-3.0

About YukaTool

YukaTool is a tool designed to work with the files used by the "Yuka System" visual novel engine.
It allows you to extract and repack the game archives as well as convert the various game files to common formats.

YukaTool comes in two flavors; a command line operated version and a GUI app.

YukaTool Gui

The GUI version is meant so serve as a quick way to look through the archives.
I do not recommend to use it for extraction and insertion of files for translation projects.
Here are some of the things it can do:

  • Open archives and display their directory structure.
  • Preview images and text files.
  • Show a hex dump of other files.
  • Export individual files.
  • Export all files in the archive.
    Note: Only raw export is supported, so files will not be converted.
  • Import files per drag'n'drop.
  • Delete files from an archive.
  • Save the modified archive.
Image: YukaTool Gui

YukaTool Gui

YukaTool Cli

The CLI variant is completely command line operated. Please make sure you know at least the basics before attempting to use it.
Place yuka.exe in your game directory and open a command prompt in the same folder.
Typing yuka help should now display a help page with a list of supported commands.

Image: YukaTool Cli

YukaTool Cli

About the "Yuka System" Engine

The Game Folder

Yuka games are easily identifiable, the game directory usually contains these files:

  • A single game executable (<name>.exe)
  • One to five dataXX.ykc files, these contain all game assets.
  • An avi folder with any video files the game might use.
  • A Save folder with your settings and save data.

Archives

The dataXX.ykc archives contain the various game files, which include graphics, audio files and scripts.
When unpacking an archive with default settings, a .manifest file will be created in the target folder, listing all extracted files and their original type. This manifest is needed when repacking to assure all files end up in the same format they were in originally.

Graphics

The Yuka engine supports a range of common image formats, such as .bmp and .png.
There is however also a proprietary image format called .ykg (Yuka Graphics), which can store animation frames in addition to the pixel data.
When unpacking with default settings, these files will automatically be converted to .png. If the file also contains frame data, it will be saved in an .ani file with the same name.

Scripts

Yuka scripts (.yks files) are the binary script files controlling everything the game does.
They are not meant to be read by humans, which is why YukaTool will decompile them back into a human readable format.
The source files end in .ykd and may be accompanied by a .csv file of the same name.
These .csv files can be imported into the spreadsheet editor of your choice and contain all the text from their correponding script.

The binary script format is unfortunately very convoluted and not publically documented, so some of them might fail to decompile properly.
If that is the case, please open an issue on GitHub and attach the script file in question.

Translating a Game

The following instructions should give you an overview over the required steps to translate a Yuka game.

1. Inspecting the Archives

The first thing you probably want to do when starting a translation project is to extract the script files.
Which archive contains the scenario scripts varies from game to game, so let's take a look at the file contents.
We are looking for a series of .yks scripts, possibly grouped by the game route.

Option A - Using YukaTool Gui

Drag and drop one of the .ykc archives onto yuka_gui.exe to open it in the archive viewer.
You can then search the left panel for any files you're interested in.

Image: Viewing files in YukaTool Gui

Viewing files in YukaTool Gui

Option B - Using YukaTool Cli

YukaTool Cli provides the list command, which allows you to inspect the files in an archive or folder.
Running yuka list data01.ykc will list all files in the data01.ykc archive.
Since I already know the files I'm looking for are contained in a folder called story, I will restrict the output by passing the filter *story* as the second argument to the list command.
If your terminal has issues displaying the special line characters used for the tree view, you can instead have the file names printed in a flat list by specifying the --list flag.

Image: Listing files with YukaTool Cli

Listing files with YukaTool Cli

2. Extracting Files

Now that we know where the files we want are located, the next step is to extract them.
In this case we are going to extract everything from the data01.ykc archive by using the command yuka unpack -v data01.ykc.
Notice that I specified the -v (or --verbose) flag. This will provide more detailed status information and will alert you of any problems that might occur.
The unpack command will now do its job and extract the entire archive into a folder with the same name.

Image: Extracting archives

Extracting archives

During extraction the proprietary Yuka file formats are converted into common formats for easy editing.
If one of these conversions fails, the original file will be copied instead.
You can disable the conversion for all files by specifying the --raw flag.

For more information on what the unpack command can do, type yuka help unpack.

3. Importing the Text Files

As you may have noticed, our .yks files from step 1 have now been turned into pairs of .ykd and .csv files.
YukaTool splits the text lines (.csv) from the rest (.ykd) so you don't have to deal with the code itself.
Depending on the game, YukaTool might sometimes not detect all of the text, if some strings are missing from the .csv file, have a look at the corresponding .ykd.

Image: Decompiled .ykd and .csv files

Decompiled .ykd and .csv files

CSV stands for "comma-separated values" and is one of the simplest and most widely supported file format for tabular data.
As such, we can simply import the generated .csv files into any spreadsheet application. For this example I will be using Google Docs.
First I'll create a blank spreadsheet, in which I will then import all of the .csv files. Make sure to keep every file in a separate sheet!

Image: Creating a Blank Spreadsheet

Creating a Blank Spreadsheet

Image: Importing Translation Sheets

Importing Translation Sheets

4. The Spreadsheet Format

Now that you've imported the text into your spreadsheet, let's take a look at how these tables are structured.
By default, every sheet has eight columns.

  • The ID is a unique identifier that helps YukaTool keep track which line of text goes where when reinserting the text.
    • It contains a letter denoting the type of string (Name, Line or String) and a sequential number.
  • The Speaker column contains the name of the character speaking that particular line.
    • As different games might use different mechanisms to set the current speaker, this might not be detected correctly.
  • The Original column contains the text as it was present when the files were unpacked.
  • All columns whose name is enclosed by [ square brackets ] are treated as translation revisions.
    • You can add or remove as many of these columns as you like, YukaTool will always choose the rightmost non-empty translation column for each line.
    • Cells containing just a single period . are treated as empty when inserting. This allows you to signal "no change needed" on a revision without leaving the cell empty.
    • If all translation columns are empty, the original text will be used.
  • The Comment column allows you to insert arbitrary comments, it is ignored by the script inserter.

At the top of every sheet you can find a list of the names of all characters speaking in that file.
This only works if the speaker names are detected correctly, otherwise they might be listed as a separate string for every line.

Underneath are all other lines and strings, in order of occurrence.
Entries with an S id might refer to choice text, dynamically generated lines or other text.
YukaTool does its best to filter out file names and other strings that don't need to be translated.

Image: Translation Sheet Structure

Translation Sheet Structure

5. Reinserting the Text

Now, let's assume you've made some edits to the translation sheet and want to check if the changes look right in-game.
First of all you will need to export the modified spreadsheet back to a .csv file.

Image: Downloading as .csv

Downloading as .csv

After you've done that, use this new version to replace the original .csv file. Make sure the name matches that of the corresponding .ykd file.
In my case I have to replace the CHAPTER1-1.csv file in data01\yks\story\common\.

If you haven't already done so, now would be a good time to create a backup of the original game archive, because next we will repack all the files we previously extracted.
For me, the command yuka pack -v data01 will do the trick. Note that I'm specifying the folder name this time, not the archive name.

For more information on what the pack command can do, type yuka help pack.

Image: Repacking the Archive

Repacking the Archive

And that's it, your text is now in the game!

Image: Text in the Game

Text in the Game

6. Closing Remarks

Of course there is more to a good localization than just translating the text.
Editing menu graphics is pretty straightforward, since YukaTool automatically converts .ykg graphics to .png and vice versa.
If you want to change the font name or size, search for a script containing a call to the function DefaultFontSet.
The second parameter (most likely an @S reference to an entry in the .csv file) is the font name, the third one the font size.

Finally, if you end up using YukaTool I would be glad to hear about your project!
Let me know if I you need help with anything, either per GitHub issue or on Discord (AtomCrafty#4511).
And good luck :)

Game Support

This is a list of games utilizing the Yuka engine and how well YukaTool works with their files.
Let me know if you find any games not listed :)

Year Developer Title Compatibility YKC YKG YKS
2007 Feng Akane Iro ni Somaru Saka ⚠ Partially compatible1
2008 PeasSoft Tsun na Kanojo Dere na Kanojo ✔ Fully compatible
2010 PeasSoft Ama Ane ✔ Fully compatible
2010 Hooksoft Sakura Bitmap ⚠ Partially compatible2
2010 Feng Hoshizora e Kakaru Hashi ⚠ Partially compatible3
2011 Smee Lover Able ✔ Fully compatible
2011 Hooksoft Strawberry Nauts ✔ Fully compatible
2011 PeasSoft Iinazuke wa Imouto-sama! ✔ Fully compatible
2011 PeasSoft Kimi o Aogi Otome wa Hime ni ✔ Fully compatible
2011 PeasSoft Amakan Ecchi na "Love Icha" Tsumechaimashita ✔ Fully compatible
2012 Feng Hoshizora e Kakaru Hashi AA ✔ Fully compatible
2012 Smee Dousei Lover Able ✔ Fully compatible
2012 PeasSoft Zutto Tsukushite Ageru no! ✔ Fully compatible
2013 PeasSoft Koisuru Shimai no Sextet ⚠ Partially compatible4
2013 PeasSoft Shitsuji ga Aruji o Erabu Toki ⚠ Partially compatible5
2013 PeasSoft Koi x Koi = Infinity ~Koisuru Otome ni Dekiru Koto~ ⚠ Partially compatible6
2014 Caramel Box Semiramis no Tenbin ⛔ Different engine version7
2015 Caramel Box Semiramis no Tenbin - Fated Dolls ⛔ Different engine version7
  1. There's a bug when unpacking .bmp files.
  2. Decompiling battle.ykc and init.yks results in the error Assignment target already set.
    Some graphics in ykg\coin\ appear to be glitched.
  3. Decompiling ui_017.yks results in an invalid cast (CInt -> Ctrl).
  4. Decompiling bgmmode.yks, CGMode.yks, config.yks, Confirmation.yks, loadmenu.yks, menu.yks, omake.yks, savemenu.yks, SCMode.yks, Start.yks and TextWindow_SystemSelect.yks results in the error Invalid expression element: Func.
  5. Decompiling bgmmode.yks, config.yks, Confirmation.yks, GalleryMode.yks, loadmenu.yks, menu.yks, savemenu.yks, start.yks and TextWindow_SystemSelect.yks results in the error Invalid expression element: Func.
    Assertion failure in mayu_00410.yks due to a malformed if statement (pretty sure this is a bug in the game script).
  6. Decompiling bgmmode.yks, CGMode.yks, config.yks, Confirmation.yks, loadmenu.yks, menu.yks, omake.yks, savemenu.yks, SCMode.yks, Start.yks and TextWindow_SystemSelect.yks results in the error Invalid expression element: Func.
    Decompiling all_00791.yks, all_00810.yks, all_00820.yks, all_00830.yks, all_00840.yks, all_00851.yks, all_00861.yks, all_00901.yks, all_00920.yks, all_00930.yks, all_00960.yks, all_01020.yks results in an invalid cast (CInt -> Ctrl).
    Assertion failure in chris_00300.yks due to a malformed if statement (pretty sure this is a bug in the game script).
  7. Assertion failure due to new archive signature (YKC002\0\0).
    Hard crash while trying to unpack .csv files.
    Script files are not recognized as such due to new file signature (YKS002\0\0).
    Non-ascii file names get corrupted when unpacking, maybe the encoding changed with the new container format?

If you discover any other games using this engine, please contact me so I can add them to the list.