[Tutorials] [Case Study][NScripter]Obake Oujo wa Haka no Shita

Entai2965

Moderator
Moderator
Elite Member
Dec 28, 2023
86
42
zompri.png


While most of this guide is formatted as a case study, this is more of an information sharing thread for the original Japanese nscripter game engine and how to work with it using a particular title as an example.

The documentation for the original nscripter engine is all in Japanese, so this post aims to have essential information about the nscripter game engine in English to use as a reference for translating. If you are only looking for updated tips and examples for how to translate nscripter script text, then just scroll down past the case study posts to the tips at bottom.

There is a translated version of some outdated reference material available in the nscripter.insani sdk and online reference for the nscripter insani fork, but that is not really relevant when translating especially when only using original Japanese version of nscripter.

For this case study, the game in question is おばけ王女は墓の下, Obake Oujo Hahaka no Shita, which could be translated as Ghost Princess Under the Grave. This post is the story of how the game patch that translates the game was created.

VNDB: https://vndb.org/v10687
Download: https://www.freem.ne.jp/win/game/3290

Additional game resources:
Translation (TL): https://archive.org/details/ghost-princess-under-the-grave
Thread: https://www.anime-sharing.com/threa...in-obake-oujo-wa-haka-no-shita-v10687.1541060

Text-based English translation of a short freeware yuri visual novel, Obake Oujo wa Haka no Shita (おばけ王女は墓の下). The game is still available to download on Freem. The translator's LiveJournal, where the English translation was published, became unavailable sometime after 2020, and the translation was not preserved in the Wayback Machine.

TL DL: https://archive.org/download/ghost-princess-under-the-grave
TL raw text: https://archive.org/download/ghost-princess-under-the-grave/ghost-princess.txt
TL Patch: https://archive.org/download/ghost-princess-under-the-grave/zompri-patch.rar

The game seems to be a short story with supernatural and yuri themes.

After extracting the archive using 7-Zip, the following files are inside of the zompri folder.

Code:
00.ns2
nscript.dat
nsogg2.dll
read_me.txt
zompri.exe

Launch it to make sure it works and then close it after the first few lines of dialogue appear. Like many eastern visual novels, it requires a locale emulator to display the characters properly.

zompri_firstline.png


So, how is it possible to start translating it? The first step is always to figure out the game engine in use. The simplest way to figure that out for VNs is usually to use Garbro and also to look at the files in the main game folder. Let's look at the files first before using Garbro.

- zompri stands for "zombie princess" maybe? That sequence of characters is used for the folder name and the main executable, so it should have some relationship with the game title. Obake means ghost, not zombie though. For simplicity's sake, I will refer to this game as "zompri" for the rest of this guide since that is easier for westerners to type and understand compared to Obake Oujo.
- nscript.dat probably has the game's dialogue scripts because it has "script" in the name.
- It is not clear what 00.ns2 is for, but it is a fairly large file relative to the other game files. Perhaps that is the main data archive for the game's assets?
- What is nsogg2.dll? right-click->Details shows the following information.

nsogg2.dll.png


So it is file version 1.0.0.1, copyright by Xiph.org Foundation, and related to libogg. I happen to know that libogg is related to the vorbis audio codec and .ogg containers. Xiph.org also has some information about it for anyone unfamiliar with audio codecs.

.dll stands for "Dynamic Link Library" which is a way of linking software libraries to programs at runtime. This allows zompri.exe program the ability to access functions external to the executable file itself. In other words, nsogg2.dll probably has something to do with providing audio services to zompri.exe, likely related to the ogg vorbis audio codec. If there are a lot of .dll files in the game folder or subfolders, it is usually a good idea to ignore them since they tend to be plugins for the game engine, not unique to the game engine itself.

If ogg is short for "ogg vorbis" and ".dll" is a library linking format, then what do the rest of the characters in "nsogg2.dll" refer to, the "ns" and the "2"? Do these characters appear elsewhere? "00.ns2" has both of those characters together and "nscript" has the "n" character. In other words, the characters "ns" likely have special meaning to this game and provide an important clue when trying to figure out what game engine it might be using.

Next is read_me.txt. Since .txt means it is likely a text file, open it in Notepad++. Most text files for Japanese games are encoded in either utf-8 or shift-jis. utf-8 supports all languages. shift-jis is an older encoding intended to support only Japanese. Notepad++ should display "Shift-JIS" at the bottom right corner for read_me.txt. Notepad++ has some autodetection code, but it does not always work. If the bottom right corner does not say utf-8 or shift-jis when reading files in Japanese, then select the correct encoding manually. Encoding->Character sets->Japanese->Shift-JIS. That tells Notepad++ which character set to use so it can display the text properly. It does not alter the original text, only the way characters are displayed.

notepadplusplus_shiftjis.png


Code:
--------------------------------------------------
Windows対応 百合ファンタジー短編ノベル
----------------------------------------2011/06/18

タイトル:おばけ王女は墓の下
バージョン:Ver1.0

■はじめに

 DLして頂き、誠にありがとうございます。
 短く拙い作品ですが、少しでも何か心に残れば幸いです。

■動作環境

 DirectX8以上 Windows98/Me/2000/XP/Vista/7
 640x480(VGA)でフルカラー(24bit)表示可能な環境

■基本操作

 左クリック・エンターキー・スペースキー等で読み進めて下さい。

■ゲームを始めるには

 まずは、圧縮ファイルをフォルダごと解凍して下さい。
 フォルダ内の「zompri.exe」を起動すればゲームが始まります。
 アンインストールは、フォルダごとゴミ箱へポイっと。

■ご注意下さい

 本ゲームを使用したことによるいかなる損害についても、ユキ子は責任を負えません。

 本ゲームの著作権はユキ子に、使用素材の著作権は各製作者様にあります。
 これらの無断転載・再配布・二次加工はご遠慮下さい。

 ご理解の上、ゲームをプレイして下さいますようお願い致します。

■ご協力に感謝!(順不同、敬称略)

 Takahashi's Web
  http://www.nscripter.com/
 NEO HIMEISM
  http://neo-himeism.net/
 G2-MIDI
  http://guru2.nobody.jp/
 WEB WAVE LIB
  http://www.s-t-t.com/wwl/

■製作元・連絡先

 ご意見、ご感想、誤字脱字の報告などはこちらへ。

 制 作:晴れ時々グラタン/ユキ子
     http://hanikamuaisuman.web.fc2.com/game.html

 連絡先:[email protected]
     一週間経っても返信が無い場合、再度ご連絡下さい。
Code:
-------------------------------------------------- Yuri Fantasy Short Novel for Windows
 ----------------------------------------2011/06/18
Title: The Ghost Princess Under the Grave
Version: Ver1.0
■ Introduction Thank you very much for DL. It's a short and clumsy work, but I hope it will leave a lasting impression on you.
Operating environment DirectX8 or higher Windows98/Me/2000/XP/Vista/7 640x480 (VGA) full-color (24-bit) display environment
■ Basic operation Please read with left-click, enter key, space key, etc.
■ How to start the game First, unzip the compressed file as a folder.
Launch "zompri.exe" in the folder to start the game.
To uninstall, pop the entire folder into the trash.
■ Please be careful Yukiko cannot be held responsible for any damage caused by the use of this game. The copyright of this game belongs to Yukiko, and the copyright of the materials used belongs to each producer. Please refrain from unauthorized reproduction, redistribution, or secondary processing. Thank you for your understanding before playing the game.
■ Thanks for your help! (In no particular order, titles omitted)
Takahashi's Web http://www.nscripter.com/
NEO HIMEISM http://neo-himeism.net/
2-MIDI http://guru2.nobody.jp/
WEB WAVE LIB http://www.s-t-t.com/wwl/
■ Manufacturer and contact information
If you have any comments, comments, or reports of typographical errors, please click here.
Production: Sunny Sometimes Gratin / Yukiko http://hanikamuaisuman.web.fc2.com/game.html
Contact: [email protected]
If you do not receive a reply within a week, please contact us again.

It is always nice when game developers properly document the tools they used to create their game. The first link in the readme leads to https://www.nscripter.com/ which says ゲーム/ゲームエンジン/ライブラリの制作・配布サイトです。 which could be translated to "This is a site for the production and distribution of games, game engines, and libraries." Thus, it looks like the game's read_me.txt file implies that it is using game engines and libraries related to NScripter.com. In other words that string that keeps repeating, "ns", in all the game files likely refers to "nscripter".

Here are some random websites that pop up when searching for nscripter.

- https://en.wikipedia.org/wiki/NScripter
- https://ja.wikipedia.org/wiki/NScripter
- http://nscripter.insani.org/
- http://nscripter.insani.org/about.html
- https://kaisernet.org/onscripter
- https://github.com/Galladite27/ONScripter-en
- https://github.com/YuriSizuku/OnscripterYuri

That is a lot of information to read through, but once complete, the initial conclusions are that nscripter has a lot of forks and that it looks like a nightmare to deal with all of them. Yikes. The original nscripter is probably also the least friendly to use for translation given that there are so many forks stated for the purpose of improving the ability to translate nscripter games because the original engine is lousy at it.

Which one is zompri using? Well, if the read_me.txt points to nscripter.com, then it likely uses whatever version is on that site. Which version or versions are on that site?

Under the ソフトウェア, software, heading nscripter.com has download links for nscripter 2018, nscripter 2015, nscripter2, something related to unity, something related to ruby, a mysterious link that has a similar archive name to the ruby archive, and some documentation. Unity is a game engine. Ruby is a general purpose scripting language.

The read_me.txt says the game was released on 2011-06-18 and wikipedia says the NScripter2 engine was not released until 2012-August-31, so one year after the game was released. That means it is highly unlikely that zompri was created on NScripter2.

Technically, there is no confirmation yet that zompri uses the nscripter game engine or which version it is using. Considering the read_me.txt points to nscripter.com, that makes it very likely zompri uses the original and latest version of the Japanese NScripter game engine as of 2011. Is there any way to falsify that hypothesis?

Back inside of Garbro, clicking on all of the files in the game directory asks Garbro to open them as text files, pictures, or archives. Garbro cannot open the nscript.dat file, but it does open that 00.ns2 file as an archive. At the bottom left, Garbro displays the file is an "NScripter game engine resource archive".

garbro_00.ns2.png


In addition, after looking around for a bit, one of the nscripter forks makes multiple references to an nscript.dat file which is indeed found in the zompri game directory. http://nscripter.insani.org/sdk.html says,

nscmake.exe -- takes your script file (0.txt) and converts it into compiled bytecode for the runtime binary (nscript.dat).
[...]
NSDec
[...]
Contents: extracts the script from any given nscript.dat.

Taking all of that information together, that makes it overwhelmingly likely that this game uses the nscripter game engine. With that confirmed, it is time to figure out how nscripter assets, like images and the game script, can be extracted and packed again so the zompri game can read them.

Extracting contents from the 00.ns2 file is easy since Garbro has already shown it can peak into the archive. Browsing around, it also seems to render the images correctly meaning that they are not obfuscated or encrypted.

Obfuscated means the bits are manipulated in an obscure way to make them difficult to render for someone unfamiliar with the series of steps, the algorithm, used to obscure them. Encrypted means the contents are permanently altered using an algorithm, also called a "cipher", while under the influence of an encryption key. For encrypted contents, it is impossible to recover the original contents perfectly without knowing the encryption key even if the cipher is known.

00ns2_bene.png


Just extract the contents of 00.ns2 to a folder named zompri\extracts\00.ns2 or similar.

Next is the script. Does the original game engine provide a way to unpack the script? Usually the answer is no.

Game developers have the original assets they packed into archives for distribution, so they do not usually need unpacking tools at all. While such tools are useful for obscure debugging, usually only the creator of the engine will have that, if they created it at all, and there is no expectation of them including such an engine debugging tool in the engine's software development kit (sdk) since that is not very useful to game developers.

The original game engine and related sdk tools are preferred when packing assets because that was the software that originally created them and it already knows how to do it without producing any additional bugs in a compatible way. The issue with this approach is that the original engine may not be published or otherwise available. It means the engine's archive and script formats need to be reverse engineered which can be very messy, buggy, and difficult, especially when packing.

Due to the above dynamics, it is normal to look for third party unpackers, like Garbro, since they are unlikely to be part of the original engine sdks and to try to use the original engine's tools for packing, provided the engine sdk is available. If the original engine sdk is not available, such as because the engine developer never published their engine as an sdk, then looking for third party packing tools may be necessary, but this is never ideal. Using the original engine sdk is almost always ideal because that is the way the assets were meant to be packed.

http://nscripter.insani.org/sdk.html has their own "Development and Translation Utilities" for working with nscripter, but that is a fork. The original engine is over at nscripter.com although it has had some updates since 2011.

Let's download nscripter.insani's NSDec script unpacking tool because that is unlikely to be part of the game engine and the Japanese nscripter 2018 sdk. If the latest 2018 sdk is not compatible with zompri, a 2011 game, then we can try the 2015 sdk version. If that fails too, then we could try using the nscripter insani fork sdk version from 2005. Since it might be useful, here is the nscripter documentation archive as well.

Here is what those archives look like in 7-Zip.

tools_archives_mojibake.png


All of the file names are in mojibake which indicates character set decoding errors. Just like text files have character encoding, the metadata of .zip files that determines the name of each file and folder in the .zip also has an associated encoding. 7-Zip and Windows Explorer assume the encoding of the files is in either utf-8 or the local Windows/ANSI code page. If the metadata was encoded as utf-8, then it would always work, but since it is not utf-8, then the local code page is used instead. If the local code page is English/cp437 but the .zip file was created by Windows under Japanese/cp932/shift-jis, then neither Windows nor 7-Zip will be able to properly decode the file names using the local English/cp437 code page. That is not the correct way of decoding those characters.

The only valid encoding for Zip files since 2006 is utf-8 which is a character set that supports all languages.

However, all versions of Windows up to and including Windows 10 22H2 that support creating zip files with Windows Explorer use the local ANSI/Windows code page for the file and folder name encoding. I did not test Windows 11. For versions of Windows with the region set to Japanese (Japan), that means the .zip files are always encoded with cp932/shift-jis. In other words, all .zip archives created by Windows Explorer are always malformed if they contain non-ascii characters.

There is no technical reason for this incorrect behavior. Microsoft could have been updated Windows sometime during the last two decades to fix this incorrect non-standards compliant behavior, but they never did until at least up to Windows 10 22H2. This problem of having incorrect .zip file encodings really only occurs because Windows has the ability to create malformed .zip files. WinRar and newer versions of 7-Zip do not have this problem because they always create archives, including .zip, using utf-8 encoding. The archive formats .rar and .7z also mandate utf-8, so they never experience this problem which leaves Windows Explorer as the remaining culprit. Note that older versions of 7-Zip (<21.02 alpha) also have this incorrect behavior but that was fixed years ago. Only Windows Explorer continues to create these malformed .zip files.

Technically, only the names are malformed, not the underlying data. However, leaving the names malformed is not advisable because sometimes files look for or require other files based upon their name which means the extracted files may not work without the correct name. Even if they do work, having the folder names correctly decoded can provide hints as to what the different files and folders contain.

Recommendations:
- Never use Windows Explorer to create .zip files because it does not encode file metadata correctly which results in it producing malformed .zip files which require users to guess the correct encoding to decode them.
- Use a newer version of WinRar or a version of 7-Zip newer than 21.02 alpha to create .zip files.
- Consider using the .7z or .rar archive formats instead of .zip because these formats effectively side-step .zip file encoding issues. They are also known to be incompatible with Windows Explorer which should encourage others to use dedicated archiving software that is not Windows Explorer.

The rationale for the above recommendations is that it is overly cumbersome to change the local code page to whatever the zip file was encoded with every time. In general terms, it is also a better idea to forgo using broken software completely and not encourage its use further. Windows Explorer's zip file functionality is broken and should therefore be treated that way.

Viable options for decoding malformed zip files:
7-Zip's graphical user interface (GUI) does not support manually specifying the zip file metadata character encoding. The 7-Zip GUI, 7zFM.exe, will read the encoding correctly if the correct code page is used on the local system. In situations where the .zip file has metadata encoded with a different code page than the local code page, 7-Zip's GUI will not be able to extract the files with the correct names. 7-Zip does support specifying the correct code page in the command line interface (CLI) using the undocumented -mcp= switch. The number of the Windows code page should be specified after the -mcp= as in -mcp=932 or -mcp=65001.

An example of a code page number is 932 which is more or less equivalent to ANSI Shift-JIS encoding. 437 is English/DOS. To check the active code page, open a command prompt and type "chcp". A list of encodings is available in the Python documentation.

Code:
"C:\Program Files\7-Zip\7z.exe" x -mcp=932 nscr_2018.zip

Linux users can use the cli program "unzip" with the -I (capital i) or -O (uppercase o) options to specify shift-jis encoding.

Code:
unzip -O shift-jis nscr_2018.zip

Python 3.11+ also works for as a cross-platform solution since the zipfile module was updated in Python 3.11 to support the --metadata-encoding cli option.

Code:
python --version
python -m zipfile --help
python -m zipfile -l nscr_2018.zip --metadata-encoding shift-jis
python -m zipfile -e nscr_2018.zip . --metadata-encoding shift-jis

Summary:
- Windows: WinRar GUI, 7-Zip's CLI, or Python 3.11+'s zipfile module.
- Linux: "unzip" CLI, 7-Zip's CLI, or Python 3.11+'s zipfile module.

To fix the malformed encoding, use archiving software that allows specifying code pages for .zip metadata. On Windows, the laziest solution is to use a newer version of WinRar. If you are comfortable with a command line, 7z.exe and Python 3.11+ are viable alternatives as well. For the CLI syntax for 7z.exe and Python, open the spoiler above. Alternatively, use WinRar.

For newer versions of WinRar:
1. Open the archive using WinRar
2. Options->Name encoding->932 (OEM/ANSI Japanese Shift-JIS)
3. "Extract to"
4. OK
5. Repeat for all 3 archives

tools_archives_winrar.png
 
Last edited:
So back to our original objective, unpack and pack the assets and scripts so that zompri can read them.

Specifically, we are looking for tools that can create .ns2 archives from generic files and nscript.dat. The usual order is to try to repack archives into a format the game engine can understand prior to focusing on scripts, so lets start there.

Browsing around the extacted files from the archives leads to a lot of files called 0.txt or 00.txt. It also eventually leads to the following interesting tool names from the SDK.

Code:
"zompri\otools\nscr_2018\NScripter最終版\ツール\NS2Arc.exe"
"zompri\otools\nscr_2018\NScripter最終版\ツール\nscmake.exe"
"zompri\otools\nscr_2018\NScripter最終版\ツール\nscmake2.exe"

NS2Arc.exe seems like it might be a promising first start to create .ns2 archives because it has "NS2" in the name and "Arc" probably stands for "archive". ツール also translates to "tool" which is exactly what we are looking for, this game engine's tool for creating .ns2 archives.

Double clicking on it results in a command prompt popping up and a message box titled "Browse for Folder". Since there are some mojibake characters on the next line, it is better to close it and start the tool again using a locale emulator set to Japanese, Japan.

Leave it as-is, if you dare, or restart it and then select the Garbro files extracted from earlier.
tool_ns2arc.png

tools_ns2arc_2.png


Close the NS2Arc.exe command prompt when done. For now, I am putting all repackaged files in a folder named repacked\ to clarify their origin. Then copy or move that packed 00.ns2 file to the folder containing the original 00.ns2 and replace it with the packed version.

After launching the game again, it loads all the way to displaying the first line of the game again. From this, the archive repackaging tool seems to work. Now, let's modify some of the images and see if it is possible to repackage the game with translated images.

For an image editor, I am using Krita which is an open source cross platform image editing and drawing program. Some alternatives are mspaint, paint.net, photoshop, and gnu image manipulation program (gimp).

The important part is to save the files in the same format the original game engine uses. In this case, the game uses .jpg files formatted as 640x480, RGB, 8-bit.

Here is what the first image looks like when not quite translated in Krita.

kirita_translation.png


Save it as extracts\00.ns2\uta1.jpg, overriding the original (after creating a backup of the original of course). Then repeat the steps above with the packing tool NS2Arc.exe to create a new 00.ns2. After loading it in game, this happens.

kirita_translation2.png


In other words, modifying the .jpg files using a normal image edit is enough to translate the images. They do not need any additional special manipulation beyond unpacking and repacking.

Next is unpacking and repacking the scripts. nscripter.insani's NSDEC.exe was extracted earlier and has this description.

NSDec
Listing Updated: 2005.06.02
Author: Liquid Systems
Platform: Win32
Size: 15KB
Contents: extracts the script from any given nscript.dat.

*click*

Hummm. It created an empty file called result.txt. Running it again within the context of a command prompt results in an error saying that it could not read input. Based upon the description, it seems to work using nscript.dat which is missing.

Let's delete the empty result.txt file, copy the nscript.dat file to the NSDEC folder, or copy NSDEC.exe to the zompri\ folder, and then try double clicking on it again with the two files next to each other. Right-click on NSDEC.exe->Run with Japanese locale.

tool_NSDec.png


All I see is mojibake. Changing the locale of the program does not change the locale of the command prompt which the program is using apparently. Sometimes, mojibake will create logic bugs but sometimes it only affects the way the data is displayed. The underlying processing may still be processing correctly. If the underlying data is getting corrupted, then switching the locale to Japanese, Japan and trying again is unavoidable. On the other hand, it may not be needed if the mojibake is purely cosmetic. Which one is it?

Here is the produced result.txt.

Code:
*define
nsa

caption "おばけ王女は墓の下"
versionstr "おばけ王女は墓の下 Version1.0","(C)2011 晴れ時々グラタン"

effectcut
[...]
ld l,":a;bene.jpg",9
「ララ、ララはどこ」@
 捨て子であったララを拾ったのは、ベネディクティンその人でした。@
 ベネディクティンは王女なので、ララはその侍女ということになるのでしょう。\

Since it has the first line of the game with an @ symbol after it, it probably extracted correctly. If it turns out to be corrupt later, then we can change the locale later and try extracting the game script again to see if the extraction tool needed it.

Another point of comparison is the documentation folder extracted earlier. Over at "zompri\otools\nscr\サンプル\メニューのカスタマイズと複合ボタン\0.txt" the syntax found within the file seems to match the extracted result.txt including having an @ at the end of a line of dialogue. There are also a lot of other files named 0.txt and 00.txt in the documentation that have very similar syntax. This raises the probably that the script was extracted correctly because it matches the templates.

Before making any changes to result.txt, always try repacking the unmodified contents to see if the repacking workflow works. That helps seperate out repacking errors from script parsing errors.

That said, how does result.txt get converted back to nscript.dat anyway? Going back to the NScripter 2018 SDK (zompri\otools\nscr_2018\NScripter最終版\ツール), there are 2 more files next to NS2Arc.exe called nscmake.exe and nscmake2.exe.

Right-click nscmake.exe->Run with Japanese locale.
A 'Browse for Folder' appears.

What is it looking for? Let's try specifying a folder that has only the results.txt file in it.

And put the resulting file at repacked\nscript.dat. The resulting file is 0 bytes in size. Clearly that did not work. Why not? Trying to do the same thing with nscmake2.exe just ends with a prompt and produces another 0 byte nscript.dat.

Humm. All of the examples in the documentation folder nscr\ always have the script files named 0.txt or 00.txt. In addition, the nscripter.insani documentation states the following.

nscmake.exe -- takes your script file (0.txt) and converts it into compiled bytecode for the runtime binary (nscript.dat).

In other words, all of the documentation assumes the script file is called 0.txt or 00.txt and never result.txt. Let's try renaming result.txt to 0.txt to see if that matters.

Code:
zompri\otools\NSDEC\output\0.txt

The resulting nscript.dat is 11978 bytes. The original nscript.dat is 11977 bytes. Since they are not exactly the same number of bytes, their hashes will not match, but those numbers are similar enough to imply that they could be exceedingly similar files. Opening them both in Notepad++, they both have the same header and look exactly the same for the first 20 lines.

After replacing the original nscript.dat in the game directory with the repacked nscript.dat, the game continues to work normally after relaunching it. In other words, this workflow works to repack the script. In other words, nscmake.exe does require the input script to be named 0.txt.

The next step is to make changes to the script and see if those changes display correctly.

Opening the script, there are a lot of lines that start with control sequences like caption, versionstr, effectcut, insertmenu rmenu and so forth. As a rule, only text that is displayed should be translated. Only the dialogue is required to be translated but it is ideal to hopefully also get the UI translated. Texts that relate to game engine or game specific functions, comments, and any text that does not display should not be translated.

Because translating the dialogue is the highest priority, let's start there. The first line of the game is "「ララ、ララはどこ」" and it appears in the following code block.

Code:
「ララ、ララはどこ」@
 捨て子であったララを拾ったのは、ベネディクティンその人でした。@
 ベネディクティンは王女なので、ララはその侍女ということになるのでしょう。\
After a lousy quality translation that becomes:
Code:
"Lara, where's Lara?"@
Benedictine herself picked up Lara who was abandoned as a child.@
Benedictine was a pricess, so Lara, of course, became her handmaiden.\

Browsing through the script, it becomes obvious very quickly that after every line of dialogue there is some sort of symbol, @, \, or /. Those are probably control characters that tell the engine to do something. It is probably best to leave those alone when translating the text since those could be considered script syntax which should not be translated. What do they mean exactly?

Anyway, leaving them alone produces a script that looks like this.

Code:
goto *ss_menu
*game_start
dwavestop 1
bg "uta1.jpg",5:bgm "scherzo.ogg"
click
stop
bg black,4:stop:bg white,9
bg "kabe.jpg",3:bgm "waltz.ogg"

ld l,":a;bene.jpg",9
"Lara, where's Lara?"@
Benedictine herself picked up Lara who was abandoned as a child.@
Benedictine was a pricess, so Lara, of course, became her handmaiden.\
ld r,":a;lala.jpg",9
「はい、お呼びで……」
「ララ、跪きなさい」@
 これは、王女の口癖のようなものでした。@
 ララは飽き飽きとした顔で舌打ちをひとつ、/
cl r,9
そして床に伏します。\
 流石の王女も不満げに眉を寄せて。@

The next step is to save the file and use nscmake.exe again to create nscript.dat again.

dialogue1.png


Loading the resulting file makes the game crash.

At this point, I tried various things like using the onscripter syntax of prepending each line of dialogue with `, the character next to 1, (that functionality is not part of the original nscripter game engine, so it did not work), replacing the game engine with made the menu bar disappear because that is not implemented in onscripter_en, and some other things, but I eventually gave up at this point and put the project on hold.

Displaying half-width latin characters (a-z) as the first character always caused the engine to crash no matter what I tried, and I just could not figure it out.

However, @Vice managed to figure out that if a line is prepended by a full width Japanese space " " \u3000, then the script does not crash. It was that piece of creative insight that allowed progress to continue at this point and eventually allowed @Vice to produce the patch found on archive.org based upon the web translation.

However, just because a patch was possible does not mean it was simple to create.
Code:
 "Lara, where's Lara?" @
 Benedictine herself picked up Lara who was abandoned as a child. @
 Benedictine was a pricess, so Lara, of course, became her handmaiden. \

dialogue2.png


The ? character is a reserved symbol in nscripter so it had to be changed to the full width version ?. Otherwise, it always crashes the game engine. There should be a way to escape the ? to tell the game engine to output a literal ? instead of using it as a symbol, but neither Vice nor I could figure it out. The escape character for most languages is usually \, as in \?, but in Nscripter, \ means to wait for user input and then clear the screen.

dialogue3.png


Using \ as an escape character can crash the game engine's script interpreter, so that is not it.

Moving on. Here is a very similar line to the one above.

Code:
 "Lara, where's Lara?"@
 Benedictine herself picked up Lara who was abandoned as a child.@
 Benedictine was a pricess, so Lara, of course, became her handmaiden.\

dialogue4.png


- The difference is that there is no empty space right before the last character.
- Word wrap is automatic but also performed per character, not per word.

Code:
 "Lara? Where are you Lara?"@
 Benedictine herself picked up Lara who was abandoned as a child.@
 Benedictine was a princess, so Lara, of course, became her handmaiden. \

dialogue5.png


- The first ? is not displayed properly. Later, it became clear this is because the engine has issues dynamically switching back and forth between half width and full width characters placed in the same line.
- The first pause character @ is displayed as a literal character and its functionality as a control character is ignored in the process. One could conclude this was because no blank space was before it, but then why does the @ in "as a child.@" work as intended as a control character instead of a literal @? That @ in the second line does not have a blank space before it, but it works as intended, so why does the first one not do that?
- Spaces also semi-randomly get deleted with results in words concatenating.

At this point, it should be apparent that this engine has a lot of quirks in how it is interpreting its own script syntax. The next step to translate this game is to try to decipher the nscripter script syntax into a set of rules to follow when generating each translated line. That means either reading documentation or experimenting.

There is some outdated documentation translated over at nscripter.insani as part of their SDK and it is also available in their online reference. The "updated" documentation is at nscr/旧マニュアル/index.htm from the archives extracted earlier, but it does not seem to have been updated in a while. It seems quite bare bones actually meaning that is more of a last-resort reference than actual documentation. The actual useful documentation, as opposed to developer reference material, is in various examples scattered throughout the folders, so finding an example that uses half width latin characters would be ideal but there is no gurantee that exists and requires looking through the entire contents of over a dozen files.

The other way to decipher the syntax is simply to ignore the documentation and experiment to see what works and what does not work.

The main benefit of the experimentation approach is that each piece of knowledge gained this way was gained through actual testing meaning that it actually works. The information contained in the documentation is purely theoretical. The engine documentation could be out of date, too new compared to the game engine zompri.exe uses, and/or just plain wrong sometimes. Any information in the documentation also needs to be tested anyway, so it can be tempting to skip reading the documentation and go straight to testing.

In my case, I experimented to create some rules to follow. Later I found some interesting documentation at nscr\新マニュアル\追加命令一覧.txt with the following information:

Code:
【english】
NScripterを英文モードにします。半角英字のみの文章を正しく表示できるようになります。
このモードを使う時は、行頭を>にしてください。
例)
*define
english
game
*start
>Peter Piper picked a peck of pickled peppers;@
end

Translation: Put NScripter in English mode. You will be able to correctly display sentences with only half-width alphabetic characters. When using this mode, the beginning of the line should be >.

Applying this to zompri results in the following.

Code:
>"Lara? Where are you Lara?";@
>Benedictine herself picked up Lara who was abandoned as a child.;@
>Benedictine was a princess, so Lara, of course, became her handmaiden.;\

[dialogue6]

In other words, the ; at the end is mostly pointless and lines display exactly like inserting a full width space at the start. Mysteriously, the @ symbol that is ignored gets switched around with the first one pausing correctly and the second @ now gets rendered literally.

Are the concatenated words really "correctly" displayed? This seems like a really obvious oversight by the engine developer. Did they literally never test their software? Going back to the example syntax, it does say to add an extra command "english" after *define and before *start.

Code:
*define
english
game
*start

The zompri script looks like this.

Code:
 effect 11,18,1500,"wasyoi.jpg"

transmode alpha

 game

*start

Updating it results in the following script.
Code:
 effect 11,18,1500,"wasyoi.jpg"

transmode alpha
english
 game

*start

[dialogue7]

Okay, that makes more sense now. Adding the "english" control characters before "game" and "*start" makes spaces work correctly and the @ symbols stop being rendered literally half the time. It also allows question marks ? to be rendered without having to convert it to the full width version even outside of quotes. The subsequent Japanese lines are still rendered correctly which makes me wonder why this is not always enabled in the engine itself. Maybe to maintain backwards compatibility or something?

That is the end of the case study. The rest of this post is just reference material for working with the nscripter game engine.
 
Last edited:
  • Love
Reactions: Eir
I reached the max number of images per post, 10, so here are the Dialogue 6 and Dialogue 7 images from the above post.
Dialogue 6:
dialogue6.png


Dialogue 7:
dialogue7.png


In summary, to unpack and repack assets:
- Garbro works to extract the assets in 00.ns2 and the original SDK from the mainline nscripter engine (2018) contains NS2Arc.exe to repack assets back into 00.ns2 archives which the game engine can read.
- For scripts, use NSDEC.exe (tested) or nscript.dat-tool (untested) with nscript.dat in the same folder to convert the script file to results.txt/nscript.txt which contains the translatable plaintext of the script along with the script commands and functions.
- To repack the script, rename results.txt/nscript.txt to 0.txt and use nscmake.exe from the official game engine sdk to create nscript.dat which the game engine will read again.

Here is some more documentation from nscr/旧マニュアル/index.htm about those mysterious control characters at the end of every line.
Code:
 表示文の説明
表示文には、全角文字と、次の特殊文字が使えます。
【@】
 クリック待ちをします。
【\】
 改ページ待ちをします。直後の改行は無視されます。
【/】
 これのすぐ後に改行を書けば、その改行は無視されます。
Translation:
Code:
Explanation of the display statement
You can use double-byte characters and the following special characters in the display text:
【@】 Wait for a click.
【\】 Wait for a page break. Immediately following a newline is ignored.
【/】 If you write a newline immediately after this, the newline will be ignored.

The translated nscripter insani documentation is even more confusing and less helpful, so here are some clarifications.
- @ will always render in a new line in english mode. In normal full width mode, it will just append to the current line.
- Another way of thinking about \ is that it clears the screen after the user clicks past the current line. If every line ends in \, then each line will display in its own screen. When @ is used, the next line is added to the currently displayed text. If the currently displayed text attempts to render outside of the program window because every line ends in an @, then the game will crash, so \ is used to clear the screen before that crash happens.
- Another way of thinking about / is that it concatenates the next line of script to the current line in the script. The point of this is to include some visual or script effect, like a character appearing or disappearing, in the middle of a line of dialogue without requiring user interaction before the effect can occur like with @ or \.
Example:
Code:
「はい、お呼びで……」
「ララ、跪きなさい」@
 これは、王女の口癖のようなものでした。@
 ララは飽き飽きとした顔で舌打ちをひとつ、/
cl r,9
そして床に伏します。\
In the above script, there are 4 lines of dialogue and the 4th line is split into 2 lines with the effect "cl r,9" occuring in the middle of that 4th line.

The syntax for the script has the following rules. The rules are split into two sections depending upon if the english command is added or not.

- To add regular half width, single byte, ascii characters, the "english" command should be added to the script with the following syntax.
Code:
*define
english
game
*start
- Lines of dialogue must begin with a full width character, a single quote ', a double quote " , or a comma , .
- Translated half width text must start with > or a full width character, like a full width space ' ', including after every control character. The documentation suggests using >. Using > will trigger different parsing syntax than using a full width space. Using a full width space can create bugs or conflics as the the english command syntax is not triggered, so always use > for pure ascii translated text. Example:
Code:
>"Lara?" @ "Wheres Lara?" @
 "Lara?" @ "Wheres Lara?" @
The second version that uses a full width space instead of > will crash because then the ? are both interpreted as script control characters.
The first version will still crash because there is no > after the @ control character. Without that, the second ? is interpreted as a script control character and thus crashes.
In other words, inserting control characters seems to make the game engine switch back to full width interpretation mode mid-line. This is also true if inserting full width spaces before full width characters. The engine switches back to full width interpetation mode. How and why did the game engine devs think this is good idea?
Code:
>"Lara?" @>"Wheres Lara?" @
The above will technically work at first but it renders the characters after the first > and the characters after the second > as two different lines, adding an extra line. Since the existing text already takes up all the available space, that will will make the game try to print text outside of the program window which will crash the game, although for a different reason.
Code:
>"Lara? Wheres Lara ?" @
The above will work without crashing but not correctly render the second ? since it is a full width character and those do not render well while in english mode.
Code:
>Benedic?tine he?rself? picked? up Lara who was abandoned as a child. ? @
Interestingly, for me the first 3 half width ? rendered correctly, the 4th ? as a full width one failed, and the 5th ? as full width rendered correctly, so the game engine is not guranteed to consistently follow its own rules since it seems like adding a full width character will make the engine switch back to full width rendering mode after that character. This switching back behavior is superceeded by using quotes, both single and double.
- If the line has mixed ascii and full width characters, then rendering it as full width and just dealing with the bugs is probably better because using > does not tend to render full width characters correctly most of the time.
Code:
 "Lara ? Wheres Lara ?" @
The above line sort-of works, but the second ? is not rendered correctly and @ is interpreted literally.
Code:
 "Lara ? Wheres Lara ?" @
Replacing the half width spaces before the second ? and the @ with full width spaces makes that line render correctly now, excluding a random dot right before the control character. Basically, this game engine's interpreter for scripts is really inconsistent, especially in full width mode but even sometimes in english mode.
- How a line displays is governed principally by the last character in a line, @, \, or /.
- The game will crash at any time a character must be rendered past what the dialogue window can display. This makes the NScripter engine very prone to crashing even when rendering otherwise valid script syntax. For that reason, it is necessary to make sure the resulting translation is never longer than what the window can display which is only known definitively at runtime. One way to automate/semi-gurantee this not being a problem is to change every ending control character @ to a \ to prevent crashes. However, this alters the author's intended flow for the dialogue in the game which makes this apporach not ideal. The alternative approach that results in the best quality is to manually check for crashes which is much more time consuming.
- Double quote ", and the full width version 「 and 」 are reserved characters with special meaning when used when rendering dialogue. Double quotes ", including the full width versions 「 」 , mean "keep going until the closing pair". There should be an escape character to disable this behavor, but I was unable to find it. The quotes will also render. The engine needs quotes closed prior to control characters like @ or it will likely crash. For automation, either detect this and close each quote prior to every control character, or remove mid-line control characters if there are quotes involved. For best quality, manually make sure quotes are closed appropriately prior to every control character.
- Full width characters inside of both single and double quotes do not seem to render properly, excluding other rendering issues not related to double quotes.
- While not required in order to the script to not crash, following these next cosmetic rules improves the chances of characters rendering accurately.
-- Inserting full width characters like ?, 「 and, 」 makes them almost always render incorrectly, but this is still possible sometimes.
-- If using the english command above, then ? should be converted to the half width variant, even inside of quotes.

These rules apply when not using the english command above.
- Question mark ? must be converted to the full width variant, even inside of quotes.
- The final control character, @, \, or /, should have a regular half-width space or a full width character proceding it.
- single quite ', double quote ", and question mark ? are reserved characters with special meaning when used when rendering dialogue. ' and " , including the full width versions, mean "keep going until the closing pair even ignoring certain control characters". This is problematic for many langauges because it means normal words like maid's and butler's will trigger the completion code which means it must be surrounded in quotation marks to render properly as in "maid's" and "butler's". The quotes will also render. There should be an escape character to disable this behavor, but I was unable to find it. Excluding other rendering issues not related to double quotes, full width characters inside of both single and double quotes do render properly. However, the engine assumes that quotes must be closed prior to control characters like @. For automation, either detect this and close each quote prior to every control character, remove mid-line control characters if there are quotes involved, or leave quotes as the original Japanese full width quotes, 「 and 」 and remove all single quotation marks. For best quality, manually make sure quotes are closed appropriately prior to every control character.
- The game engine tends to just remove half width spaces after a few wordswhichresults in concatinatingwordsmaking them hardtoread. However, it then goesback to rendering themagain properlyagain as if in a regular cycle. Using only full width spaces for dialogue instead of half width spaces makes the game render the line with the same meaning as @ in place of every space which requires waiting for the user to continue after every word. Inserting a full width space everytimewords getconcatenated does not break the flow of the dialogue so it all renders without user interaction just like the developer intended. The exact spots where full width spaces must be inserted as replacements for half width spaces are not known prior to runtime.
-- Hypothesis: The algorithim the game engine uses for this strange behavior around dialogue rendering seems to be at least partially dependent on the amount of horizontal space used by the characters which implies that it should be dependent on the font used. If the correct width for each part of the cycle can be measured, then it should be possible to automate replacing normal half width spaces with fully with spaces only where they are needed. Code that measures width accurately is somewhere in the VNT source tree. However, the game engine is also inconsistent about it where sometimes full width spaces are needed when surrounding small two letter words in a row. Other times, this is not necessary. That makes iplementing an algorithim as a workaround for this bug is not at all straight-forward.
-- For now, to automate this, leave words as seperated either entirely by half width spaces or full width spaces. Full width implies telling the user to always play with Auto(A) forward dialogue enabled which is not that big a deal, even if not ideal. The alternative of using entirely half width spaces means either publishing a patchwith halfthe wordsconcatenated or manually going through the script and adding full width spaces wherever words are concatenated. More time spent QC'ing the script would result in better quality output for this second approach.

For both rulesets:
- The engine word wraps by splicing words in the mid
dle which makes phrases hard to read. Making sure wo
rd wrapping works requires adding half width spaces
or full width spaces manually to fix the alignment o
f specific words.
- Mixing full width Japanese quotes 「 」 with half width single quotes ' seems to confuse the game engine and lead to unpredictable behavior. Either that or I could not figure out the rules to get such combinations stable.

The TL patch for zompri linked at the top does not use the english command which made working with the engine extra annoying.

Conclusion:
Due to the many limitations and quirks of this game engine. It is only recommended to use the original nscripter engine for smaller projects, <500 lines of dialogue and only for English. For larger projects and other languages besides Japanese and English, it is strongly recommended to consider porting the nscripter script to a more advanced engine like nscripter-insani, Onscripter, Onscripter-insani, Onscripter-en, Onscripter-yuri, or even a completely different type of engine like Ren'Py. Preferably, pick one that supports utf-8. Even if the scripts need to be partially or fully manually re-written for those game engines, that is already true anyway due to the many quirks of the nscripter game engine. The end results of porting the scripts to a better engine should be both better quality and increased automation.

 
Last edited:
  • Love
Reactions: Eir
No problem, glad to help give you some idea on how to do it

Though the reason I didn't code the game in renpy was because I was working on a few projects already and doing the whole thing from scrap would take a lot of time


I mostly gathered this idea in my mind after seeing some threads from fuwanovel working on nscripter engines and being unsuccessful at it

I am still not a pro coder yet, but I am great at giving ideas to people that need help
 
  • Like
Reactions: Eir and Entai2965
I was reviewing the tutorial and it was useful for several games but of few lines, in one of 3 mb of the nscript.dat only garbage characters came out and the game crashed:ROFLMAO:
 
I was reviewing the tutorial and it was useful for several games but of few lines, in one of 3 mb of the nscript.dat only garbage characters came out and the game crashed:ROFLMAO:

Send me a screenshot.

Edit: I received the dm.
 
Last edited:

Users who are viewing this thread

Latest profile posts

Xieppong wrote on Shine's profile.
Hello Shine please update the

✨Shine✨[ちなころ/えるふ茶園][JA/EN/ZH]極限改変・魔法少女ミスティックルーンver.0.4.0β to 極限改変・魔法少女ミスティックルーンver.0.6.0β [version 0.6.0], thank you, thanks for your post anyway

Jelly-filled Donut wrote on Otokonoko's profile.
Hi, would it possible for you to update this? Just asking.
暗い部屋の孤独な少女の物語 to Ver1.06