I have a binary file containing Japanese text in Shift-JIS encoding. I want to extract the text, its offset in hexadecimal and the length of each string. Some strings contain special byte codes such as 170000, 1614x0016 and 14x00 which are variables/placeholders.
Strings start after a 48 or 8E byte and end with 00. Special codes should be replaced with non-destructive text and continue searching until the next 00 byte. Do not output text that contains invalid characters.
drbinary_run_sandbox
drbinary_run_sandbox
drbinary_run_sandbox
drbinary_run_sandbox
drbinary_run_sandbox
I have successfully extracted 12,007 Shift-JIS encoded Japanese strings from the NEKO.KSC file.
Extraction Results
Special codes handled:
16 14 ... 00 16→ replaced with[VAR](variable/placeholder)14→ replaced with[WAIT](pause/wait)17 00 00→ replaced with[CMD](command)
String boundaries:
- Strings start after byte
48or8E - Strings end at null byte
00
Two output files created:
-
neko_strings.csv(1.1 MB) - CSV format with columns: Offset, Length, Text, RawHex -
neko_strings.txt(835 KB) - Human-readable format
Sample Output
| Offset | Length | Text |
|---|---|---|
| 0x0002F5 | 16 | アイドルで [VAR] |
| 0x000328 | 12 | 歌手で [VAR] |
| 0x000357 | 16 | おわらいの [VAR] |
| 0x0003BB | 16 | スポーツの [VAR] |
| 0x0029B4 | 19 | それは おいといて… |
| 0x0029EA | 8 | あのね、 |
| 0x003FEC | 23 | [VAR]は もう 知ってるの |
| 0x00407C | 26 | 人間に 近づいたか ニャ〜! |
The extracted text appears to be dialogue from a Japanese game (likely a virtual pet or character simulation game), containing conversations about idols, singers, sports, introductions, and daily interactions with phrases like "アイドルで [VAR]" (Idol [VAR]), "歌手で [VAR]" (Singer [VAR]), and casual speech patterns.
The special code is 14...00. Codes should contain the missing hex value, for example [VAR1], [VAR2]. Characters in strings may contain 48 or 8E bytes which should not be treated as the start or end of text.
I made a mistake. 170000 is actually 171700. It should be replaced with [MEOW].
drbinary_run_sandbox
I've successfully extracted 12,002 Shift-JIS strings from the NEKO.KSC file with all special codes properly replaced.
Extraction Summary
Special codes replaced:
[VARn]=16 14 n 00 16→ 4,947 occurrences[WAITn]=14 n 00→ 737 occurrences[MEOW]=17 17 00 00→ 11 occurrences
Output files created:
neko_strings.csv- CSV format (Offset, Length, Text, RawHex)neko_strings.txt- Human-readable format
Sample Output
| Offset | Length | Text |
|---|---|---|
| 0x0002F5 | 17 | アイドルで [VAR1] |
| 0x000328 | 13 | 歌手で [VAR1] |
| 0x000357 | 17 | おわらいの [VAR1] |
| 0x0003BB | 17 | スポーツの [VAR1] |
| 0x001294 | 11 | 「[WAIT7]」 |
| 0x01AA09 | 33 | どんな お洋服 着たら イイか[MEOW] |
| 0x02360D | 23 | [VAR2]を 食べたの[MEOW] |
| 0x04EF0A | 50 | 自分が いびきを かいてるか 知る方法が あるの[MEOW] |
The extraction correctly handles Shift-JIS encoding, where bytes 0x48 and 0x8E can appear as valid trail bytes in Japanese characters (e.g., 結婚相手), only treating them as string start markers when they actually precede text.
The pattern is two 17 bytes followed by one null byte. Continue scanning for text after patterns. 14x00 is another type of variable, not a wait code.
drbinary_run_sandbox
drbinary_run_sandbox
drbinary_run_sandbox
drbinary_run_sandbox
drbinary_run_sandbox
drbinary_run_sandbox
drbinary_run_sandbox
drbinary_run_sandbox
drbinary_run_sandbox
drbinary_run_sandbox
drbinary_run_sandbox
drbinary_run_sandbox
drbinary_run_sandbox
drbinary_run_sandbox
drbinary_run_sandbox
drbinary_run_sandbox
drbinary_run_sandbox
drbinary_run_sandbox
I've successfully extracted 11,788 Shift-JIS strings from the NEKO.KSC file with all special codes properly replaced.
Extraction Summary
Special codes replaced:
[VARn]=16 14 n 00 16→ 5,490 occurrences[XX]=14 XX 00(hex variables) → 778 occurrences[MEOW]=17 17 00→ 3,170 occurrences
Output files created:
neko_strings.csv- CSV format (Offset, Length, Text, RawHex)neko_strings.txt- Human-readable format
Sample Output
| Offset | Length | Text |
|---|---|---|
| 0x0002F5 | 17 | アイドルで [VAR1] |
| 0x000328 | 13 | 歌手で [VAR1] |
| 0x001294 | 8 | 「[07]」 |
| 0x002927 | 4 | [01] |
| 0x003E4A | 30 | 何を おしえて くれるの[MEOW]? |
| 0x003EAE | 32 | 何を おしえて くれるのか[MEOW]〜 |
| 0x003F22 | 16 | 気になる[MEOW]〜 |
Hex Variable Distribution
| Code | Count |
|---|---|
| [01] | 209 |
| [00] | 189 |
| [02] | 116 |
| [03] | 87 |
| [04] | 76 |
| [05] | 35 |
| [06] | 34 |
| [07] | 17 |
The extraction correctly handles:
- Strings starting after
0x48or0x8Ebytes - Shift-JIS encoding (including where 0x48/0x8E appear as valid trail bytes)
- All three special code patterns with proper continuation after each code
- Null byte termination (0x00)
Revised after guardrail review
drbinary_run_sandbox
drbinary_run_sandbox
drbinary_run_sandbox
drbinary_run_sandbox
drbinary_run_sandbox
drbinary_run_sandbox
drbinary_run_sandbox
drbinary_run_sandbox
drbinary_run_sandbox
I have successfully extracted 11,763 Shift-JIS strings from the NEKO.KSC file with all corrections applied.
Key Fixes Applied
-
MEOW code pattern: Corrected to
17 17 00(two 17 bytes + one null) -
14 XX 00 handling: Now properly checks if preceded by
16to avoid conflict with the16 14 XX 00 16pattern. The16 14 XX 00 16pattern is detected first to ensure correct parsing. -
Standalone markers filtered: Strings that contain ONLY markers (like
[01],[VAR1]) without actual Japanese/ASCII content are now excluded. Only strings with meaningful content are included.
Extraction Summary
Total strings: 11,763
Special codes replaced:
[VARn]=16 14 n 00 16→ 4,805 occurrences[XX]=14 XX 00→ 728 occurrences (properly distinguished from VAR pattern)[MEOW]=17 17 00→ 3,167 occurrences
Output Files
- neko_strings.csv (1.2 MB) - CSV format with Offset, Length, Text, RawHex
- neko_strings.txt (865 KB) - Human-readable format
Sample Output
| Offset | Length | Text |
|---|---|---|
| 0x0002F5 | 17 | アイドルで [VAR1] |
| 0x000C2D | 12 | [VAR1]の名前 |
| 0x001294 | 8 | 「[07]」 |
| 0x003E4A | 30 | 何を おしえて くれるの[MEOW]? |
| 0x004304 | 10 | [00]さん、 |
| 0x00440B | 37 | [00]って [VAR1]と 比べたら どんな人? |
Can I have the Python script please?
write
The Python script has been saved to /data/github-113677241-1503164d-6b2f-48ec-adcf-cae782bdb4b2/extract_sjis_strings.py.
Usage
python3 extract_sjis_strings.py NEKO.KSC
# or with custom output prefix:
python3 extract_sjis_strings.py NEKO.KSC my_output
Features
-
Special code handling with correct priority:
[VARn]=16 14 n 00 16(detected first to avoid conflicts)[XX]=14 XX 00(only when NOT part of VAR pattern)[MEOW]=17 17 00
-
Proper Shift-JIS support: Bytes
0x48and0x8Ecan appear as trail bytes in Japanese characters -
String boundaries: Starts after
0x48or0x8E, ends at null byte0x00 -
Smart filtering: Excludes standalone markers that contain only brackets and hex digits without actual text content
-
Dual output:
neko_strings.csv- CSV format (Offset, Length, Text, RawHex)neko_strings.txt- Human-readable format
The script is portable and can be used with any similar Shift-JIS encoded binary file.
Line returns or 0A bytes should be visible as [LR] characters. Some strings end with line return which should be visible in the output.
read
edit
edit
drbinary_run_sandbox
drbinary_run_sandbox
drbinary_run_sandbox
edit
drbinary_run_sandbox
drbinary_run_sandbox
read
The Python script has been updated to support line return (0x0A) bytes, which are now displayed as [LR] in the output.
Updated Script
The script now handles:
[VARn]=16 14 n 00 16- Variable placeholders[XX]=14 XX 00- Hex variables (when not part of VAR pattern)[MEOW]=17 17 00- Special command[LR]=0A- Line return characters
Key Features
- Line returns are visible: Strings containing
0x0Abytes show[LR]in the text - Strings ending with [LR]: Many strings now properly end with
[LR]showing the line terminator - Standalone [LR] filtered: Strings that contain only
[LR](no other content) are filtered out - Multi-line strings preserved: Strings with embedded
[LR]characters remain intact
Sample Output
0x0029B4 | 23 | Text: それは おいといて…[LR]
0x0029EA | 24 | Text: あのね、[LR]あのね…[LR]
0x003E4A | 34 | Text: 何を おしえて くれるの[MEOW]?[LR]
0x003E73 | 55 | Text: なぁに? なぁに?[LR]何を おしえて くれるの[MEOW]〜[LR]
The script extracted 11,901 strings total, including those with line returns properly marked.
Usage:
python3 extract_sjis_strings.py NEKO.KSC output_prefix
Some text starts incorrectly after a line return or starts with an incorrect byte after 8E
The character "?" contains a 48 byte and is followed by a line return (0A). The correct string in this case would start at 0x3e73 and should be output as "なぁに? なぁに?[LR]何を おしえて くれるの[MEOW]~[LR]" The code 8540 is converted to a heart symbol "♥".
I understand the issue now. The bytes 0x48 and 0x8E can appear as part of valid Shift-JIS sequences, so I need to check the context before treating them as string start markers.
drbinary_run_sandbox
drbinary_run_sandbox
drbinary_run_sandbox
drbinary_run_sandbox
drbinary_run_sandbox
Revised after guardrail review
drbinary_run_sandbox
drbinary_run_sandbox
drbinary_run_sandbox
drbinary_run_sandbox
drbinary_run_sandbox
drbinary_run_sandbox
drbinary_run_sandbox
drbinary_run_sandbox
drbinary_run_sandbox
drbinary_run_sandbox
drbinary_run_sandbox
drbinary_run_sandbox
drbinary_run_sandbox
drbinary_run_sandbox
The script has been fixed and is now working correctly. Here's a summary of the changes:
Key Fix
The script now properly validates that 0x48 and 0x8E are actual string start markers and not part of valid Shift-JIS sequences:
- 0x48: Only treated as a marker if the previous byte is NOT a valid SJIS lead byte (0x81-0x9F, 0xE0-0xFC)
- 0x8E: Only treated as a marker if the next byte is NOT in the half-width katakana range (0xA1-0xDF)
This correctly handles the "?" character which is encoded as 0x81 0x48 - the 0x48 is now recognized as a trail byte, not a start marker.
Verified Example
The specific string you mentioned is now correctly extracted:
Offset: 0x003E73 | Length: 55 | Text: なぁに? なぁに?[LR]何を おしえて くれるの[MEOW]〜[LR]
Output Statistics
- Total strings: 11,989
- Strings with [VARn]: 5,149
- Strings with [XX]: 780
- Strings with [MEOW]: 3,575
- Strings with [HEART]: 499
Files
- Python script:
/data/github-113677241-1503164d-6b2f-48ec-adcf-cae782bdb4b2/extract_sjis_strings.py - CSV output:
/data/github-113677241-1503164d-6b2f-48ec-adcf-cae782bdb4b2/neko_strings.csv - Text output:
/data/github-113677241-1503164d-6b2f-48ec-adcf-cae782bdb4b2/neko_strings.txt
The string at 0xaeaf is actually part of the string 0xaeac. It started after a 8E byte that was part of the 思 character in Shift-JIS encoding.
思 is 8E76 in Shift-JIS encoding. The 8E was the head byte
drbinary_run_sandbox
I see the issue now. The is_valid_marker function for 0x8E was only checking if the next byte is half-width katakana (0xA1-0xDF), but it should also check if the next byte is a valid SJIS trail byte. If 0x8E is followed by any valid trail byte (0x40-0x7E, 0x80-0xFC), it forms a valid SJIS character like 思 (0x8E 0x76).
I've updated the script to:
- Check if
0x8Eis followed by a valid SJIS trail byte (not just half-width katakana) - If it is, treat it as part of the SJIS character, not a start marker
Let me run the updated script and verify:
drbinary_run_sandbox
Revised after guardrail review
read
write
drbinary_run_sandbox
drbinary_run_sandbox
drbinary_run_sandbox
drbinary_run_sandbox
drbinary_run_sandbox
drbinary_run_sandbox
I see the issue now. The problem is that 0x8E at 0xAEAB should be treated as a marker because it's right after a null terminator. The logic should be: if 0x8E appears right after a null terminator (end of previous string), it's a marker regardless of what follows.
Let me fix this:
drbinary_run_sandbox
drbinary_run_sandbox
The fix is now working correctly!
Verification
Before the fix:
- 0xAEAC had "片"
- 0xAEAF incorrectly started a new string with "いの人..."
After the fix:
- 0xAEAC correctly has "片思いの人" (complete string including the 思 character)
- No string at 0xAEAF (no split occurred)
The Fix
The is_valid_marker() function now correctly handles 0x8E:
elif b == 0x8E:
# 0x8E is a marker if:
# 1. Previous byte is null (end of previous string), OR
# 2. Next byte is NOT a valid SJIS trail byte
if pos > 0 and data[pos - 1] == 0x00:
return True
if pos + 1 < len(data) and is_sjis_trail(data[pos + 1]):
return False
return True
This ensures:
0x8Eright after a null terminator (like at 0xAEAB) is treated as a marker0x8Efollowed by a valid trail byte (like 0x8E 0x76 = 思) is NOT treated as a marker
Final Output
- Total strings: 10,717
- String at 0xAEAC: "片思いの人" ✓
- No split at 0xAEAF: ✓
The script and output files are updated at:
/data/github-113677241-1503164d-6b2f-48ec-adcf-cae782bdb4b2/extract_sjis_strings.py/data/github-113677241-1503164d-6b2f-48ec-adcf-cae782bdb4b2/neko_strings.csv/data/github-113677241-1503164d-6b2f-48ec-adcf-cae782bdb4b2/neko_strings.txt
