QuickBMS errors [programming, scripting, quickbms.exe tool... NOT games]

Doubts, help and support about QuickBMS and other game research tools
Shokoniraya
Posts: 416
Joined: Sat Sep 15, 2018 5:22 am

Re: QuickBMS errors [programming, scripting, quickbms.exe tool... NOT games]

Post by Shokoniraya »

importing based on id's works
and there is a problem, when a text file is missing, slog gives error

- error in src\file.c line 2113: dumpa_slog()
Error: No such file or directory


can you ignore it for missing files of slog?
aluigi
Site Admin
Posts: 12984
Joined: Wed Jul 30, 2014 9:32 pm

Re: QuickBMS errors [programming, scripting, quickbms.exe tool... NOT games]

Post by aluigi »

Great, thanks for testing.

Ok I will remove the slog error later.
Since the slog text is just like the other extracted files, there should be no error displayed in reimport mode if missing.
Shokoniraya
Posts: 416
Joined: Sat Sep 15, 2018 5:22 am

Re: QuickBMS errors [programming, scripting, quickbms.exe tool... NOT games]

Post by Shokoniraya »

sir aluigi, text importing with id's has three problems
1) empty lines can't be passed (or even lines with unused texts)
2) i think some id's that include = character can't be import as well. maybe = should replace with something like \x3D in id's

3) can't import unsorted id's (if they unsorted by hand)
for example

Code: Select all

1=text_1
3=text_3
2=text_2
aluigi
Site Admin
Posts: 12984
Joined: Wed Jul 30, 2014 9:32 pm

Re: QuickBMS errors [programming, scripting, quickbms.exe tool... NOT games]

Post by aluigi »

Exactly, the strings must keep the original order.
Empty lines are just considered strings.
And no, the ID can't contain the = character (why an id should have it?).

So let's say the original slog was:

Code: Select all

1=text_1
2=text_2
3=text_3

The new slog can be:

Code: Select all

2=text_2
3=text_3

The code is exactly the same sequential code for both with and without IDs, the only difference is that quickbms will not go forward until it finds the expected id.
So in the example you provided (1,3,2) it will import the strings 1 and 3 but will ignore 2.
If you used 1,3,2,4 it would have ignored both 2 and 4.
The correct one was 1,3,4.

The reason why I can't change this behaviour is that you can have multiple slog with different settings for the ID.
Everything works if you just delete original line without altering the original structure of the slog file.
spiritovod
Posts: 719
Joined: Sat Sep 28, 2019 7:00 pm

Re: QuickBMS errors [programming, scripting, quickbms.exe tool... NOT games]

Post by spiritovod »

Not an actual error, but I wonder if syntax errors handling can be improved. Currently, in most cases you can only see c_structs message somewhere in the header and the script continue to work, but with unexpected results. I think it's worth to make it more noticeable.
For example, script like this will actually read SIZE, but starting from second byte, which is not obvious:

Code: Select all

string NAME "test"
get SIZE long
print "Size: %SIZE|hex%"

For data like 0x0102030405 it will be "Size: 0x0000000005040302".
aluigi
Site Admin
Posts: 12984
Joined: Wed Jul 30, 2014 9:32 pm

Re: QuickBMS errors [programming, scripting, quickbms.exe tool... NOT games]

Post by aluigi »

I agree, the c_structs messages are almost invisible.
Maybe I can use a red color for those c_structs message so that they will be immidiately visible.

The idea of using console colors is not new and I think it would be useful for me too, as long as I will not make quickbms an xmas tree :D

Do you think the color may be helpful with that c_structs issue?
spiritovod
Posts: 719
Joined: Sat Sep 28, 2019 7:00 pm

Re: QuickBMS errors [programming, scripting, quickbms.exe tool... NOT games]

Post by spiritovod »

The problem is not the color, but the fact, that you can't tell it's some kind of error. If you don't know what it is exactly, you can think that it's a part of header message (this error is laughable, but a good example), along with used script and input/output folders. In all programming languages you usually expect that code stop working at syntax error, but quickbms just ignores them when possible, which can confuse you at some point, especially with big complicated scripts, if an accident typo will slip in.
aluigi
Site Admin
Posts: 12984
Joined: Wed Jul 30, 2014 9:32 pm

Re: QuickBMS errors [programming, scripting, quickbms.exe tool... NOT games]

Post by aluigi »

I understand.
A part from the colors I don't think there is a possible solution.

The support for the structures is quite useful sometimes even if it's experimental, but there is no way to understand if it's an error or it's meant to be that way.

I'm open to ideas.
spiritovod
Posts: 719
Joined: Sat Sep 28, 2019 7:00 pm

Re: QuickBMS errors [programming, scripting, quickbms.exe tool... NOT games]

Post by spiritovod »

I don't quite understand - is there a situation when you would see "structs" message, but the script will work as expected? I thought that any "structs" appearance would imply some kind of error in the script or while parsing the data. If that the case, it's probably possible to add "error" / "warning" prefix to this message, along with some highlighters, like this:
---------------------
error: c_structs ...
---------------------

This way it surely will be noticeable. Ideally, position in the script when it appeared would be nice too. For example, "error at line 10: c_structs ...". It's just a suggestion though.
Shokoniraya
Posts: 416
Joined: Sat Sep 15, 2018 5:22 am

Re: QuickBMS errors [programming, scripting, quickbms.exe tool... NOT games]

Post by Shokoniraya »

sir aluigi, i understand that importing function forwards with .txt while it's about to be reading
but maybe you can use a different solution. i mean read a .txt from beginning (form first line each time when slog importing function starts)
i know maybe it's a dummy idea and make it slower, but it works
or you could upload txt files in memory and make a binary table (TOC) with id strings and offsets in memory from those txt files to read it faster
aluigi
Site Admin
Posts: 12984
Joined: Wed Jul 30, 2014 9:32 pm

Re: QuickBMS errors [programming, scripting, quickbms.exe tool... NOT games]

Post by aluigi »

@spiritovod
This is an example of where I found the c_structs feature very useful:
http://aluigi.org/bms/parse_exe.bms

@Shokoniraya
There is not much to do.
spiritovod
Posts: 719
Joined: Sat Sep 28, 2019 7:00 pm

Re: QuickBMS errors [programming, scripting, quickbms.exe tool... NOT games]

Post by spiritovod »

Actually it's the first time I see its proper usage. Then maybe it's possible to add command-line option that will let quickbms know that structs are expected in the script - otherwise they will be considered as errors/warnings. Default state will be without structs (I believe they're rarely used).
aluigi
Site Admin
Posts: 12984
Joined: Wed Jul 30, 2014 9:32 pm

Re: QuickBMS errors [programming, scripting, quickbms.exe tool... NOT games]

Post by aluigi »

I don't know how many people use it in their scripts.
An additional command-line option would make their scripts no longer working.

The alternative to the colors would be to a warning asking the user to confirm if going forward, something like already happens when using calldll.
It's a bit annoying for users.
spiritovod
Posts: 719
Joined: Sat Sep 28, 2019 7:00 pm

Re: QuickBMS errors [programming, scripting, quickbms.exe tool... NOT games]

Post by spiritovod »

Why though? You can simply add additional message, so by default (with structs disabled) it will be like this:
"error: c_structs ...
If you're using structs in you script, launch quickbms with [-option]"
or something and terminate script execution after the first error like this. This way they will be aware of the change even if they didn't read updated docs.
aluigi
Site Admin
Posts: 12984
Joined: Wed Jul 30, 2014 9:32 pm

Re: QuickBMS errors [programming, scripting, quickbms.exe tool... NOT games]

Post by aluigi »

Ok I released the new beta which asks if going forward if there is a syntax error.
For avoiding the message I used the -c option in quickbmsver, it's not documented yet since it's just a test, on command-line that option is used to display the list of commands therefore it's unused in quickbmsver.

I also added a new argument for the Get command.
Even if I don't like to make the commands too complicated, I think this new argument may be interesting since it's the offset where we want to use the Get command.

Example with the normal savepos+goto+get+goto:

Code: Select all

get NAME_OFF long
savepos TMP
goto NAME_OFF
get NAME string
goto TMP
Now:

Code: Select all

get NAME_OFF long
get NAME string 0 NAME_OFF
spiritovod
Posts: 719
Joined: Sat Sep 28, 2019 7:00 pm

Re: QuickBMS errors [programming, scripting, quickbms.exe tool... NOT games]

Post by spiritovod »

Thank you, that new errors handling is much clearer, I hope it will be helpful for newcomers.
spiritovod
Posts: 719
Joined: Sat Sep 28, 2019 7:00 pm

Re: QuickBMS errors [programming, scripting, quickbms.exe tool... NOT games]

Post by spiritovod »

Not sure if you read that topic already, but there is possible bug with quickbms_hash or escapes in general: viewtopic.php?f=9&t=14485
tbmq008
Posts: 62
Joined: Thu Nov 26, 2020 2:13 pm

Re: QuickBMS errors [programming, scripting, quickbms.exe tool... NOT games]

Post by tbmq008 »

i'm having some problems with arrays.
so i'm writing up a script that covers an file system format taking full advantage of this whole "directory" info thingy, so i thought. why not handle directories in an interesting way?
so i started by putting out putarrays and getarrays around the whole script while attempting to correctly parse the directory structure of such an format and while i did manage to get pretty far, the results were less than convincing.

Code: Select all

-------------------
*EXCEPTION HANDLER*
-------------------
An error or crash occurred:

*EH* ExceptionCode      c00000fd stack overflow
*EH* ExceptionFlags     00000000
*EH* ExceptionAddress   75727FC7
                        756C0000 + 00067fc7 msvcrt.dll
*EH* NumberParameters   00000002
*EH*                    00000000
*EH*                    00402000

Last script line before the error or that produced the error:
  329 getarray next_padded_sub_dir_number 8 current_directory_number

an error related with arrays was all it took for quickbms to "pan out".

here's the script i'm trying to write for this format.

Code: Select all

get is_vol extension
if is_vol != "vol"
   cleanexit
endif
get vol_size asize

math name_quirks = 0
get vol_sign long
if vol_sign == 0xacb990ad
   math name_quirks = 1
   print "\n hold on, this script will analyze the archive itself based on a 4-byte sign alongside its 4-byte number just so it can handle the whole extraction/reimport process. \n don't worry this script won't scan the entire archive for just two 4-byte values, but you do have to wait until the script can extract the files for you. "
   savepos temp_01
   goto 0
   math vol_ver = 0
   math c_01 = 0
   do
      savepos temp_02
      get vol_check_01 long
      get vol_check_02 long
      if vol_check_01 == 0xacb990ad
         math c_01 + 1
         putarray c_01 0 temp_02
         if vol_check_02 == 0x00020002
            math vol_ver = 1
         endif
         if vol_check_02 == 0x00030001
            math vol_ver = 2
         endif
      endif
      math temp_02 += 0x800
      goto temp_02
   while temp_02 != 0x2000000
   goto temp_01
   print " \n found .vol file with common(0xad90b9ac) sign. \n parsing vol info now. \n"
elif vol_sign == 0x53466f52 # "RoFS"
   math vol_ver = 1
   print " \n found .vol file with RoFS sign. \n parsing vol info now. an"
   putarray 1 0 0
else
   string unknown_vol_sign p "0x%08x" vol_sign
   print " \n unknown VOL sign - %unknown_vol_sign% \n"
   cleanexit
endif

if vol_ver = 1
   getarray vol_offset 1 0
   goto vol_offset
   get vol_sign_01 long
   get min_ver short
   get max_ver short
   get header_size long
   get info_size long
   get name_size long
   for i = 0 < 256
      putarray 0 i 0
      putarray 1 i 0
      putarray 2 i 0
      putarray 3 i ""
      putarray 4 i 0
      putarray 5 i 0
      putarray 6 i 15
      putarray 7 i 0
      putarray 8 i 0
      putarray 9 i 0
      putarray 10 i 0
      putarray 11 i 0
      putarray 12 i 0
      putarray 13 i 0
      putarray 14 i 0
   next i
   math entry_info_offset = 0x14
   math current_directory_number = 0
   math current_directory_offset = 0
   math current_padded_sub_dir_number = 0
   math current_sub_dir_number = 0
   math next_padded_sub_dir_number = 0
   math next_sub_dir_number = 0
   math max_sub_dir_limit = 0
   math dir_is_done = 0
   callfunction parse_rofs_ver_one 1
   # (todo) this function somehow causes quickbms to act up,
   # resulting in error messages like these:
   /*
   -------------------
   *EXCEPTION HANDLER*
   -------------------
   An error or crash occurred:

   *EH* ExceptionCode      c00000fd stack overflow
   *EH* ExceptionFlags     00000000
   *EH* ExceptionAddress   00F65F43
                           00810000 + 00755f43 quickbms.exe
   *EH* NumberParameters   00000002
   *EH*                    00000001
   *EH*                    036F20FC

   Last script line before the error or that produced the error:
     391 clog file_name file_offset compressed_file_size original_file_size
   */
   # or simply having nothing to show as an error message at all.
   # this affects both quickbms.exe and quickbms_4gb_files.exe
   # as said error can happen at any time during vol extraction.
endif
if vol_ver == 2
   getarray vol_offset 2 0
   goto vol_offset
   get vol_sign_02 long
   get min_ver short
   get max_ver short
   get full_compressed_info_size long
   get raw_data_offset long
   get average_block_size_per_sector short
   get file_info_chunks short
   xmath base_offset "vol_offset + (raw_data_offset * average_block_size_per_sector)"
   xmath chunk_index_offset "vol_offset + 0x40"
   goto chunk_index_offset
   math z1 = 1
   math z2 = 0
   for i = 0 <= file_info_chunks
      math seed = 0x14AC327A
      get enc_byte long
      math seed * z1
      xmath dec_byte "(enc_byte ^ seed) & 0xffffffff"
      putarray 1 z2 dec_byte
      math z1 + 1
      math z2 + 1
   next i
   for i = 0 < file_info_chunks
      getarray chunk_offset 1 i
      math i + 1
      getarray size_aid 1 i
      math i - 1
      xmath compressed_chunk_size "size_aid - chunk_offset"
      math original_chunk_size = 0x800
      putarray 2 i compressed_chunk_size
      putarray 3 i original_chunk_size
   next i
   print " okay, you may need to wait a bit. \n the script needs to sort everything out with this vol file first. "
   comtype deflate_noerror
   math total_entries = 0
   for i = 0 < file_info_chunks
      getarray chunk_offset 1 i
      getarray compressed_chunk_size 2 i
      getarray original_chunk_size 3 i
      xmath physical_chunk_offset "vol_offset + chunk_offset"
      clog MEMORY_FILE physical_chunk_offset compressed_chunk_size original_chunk_size
      goto 0 MEMORY_FILE
      putvarchr MEMORY_FILE2 0x800 0
      log MEMORY_FILE2 0 0
      for j = 0 < 2048
         get enc_byte byte MEMORY_FILE
         xmath dec_byte "enc_byte ^ 0x55"
         put dec_byte byte MEMORY_FILE2
      next j
      math chunk_read_element = -2
      callfunction parse_rofs_ver_three 1
   next i
   # (todo) this needs to be optimized for performance
   # work smarter, not harder
   math folders = 0
   math files = 0
   for i = 0 < total_entries
      getarray entry_type 18 i
      if entry_type == 0
         getarray entry_first_sub_entry 19 i
      else
         getarray file_offset 20 i
         getarray time_stamp 21 i
         getarray physical_file_offset 22 i
         if entry_type == 1
            getarray file_size 23 i
         elif entry_type == 2
            getarray compressed_file_size 23 i
            getarray original_file_size 24 i
         endif
      endif
      getarray entry_number 25 i
      getarray entry_name 26 i
      if entry_type == 0
         putarray 27 folders entry_number
         putarray 28 folders entry_name
         putarray 29 folders entry_first_sub_entry
         math folders + 1
      else
         putarray 30 files entry_number
         putarray 31 files entry_name
         putarray 32 files physical_file_offset
         putarray 33 files time_stamp
         putarray 34 files entry_type
         if entry_type == 1
            putarray 35 files file_size
         elif entry_type == 2
            putarray 35 files compressed_file_size
            putarray 36 files original_file_size
         endif
         math files + 1
      endif
   next i
   for i = 0 < files
      math total_keywords = 0
      getarray file_number 30 i
      getarray file_name 31 i
      getarray physical_file_offset 32 i
      getarray time_stamp 33 i
      getarray file_type 34 i
      if file_type == 1
         getarray file_size 35 i
      elif file_type == 2
         getarray compressed_file_size 35 i
         getarray original_file_size 36 i
         goto physical_file_offset
         get deflate_sign long
         math deflate_sign ~ deflate_sign
         math deflate_sign & 0xffffffff
         get original_file_size_02 long
         math original_file_size_02 ~ original_file_size_02
         math original_file_size_02 & 0xffffffff
         math physical_file_offset + 8
      endif
      putarray 41 total_keywords file_name
      math total_keywords = 1
      math x1 = 0
      math found_folder_number = 0
      callfunction prepare_file_name_building 1
      if file_type == 1
         log full_name physical_file_offset file_size
      elif file_type == 2
         clog full_name physical_file_offset compressed_file_size original_file_size_02
      endif
   next i
endif

startfunction parse_rofs_ver_one
   goto entry_info_offset
   /*
   putarray 0 j 0
   putarray 1 j 0
   putarray 2 j 0
   putarray 3 j ""
   putarray 4 j 0
   putarray 5 j 0
   putarray 6 j 0
   putarray 7 j 0
   putarray 8 j 0
   putarray 9 j 0
   putarray 10 j 0
   putarray 11 j 0
   putarray 12 j 0
   putarray 13 j 0
   putarray 14 j 0
   */
   for pos_01 = entry_info_offset < info_size
      if dir_is_done = 1
         break
      endif
      get entry_info long
      xmath entry_type "(entry_info >> 24) & 0xff"
      xmath entry_name_offset "entry_info & 0xffffff"
      math pos_01 + 4
      savepos temp_01
      goto entry_name_offset
      set entry_name_string string ""
      for x = 0
         get string_char byte
         math string_char ^ 0xff
         if string_char == 0
            break
         else
            string string_char = string_char
            string entry_name_string + string_char
         endif
      next x
      goto temp_01
      putarray 0 current_directory_number entry_info_offset
      putarray 1 current_directory_number entry_type
      putarray 2 current_directory_number entry_name_offset
      putarray 3 current_directory_number entry_name_string
      if entry_name_offset != 0
         if entry_type == 0
            get file_offset long
            get file_size long
            math pos_01 + 8
            putarray 4 current_directory_number file_offset
            putarray 5 current_directory_number file_size
            #callfunction get_file_from_rofs_ver_one 1
            callfunction rofs_ver_one_step_back 1
         elif entry_type == 1
            get sub_directories long
            putarray 4 current_directory_number sub_directories
            math pos_01 + 4
            xmath max_sub_dir_limit "sub_directories + 15"
            putarray 5 current_directory_number max_sub_dir_limit
            getarray current_sub_dir_number 7 current_directory_number
            if current_sub_dir_number == 0
               math next_sub_dir_number = 2
            else
               xmath next_sub_dir_number "current_sub_dir_number + 1"
            endif
            putarray 9 current_directory_number next_sub_dir_number
            xmath pos_01_aid "current_sub_dir_number * 4"
            math pos_01 + pos_01_aid
            for i1 = current_sub_dir_number < next_sub_dir_number
               if i1 == sub_directories
                  break
               endif
               xmath i2 "i1 + 15"
               goto pos_01
               get sub_dir_offset long
               putarray i2 current_directory_number sub_dir_offset
               math pos_01 + 4
            next i1
         elif entry_type == 2
            get file_offset long
            get original_file_size long
            get compressed_file_size long
            math pos_01 + 12
            putarray 4 current_directory_number file_offset
            putarray 5 current_directory_number original_file_size
            putarray 10 current_directory_number compressed_file_size
            #callfunction get_file_from_rofs_ver_one 1
            callfunction rofs_ver_one_step_back 1
         endif
      endif
      if entry_type == 1
         getarray sub_directories 4 current_directory_number
         getarray current_padded_sub_dir_number 6 current_directory_number
         putarray 6 current_directory_number current_padded_sub_dir_number
         getarray current_sub_dir_number 7 current_directory_number
         getarray next_padded_sub_dir_number 8 current_directory_number
         getarray next_sub_dir_number 9 current_directory_number
         print " %current_padded_sub_dir_number% "
         if current_sub_dir_number == sub_directories
            if current_directory_number == 0
               math dir_is_done = 1
            else
               callfunction rofs_ver_one_step_back 1
            endif
         else
            for i1 = current_sub_dir_number < next_sub_dir_number
               getarray sub_dir_offset current_padded_sub_dir_number current_directory_number
               xmath next_padded_sub_dir_number "current_padded_sub_dir_number + 1"
               putarray 6 current_directory_number current_padded_sub_dir_number
               putarray 7 current_directory_number current_sub_dir_number
               putarray 8 current_directory_number next_padded_sub_dir_number
               putarray 9 current_directory_number next_sub_dir_number
               math current_padded_sub_dir_number + 1
               math current_sub_dir_number + 1
               if i1 != 0
                  math entry_info_offset = sub_dir_offset
                  math current_directory_number + 1
                  putarray 6 current_directory_number 15
                  putarray 7 current_directory_number 0
                  putarray 8 current_directory_number 16
                  callfunction parse_rofs_ver_one 1
               else
               endif
            next i1
         endif
      endif
   next
endfunction

startfunction rofs_ver_one_step_back
   math current_directory_number - 1
   getarray entry_info_offset 0 current_directory_number
   getarray max_sub_dir_limit 5 current_directory_number
   getarray current_padded_sub_dir_number 6 current_directory_number
   getarray current_sub_dir_number 7 current_directory_number
   getarray next_padded_sub_dir_number 8 current_directory_number
   getarray next_sub_dir_number 9 current_directory_number
   putarray 6 current_directory_number next_padded_sub_dir_number
   math current_sub_dir_number + 1
   putarray 7 current_directory_number current_sub_dir_number
   math next_padded_sub_dir_number + 1
   putarray 8 current_directory_number next_padded_sub_dir_number
   putarray 9 current_directory_number next_sub_dir_number
   math dir_is_done = 0
   callfunction parse_rofs_ver_one 1
endfunction

startfunction get_file_from_rofs_ver_one
   xmath max_name_strings "current_directory_number + 1"
   set file_name string ""
   for x = 0 < max_name_strings
      string file_name + "/"
      getarray entry_name_string 3 x
      string file_name + entry_name_string
   next x
   getarray file_offset 4 current_directory_number
   math file_offset << 11
   if entry_type == 2
      getarray original_file_size 5 current_directory_number
      getarray compressed_file_size 10 current_directory_number
      savepos temp_04
      goto file_offset
      for cc = 1 <= 2
         get compressed_sign byte
         if cc = 1
            if compressed_sign == 0x1f
               math comp_type = 1
            elif compressed_sign == 0xc5
               math comp_type = 2
            endif
         elif cc = 2
            if compressed_sign == 0x8b
               math comp_type = 1
            elif compressed_sign == 0xee
               math comp_type = 2
            endif
         endif
      next cc
      if comp_type = 1
         comtype gzip
      elif comp_type = 2
         comtype deflate_noerror
         goto file_offset
         get deflate_sign long
         math deflate_sign ~ deflate_sign
         get original_file_size_02 long
         math original_file_size_02 ~ original_file_size_02
         math file_offset + 8
      endif
      goto temp_04
   else
      getarray file_size 5 current_directory_number
   endif
   if entry_type == 2
      clog file_name file_offset compressed_file_size original_file_size
   else
      log file_name file_offset file_size
   endif
endfunction

startfunction parse_rofs_ver_three
   goto 0 chunk_read_element
   get chunk_type short chunk_read_element
   get sub_entries short chunk_read_element
   math sub_entries / 2
   get previous_chunk_number long chunk_read_element
   get next_chunk_number long chunk_read_element
   if chunk_type == 1
      math chunk_info_offset = 0x7f8
   else
      math chunk_info_offset = 0x7fc
   endif
   if chunk_type == 1
      for ki = 0 < sub_entries
         goto chunk_info_offset chunk_read_element
         get entry_info_offset short chunk_read_element
         putarray 11 ki entry_info_offset
         get entry_info_size short chunk_read_element
         putarray 12 ki entry_info_size
         get related_chunk_number long chunk_read_element
         putarray 13 ki related_chunk_number
         math chunk_info_offset - 8
      next ki
   else
      for ki = 0 < sub_entries
         for k2 = 0 < 2
            goto chunk_info_offset chunk_read_element
            get entry_info_offset short chunk_read_element
            get entry_info_size short chunk_read_element
            if k2 = 0
               putarray 14 ki entry_info_offset
               putarray 15 ki entry_info_size
            elif k2 = 1
               putarray 16 ki entry_info_offset
               putarray 17 ki entry_info_size
            endif
            math chunk_info_offset - 4
         next k2
      next ki
   endif
   if chunk_type == 1
      for ki = 0 < sub_entries
         getarray entry_info_offset 11 ki
         getarray entry_name_string_size 12 ki
         getarray related_chunk_number 13 ki
         goto entry_info_offset chunk_read_element
         getdstring full_entry_info entry_info_size chunk_read_element
      next ki
   else
      for ki = 0 < sub_entries
         getarray entry_info_offset_01 14 ki
         getarray entry_info_size_01 15 ki
         goto entry_info_offset_01 chunk_read_element
         get entry_type byte chunk_read_element
         putarray 18 total_entries entry_type
         if entry_type == 0
            get entry_first_sub_entry long chunk_read_element
            putarray 19 total_entries entry_first_sub_entry
         else
            get file_offset long chunk_read_element
            putarray 20 total_entries file_offset
            get time_stamp time chunk_read_element
            putarray 21 total_entries time_stamp
            xmath physical_file_offset "base_offset + (file_offset * average_block_size_per_sector)"
            putarray 22 total_entries physical_file_offset
            if entry_type == 1
               get file_size long chunk_read_element
               putarray 23 total_entries file_size
            elif entry_type == 2
               get compressed_file_size long chunk_read_element
               putarray 23 total_entries compressed_file_size
               get original_file_size long chunk_read_element
               putarray 24 total_entries original_file_size
            endif
         endif
         getarray entry_info_offset_02 16 ki
         getarray entry_info_size_02 17 ki
         goto entry_info_offset_02 chunk_read_element
         get entry_number long chunk_read_element
         math entry_number s 4
         putarray 25 total_entries entry_number
         math entry_name_string_size = entry_info_size_02
         math entry_name_string_size - 4
         getdstring entry_name entry_name_string_size chunk_read_element
         putarray 26 total_entries entry_name
         math total_entries + 1
      next ki
   endif
endfunction

startfunction prepare_file_name_building
   math search_is_over = 0
   for x = x1
      if search_is_over = 1
         break
      endif
      if x = 0
         for j = 0 < folders
            getarray folder_number 27 j
            getarray folder_name 28 j
            getarray first_entry_within_this_folder 29 j
            if first_entry_within_this_folder == file_number
               math found_folder_number = folder_number
               putarray 41 total_keywords folder_name
               math total_keywords + 1
               math x1 + 1
               break
            endif
         next j
      else
         for j = 0 < folders
            getarray folder_number 27 j
            getarray folder_name 28 j
            getarray first_entry_within_this_folder 29 j
            if first_entry_within_this_folder == found_folder_number
               math found_folder_number = folder_number
               putarray 41 total_keywords folder_name
               math total_keywords + 1
               if folder_number != 0
                  math x1 + 1
                  callfunction prepare_file_name_building 1
               else
                  math search_is_over = 1
                  math x1 + 1
                  if search_is_over = 1
                     break
                  endif
               endif
            endif
         next j
      endif
   next x
   for x2 = 0 < total_keywords
      getarray key_word 41 x2
   next x2
   math x3 = total_keywords
   math x3 - 1
   set full_name string ""
   for x2 = 0 < total_keywords
      string full_name + "/"
      getarray key_word 41 x3
      string full_name + key_word
      math x3 - 1
   next x2
endfunction
should you need any sample files to test this, just let me know.
aluigi
Site Admin
Posts: 12984
Joined: Wed Jul 30, 2014 9:32 pm

Re: QuickBMS errors [programming, scripting, quickbms.exe tool... NOT games]

Post by aluigi »

@spiritovod
ok, I will check.

@tbmq008
Wow, very long script :)
Have you also checked with the current beta?
https://aluigi.altervista.org/beta/quickbms_exe.zip
(if you need both the exes and source code: https://aluigi.altervista.org/beta/quickbms_beta.zip)

BTW, I guess it's a problem with the script because that "stack overflow" error is clearly referred to a function called many times recursively till it saturates the (huge) stack assigned to the process.
In any case I will now check if there is any stack variable that eats memory for nothing.
tbmq008
Posts: 62
Joined: Thu Nov 26, 2020 2:13 pm

Re: QuickBMS errors [programming, scripting, quickbms.exe tool... NOT games]

Post by tbmq008 »

checked with current beta, same problem.

Code: Select all

-------------------
*EXCEPTION HANDLER*
-------------------
An error or crash occurred:

*EH* ExceptionCode      c00000fd stack overflow
*EH* ExceptionFlags     00000000
*EH* ExceptionAddress   75727FC7
                        756C0000 + 00067fc7 msvcrt.dll
*EH* NumberParameters   00000002
*EH*                    00000000
*EH*                    03D62000

Last script line before the error or that produced the error:
  329 getarray next_padded_sub_dir_number 8 current_directory_number
  coverage file 0     0%   192085     3490467840 . offset 000063e4

as for the script being long... well, thanks.
i've only made it long because i wanted to find a way to parse that specific structure without using "hacks" or anything similar. so i went all out with it.
aluigi wrote:BTW, I guess it's a problem with the script because that "stack overflow" error is clearly referred to a function called many times recursively till it saturates the (huge) stack assigned to the process.
i guess that's why the script keeps breaking quickbms.