Skip to content
View in the app

A better way to browse. Learn more.

ResHax

A full-screen app on your home screen with push notifications, badges and more.

To install this app on iOS and iPadOS
  1. Tap the Share icon in Safari
  2. Scroll the menu and tap Add to Home Screen.
  3. Tap Add in the top-right corner.
To install this app on Android
  1. Tap the 3-dot menu (⋮) in the top-right corner of the browser.
  2. Tap Add to Home screen or Install app.
  3. Confirm by tapping Install.
Help us keep the site running.

Higurashi no Naku Koro ni Sui - data.rom

Featured Replies

  • Author
  • Localization

AlphaTwentyThree, posted Tue Apr 14, 2015 8:57 am (4509)


Thanks a lot, luigi! Don't worry about the folder structure, I'm only after the music as you might have guessed. ;)
  • Author
  • Localization

aluigi, posted Fri Jul 17, 2015 9:33 pm (6443)


They don't seem archives.
  • Author
  • Localization

zander1995, posted Wed Oct 12, 2016 1:23 am (17980)


I hope it's okay to respond to an old thread, I didn't see anything about it in the rules, but it's not an archive. It's a single script file with all of the text included.

The problem is that it uses a custom character table somewhat different than base Shift JIS. Kanji and han/dakuten gojuuon are in base Shift JIS, but Hiragana and Katakana have completely different hex values.

With an edited Shift JIS table.
Image

With plain Shift JIS
Image
  • Author
  • Localization

aaa801, posted Wed Oct 12, 2016 7:57 pm (18008)


Handles dir structure, xyz made this script

Code:
from sys import argv
import struct
import os


def hexdump(src, length=16, sep='.'):
    FILTER = ''.join([(len(repr(chr(x))) == 3) and chr(x) or sep for x in range(256)])
    lines = []
    for c in xrange(0, len(src), length):
        chars = src[c:c length]
        hex = ' '.join(["x" % ord(x) for x in chars])
        if len(hex) > 24:
            hex = "%s %s" % (hex[:24], hex[24:])
        printable = ''.join(["%s" % ((ord(x) <= 127 and FILTER[ord(x)]) or sep) for x in chars])
        lines.append("x:  %-*s  |%s|\n" % (c, length*3, hex, printable))
    print ''.join(lines)

def u8(b, off=0):
    return ord(b[off])

def u16(b, off=0):
    return struct.unpack("
def u32(b, off=0):
    return struct.unpack("
def c_str(b, off=0):
    part = b[off:]
    term = part.find("\x00")
    if term == -1:
        print "full dump:"
        hexdump(b)
        print "part dump (offset 0x{:x})".format(off)
        hexdump(part)
        raise Exception("failed to find C-string here")
    return part[:term]


folder_map = dict()


class File():

    def __init__(self, data, parent_data):
        name_off = u32(data[0:3] "\x00")
        self.name = c_str(parent_data, name_off)
        self.flags = u8(data, 3)
        self.offset = u32(data, 4)
        self.size = u32(data, 8)


class Info():

    def __init__(self, data):
        self.num_files = u32(data, 0)

        self.files = []
        for x in range(self.num_files):
            start = 4 x * 0xC
            file_info = data[start:start 0xC]
            self.files.append(File(file_info, data))

        for file in self.files:
            if file.name == ".":
                folder_map[file.offset] = self
            elif file.name == "..":
                self.parent = folder_map[file.offset]

fin = None


def extract_folder(folder, path):
    os.mkdir(path)
    for file in folder.files:
        if file.name in [".", ".."]:
            continue
        print "{}/{}{}".format(path, file.name, "/" if file.flags & 0x80 else "")
        if file.flags & 0x80:
            extract_folder(folder_map[file.offset], os.path.join(path, file.name))
        else:
            fin.seek(file.offset * 0x800)
            fout = open(os.path.join(path, file.name), "wb")
            fout.write(fin.read(file.size))
            fout.close()


def main():
    global fin
    fin = open(argv[1], "rb")
    assert fin.read(4) == "ROM "
    assert u16(fin.read(2)) == 1
    assert u16(fin.read(2)) == 2
    header_size = u32(fin.read(4))
    unk1 = fin.read(4)

    folders = []

    while fin.tell() < header_size:
        start = fin.tell()
        fin.seek(start 0xC)
        info_size = u32(fin.read(4))
        fin.seek(start)
        data = fin.read(info_size)
        # hexdump(data)
        info = Info(data)
        folders.append(info)
       
        end = start info_size
        # align to 0x10
        end = (end 0xF) & ~0xF
        fin.seek(end)

    extract_folder(folders[0], path="extract")


if __name__ == "__main__":
    main()
  • Author
  • Localization

zander1995, posted Thu Oct 13, 2016 6:50 am (18024)


aaa801 wrote:
Handles dir structure, xyz made this script


How do we use that script? QuickBMS throws up errors when attempting to run it.
  • Author
  • Localization

aaa801, posted Thu Oct 13, 2016 4:57 pm (18031)


zander1995 wrote:
aaa801 wrote:
Handles dir structure, xyz made this script


How do we use that script? QuickBMS throws up errors when attempting to run it.

its a python script, python blabla.py data.rom out
i don't really get on with quickbms enough to convert it
  • Author
  • Localization

zander1995, posted Thu Oct 13, 2016 9:04 pm (18036)


aaa801 wrote:
zander1995 wrote:
aaa801 wrote:
Handles dir structure, xyz made this script


How do we use that script? QuickBMS throws up errors when attempting to run it.

its a python script, python blabla.py data.rom out
i don't really get on with quickbms enough to convert it


Oh, cool. Thanks.
  • Author
  • Localization

aaa801, posted Mon Oct 17, 2016 3:44 pm (18120)


forgot to mention,
the game uses binary search so the entries need to be in alphabetical order.
  • Author
  • Localization

ever17, posted Wed Oct 25, 2017 7:06 am (27680)


aaa801 wrote:
Python script[/code]


It give me error:
Quote:
1.py data.rom
File "1.py", line 16
print ''.join(lines)
^
SyntaxError: invalid syntax


I try it on vita data.rom file
Python36-32
Help?
  • Author
  • Localization

Acewell, posted Wed Oct 25, 2017 9:59 am (27681)


looks like the script was written for Python 2.x by the looks of the print statements, but you should be able to
fix that error by adding parenthesis around all the print statements and just use Python 3.x to run it.

for example change this
Code:
print ''.join(lines)

to this
Code:
print(''.join(lines))
  • Author
  • Localization

ever17, posted Thu Oct 26, 2017 6:29 am (27703)


Acewell wrote:
looks like the script was written for Python 2.x by the looks of the print statements, but you should be able to
fix that error by adding parenthesis around all the print statements and just use Python 3.x to run it.

for example change this
Code:
print ''.join(lines)

to this
Code:
print(''.join(lines))

Thanks, would test it later!
  • Author
  • Localization

masagrator, posted Sun Feb 17, 2019 10:42 am (43584)


Sorry for bumping, but Switch version Higurashi has new data.rom that has at the beginning ROM2

Here are first and last chunk of file (Whole archive is 7.04 GiB big)
https://drive.google.com/file/d/1t9ebtA ... sp=sharing

If someone could update script (and if it's Python - please write in Python 3)
  • Author
  • Localization

wwwklopar, posted Sun Feb 17, 2019 6:44 pm (43594)


Searching script for Switch version of Higurashi too
  • Author
  • Localization

voddler, posted Sat Oct 26, 2019 5:27 pm (51755)


Also looking for a script for the switch version file above, please help us out. We'd appreciate it! :D
  • Author
  • Localization

wwwklopar, posted Sat Oct 26, 2019 5:41 pm (51756)


I can add link to full archive if it will help.
Link
  • Author
  • Localization

aaa801, posted Mon Nov 30, 2020 11:53 pm (60809)


Heres more python 2 for ya, handles the newer files (switch) (anyone feel free to convert it to python 3, I tried.. its a panful time)

Might attempt to convert it over to bms eventually..

Code:
from sys import argv
import struct
import os

def hexdump(src, length=16, sep='.'):
    FILTER = ''.join([(len(repr(chr(x))) == 3) and chr(x) or sep for x in range(256)])
    lines = []
    for c in xrange(0, len(src), length):
        chars = src[c:c length]
        hex = ' '.join(["x" % ord(x) for x in chars])
        if len(hex) > 24:
            hex = "%s %s" % (hex[:24], hex[24:])
        printable = ''.join(["%s" % ((ord(x) <= 127 and FILTER[ord(x)]) or sep) for x in chars])
        lines.append("x:  %-*s  |%s|\n" % (c, length*3, hex, printable))
    print ''.join(lines)

def u8(b, off=0):
    return ord(b[off])

def u16(b, off=0):
    return struct.unpack("
def u32(b, off=0):
    return struct.unpack("
def c_str(b, off=0):
    part = b[off:]
    term = part.find("\x00")
    if term == -1:
        print "full dump:"
        hexdump(b)
        print "part dump (offset 0x{:x})".format(off)
        hexdump(part)
        raise Exception("failed to find C-string here")
    return part[:term]


folder_map = dict()


class File():

    def __init__(self, data, parent_data):
        name_off = u32(data[0:3] "\x00")
        self.name = c_str(parent_data, name_off)
        self.flags = u8(data, 3)
        self.offset = u32(data, 4)
        self.size = u32(data, 8)
        print "name " self.name " offset " "{}".format(self.offset) " size " "{}".format(self.size)


class Info():

    def __init__(self, data):
        self.num_files = u32(data, 0)

        self.files = []
        for x in range(self.num_files):
            start = 4 x * 0xC
            file_info = data[start:start 0xC]
            self.files.append(File(file_info, data))

        for file in self.files:
            if file.name == ".":
                folder_map[file.offset] = self
            elif file.name == "..":
                self.parent = folder_map[file.offset]

fin = None


def extract_folder(folder, path):
    try:
      os.mkdir(path)
    except OSError as error:
      print(error)
    for file in folder.files:
        if file.name in [".", ".."]:
            continue
        print "{}/{}{}".format(path, file.name, "/" if file.flags & 0x80 else "")
        if file.flags & 0x80:
            extract_folder(folder_map[file.offset], os.path.join(path, file.name))
        else:
            if file.offset * offsetMultiplier file.size >= archiveSize:
              print "Skipping file as archive is to small!"
              continue
            print "saving"  file.name " offset " "{}".format(file.offset * offsetMultiplier) " size " "{}".format(file.size)
            fin.seek(file.offset * offsetMultiplier)
            fout = open(os.path.join(path, file.name), "wb")
            fout.write(fin.read(file.size))
            fout.close()


def main():
    global fin
    fin = open(argv[1], "rb")
    global archiveSize
    archiveSize = os.path.getsize(argv[1])
      
    magic = fin.read(4)
    assert magic == "ROM " or magic == "ROM2"
   
    global fileStart
    global offsetMultiplier

    if magic == "ROM ":
      fileStart = 0x10
      offsetMultiplier = 0x800
    elif magic == "ROM2":
      fileStart = 0x20
      offsetMultiplier = 0x200
    else:
     print "oh no"
     exit()
    
    fin.read(4)
    header_size = u32(fin.read(4))
    unk1 = fin.read(4)

    folders = []

    fin.seek(fileStart)
    while fin.tell() < header_size:
        start = fin.tell()
        fin.seek(start 0xC)
        info_size = u32(fin.read(4))
        fin.seek(start)
        data = fin.read(info_size)
        # hexdump(data)
        info = Info(data)
        folders.append(info)
       
        end = start info_size
        # align to 0x10
        end = (end 0xF) & ~0xF
        fin.seek(end)

    extract_folder(folders[0], path="extract")


if __name__ == "__main__":
    main()
  • Author
  • Localization

aaa801, posted Tue Dec 01, 2020 9:24 pm (60842)


Here is a truly awful quickbms script for these..

Code:
# Higurashi data.rom
# Script for QuickBMS http://quickbms.aluigi.org

idstring ROM
get VERSION byte

if VERSION == 0x20
   # Original version
   set INFO_START = 0x10
   set OFFSET_MULTIPLIER = 0x800
   print "Original format"
else if VERSION == 0x32
   # Newer version (switch)
   set INFO_START = 0x20
   set OFFSET_MULTIPLIER = 0x200
   print "New format"
else
   print "Unsupported version"
endif

get UNK long
get HEADER_SIZE long

goto SEEK_END
savepos INPUT_END

# Go to the start of file entry table
goto INFO_START

set TOTAL_ENTRIES 0
set TOTAL_FOLDERS 0

# Read info
savepos LAST_POS
Do
   print "Reading info at %LAST_POS% / %HEADER_SIZE%"
   savepos START
   savepos BASE_LOC

   get NUM_FILES long

   xmath TMP "START 0x0C"
   goto TMP
   
   get INFO_SIZE long
   goto START
   
   # Read info
   callfunction readInfo 1
   
   xmath END "START INFO_SIZE"
   print "start %START% %END%"

   goto END
   padding 0x10
      
   savepos LAST_POS
   # print "start was %START% info_size was %INFO_SIZE%"
   print "-"
while LAST_POS < HEADER_SIZE

callfunction dumpFiles

# Ugh.. bms is a pain for stuff like this..
# need to store info for each file..
# arrays,
# 0 = name
# 1 = flags
# 2 = offset
# 3 = size
# --
# 4 = is_folder
# 5 = FOLDER_OFFSET
# 6 = PARENT_FOLDER_OFFSET
# -- these are for folder entries
# 7 = folder name
# 8 = folder offset
# 9 = parent folder offset

startfunction readInfo
   #get NUM_FILES long
   print "Files %NUM_FILES%"
   print "Baseloc %BASE_LOC%"
      
   for i = 0 < NUM_FILES
      xmath FILE_ENTRY_START "4 i * 0xC"
      xmath FILE_ENTRY_START "FILE_ENTRY_START BASE_LOC"
      #print "File %i% info at %FILE_ENTRY_START%"
      #print "TOTAL_ENTRIES %TOTAL_ENTRIES%"   
      savepos TMP
      
      goto FILE_ENTRY_START
      get NAME_OFF THREEBYTE
      get FLAGS byte
      get OFFSET long
      get SIZE long
      
      # print "raw_name_off %NAME_OFF%"
      xmath NAME_LOC "BASE_LOC NAME_OFF"
        # print "File %i% name_off %NAME_LOC%"
      goto NAME_LOC
      get NAME string
      
      PutArray 0 TOTAL_ENTRIES NAME
      PutArray 1 TOTAL_ENTRIES FLAGS
      PutArray 2 TOTAL_ENTRIES OFFSET
      PutArray 3 TOTAL_ENTRIES SIZE
      
      if FLAGS & 0x80
            math IS_FOLDER = 1
         if NAME != "." && NAME != ".."
            PutArray 7 TOTAL_FOLDERS NAME
            PutArray 8 TOTAL_FOLDERS OFFSET
            PutArray 9 TOTAL_FOLDERS FOLDER_OFFSET
            xmath TOTAL_FOLDERS "TOTAL_FOLDERS 1"
         endif
        else
            math IS_FOLDER = 0
        endif
      PutArray 4 TOTAL_ENTRIES IS_FOLDER
      
      if NAME == "."
         set FOLDER_OFFSET OFFSET
      elif NAME == ".."
         set PARENT_FOLDER_OFFSET OFFSET
      endif
      
      goto TMP
      xmath TOTAL_ENTRIES "TOTAL_ENTRIES 1"
   next i
   
   # set folder offsets
   for i = 0 < NUM_FILES
      xmath INDEX "TOTAL_ENTRIES - NUM_FILES i"
      PutArray 5 INDEX FOLDER_OFFSET
      PutArray 6 INDEX PARENT_FOLDER_OFFSET
   next i
   
endfunction

startfunction dumpFiles
   
   callfunction dumpFolders
   
   print "dumpFiles"

   print "Total entries: %TOTAL_ENTRIES%"

   # set full paths
   for i = 0 < TOTAL_ENTRIES   
      getarray FILE_NAME 0 i
      getarray FILE_FLAGS 1 i
      getarray FILE_OFFSET 2 i
      getarray FILE_SIZE 3 i
      getarray FILE_IS_FOLDER 4 i
      getarray FILE_FOLDER_OFFSET 5 i
      getarray FILE_PARENT_FOLDER_OFFSET 6 i
      
      # testing skip
      if FILE_NAME != "hse_31.nxa"
      # se/hse/hse_31.nxa
         #continue
      endif
   
      math FILE_OFFSET u* OFFSET_MULTIPLIER

      print "Name %FILE_NAME% Folder %FILE_IS_FOLDER% Flags %FILE_FLAGS% Offset %FILE_OFFSET% Size %FILE_SIZE% Folder_offset %FILE_FOLDER_OFFSET% parent_folder_offset %FILE_PARENT_FOLDER_OFFSET%"

      if FILE_IS_FOLDER == 1
         continue
      endif
      
      
      set FOLDER_PATH ""
      set CUR_SEARCH_FOLDER_OFFSET FILE_FOLDER_OFFSET
      callfunction getPath 1
      #print "FOLDER_PATH %FOLDER_PATH%"
      
      set FILE_PATH ""
      String FILE_PATH FOLDER_PATH
      String FILE_PATH FILE_NAME
      #print "FILE_PATH %FILE_PATH%"

      set END_OFFSET FILE_OFFSET
      math END_OFFSET u FILE_SIZE
      print "end %END_OFFSET% INPUT_END %INPUT_END%"
      
      # Explodes on 32bit runover.. -_-
      if END_OFFSET u> INPUT_END
         print "Skipping file as archive is too small!"
      else
         log FILE_PATH FILE_OFFSET FILE_SIZE
      endif

      
   next i
   
   
endfunction

startfunction dumpFolders
   print "dumpFolders %TOTAL_FOLDERS%"

   for aaa = 0 < TOTAL_FOLDERS
       getarray FOLDER_NAME 7 aaa
      getarray FOLDER_OFFSET 8 aaa
      getarray PARENT_FOLDER_OFFSET 9 aaa
      #print "fname %FOLDER_NAME% foffset %FOLDER_OFFSET% pfoffset %PARENT_FOLDER_OFFSET%"
   next aaa
endfunction

startfunction getPath
   #print "ugh paths"
   if CUR_SEARCH_FOLDER_OFFSET == 0
      #print "heh....."
   else
      for aaa = 0 < TOTAL_FOLDERS
         getarray FOLDER_NAME 7 aaa
         getarray FOLDER_OFFSET 8 aaa
         getarray PARENT_FOLDER_OFFSET 9 aaa
         
         #print "looking for.. foffset %CUR_SEARCH_FOLDER_OFFSET%"
         #print "fname %FOLDER_NAME% foffset %FOLDER_OFFSET% parent_foffset %PARENT_FOLDER_OFFSET%"
         
         if CUR_SEARCH_FOLDER_OFFSET == FOLDER_OFFSET
            set TMP_PATH ""
            String TMP_PATH FOLDER_NAME
            String TMP_PATH "/"
            String TMP_PATH FOLDER_PATH

            set FOLDER_PATH TMP_PATH
            
            #String FOLDER_PATH FOLDER_NAME
            #String FOLDER_PATH "/"
            
            if PARENT_FOLDER_OFFSET != 0
               #print "brrrrr"
               set CUR_SEARCH_FOLDER_OFFSET PARENT_FOLDER_OFFSET
               callfunction getPath 1
            endif
            break
         endif
      next aaa
   endif

endfunction

Guest
This topic is now closed to further replies.

Account

Navigation

Search

Search

Configure browser push notifications

Chrome (Android)
  1. Tap the lock icon next to the address bar.
  2. Tap Permissions → Notifications.
  3. Adjust your preference.
Chrome (Desktop)
  1. Click the padlock icon in the address bar.
  2. Select Site settings.
  3. Find Notifications and adjust your preference.