ZenHAX

Free Game Research Forum | Official QuickBMS support | twitter @zenhax
It is currently Fri Aug 12, 2022 8:18 am

All times are UTC




Post new topic  Reply to topic  [ 5 posts ] 
Author Message
PostPosted: Fri Jan 21, 2022 8:20 am 

Joined: Sat Aug 09, 2014 11:21 am
Posts: 909
Hi there,

I'm not really familiar with C, so I'm asking for help here. I'm currently taking a look at the mjh/mjb pairs from Star Wars: Bounty Hunter (PS2). The format is implemented in vgmstream but there is name information in an external file that I would like to implement. For this, I need the mjb extracted so I can parse the names in. The vgmstream plugin just parses the mjb by splitting at certain offsets as the mjh doesn't have any info on that.
I'll need the following code in QuickBMS format:
Code:
        int i;
        off_t subsong_offset = 0;

        total_subsongs = read_s32le(0x00,sh);
        if (target_subsong == 0) target_subsong = 1;
        if (target_subsong < 0 || target_subsong > total_subsongs || total_subsongs < 1) goto fail;

        for (i = 0; i < total_subsongs; i++) {
            off_t offset = 0x40 + 0x40 * i;
            size_t subsong_size = read_u32le(offset + 0x08,sh) * read_u32le(offset + 0x10,sh) * read_u32le(offset + 0x14,sh);

            if (i + 1== target_subsong) {
                header_offset = offset;
                start_offset = subsong_offset;
            }
            subsong_offset += subsong_size;
        }

Thanks a lot!


Last edited by AlphaTwentyThree on Fri Jan 21, 2022 8:04 pm, edited 1 time in total.

Top
   
PostPosted: Fri Jan 21, 2022 8:50 am 
Site Admin
User avatar

Joined: Wed Jul 30, 2014 9:32 pm
Posts: 12982
The first script I propose is just a mere reusage of the C code in quickbms with just some minimal changes for returning header_offset and start_offset other than subsong_offset.
Code:
set MEMORY_FILE10 string "
typedef unsigned int    off_t;
typedef unsigned int    size_t;

int function(unsigned char *sh, int target_subsong, int *header_offset, int *start_offset) {
        int i;
        off_t subsong_offset = 0;

        int total_subsongs = *(int*)(0x00+sh);
        if (target_subsong == 0) target_subsong = 1;
        if (target_subsong < 0 || target_subsong > total_subsongs || total_subsongs < 1) return -1;

        for (i = 0; i < total_subsongs; i++) {
            off_t offset = 0x40 + 0x40 * i;
            size_t subsong_size = *(unsigned int *)(offset + 0x08+sh) * *(unsigned int *)(offset + 0x10+sh) * *(unsigned int *)(offset + 0x14+sh);

            if (i + 1== target_subsong) {
                *header_offset = offset;
                *start_offset = subsong_offset;
            }
            subsong_offset += subsong_size;
        }

        return subsong_offset;
}
"

get SIZE asize
log MEMORY_FILE 0 SIZE

math header_offset = 0
math start_offset  = 0
calldll MEMORY_FILE10 function tcc subsong_offset MEMORY_FILE 123 &header_offset &start_offset
print "%subsong_offset% %header_offset% %start_offset%"

This method is the best if you have no time and the code would be too slow in bms script.

The code is very simple so it's also possible to make a native bms script, give me some minutes.


Top
   
PostPosted: Fri Jan 21, 2022 8:58 am 
Site Admin
User avatar

Joined: Wed Jul 30, 2014 9:32 pm
Posts: 12982
And this is the bms script:
Code:
math header_offset = 0
math start_offset  = 0
math subsong_offset = 0

get total_subsongs long
if target_subsong == 0
    math target_subsong = 1
endif

getdstring DUMMY 0x3c   # 0x40 - 4
for i = 1 <= total_subsongs
    get DUMMY long      # 0x0
    get DUMMY long      # 0x4
    get NUM1 long       # 0x8
    get DUMMY long      # 0xc
    get NUM2 long       # 0x10
    get NUM3 long       # 0x14
    getdstring DUMMY 0x28   # 0x40 - 0x18

    xmath subsong_size "NUM1 * NUM2 * NUM3"

    if i == target_subsong
        math header_offset = offset
        math start_offset = subsong_offset
    endif
    math subsong_offset += subsong_size
next i

print "%subsong_offset% %header_offset% %start_offset%"


Top
   
PostPosted: Fri Jan 21, 2022 4:11 pm 

Joined: Sat Aug 09, 2014 11:21 am
Posts: 909
Thanks for that - however, it should be

Code:
xmath subsong_size NUM1 * NUM2 * NUM3


Then everything fits. I basically needed an idea how the internal processing of vgmstream for a specific format was. Here's the script to get single tracks out of a mjh/mjb pair:

Code:
open FDDE mjh 0
open FDDE mjb 1
get FILES long 0
goto 0x40 0
get BNAME basename
set OFFSET 0
for i = 1 <= FILES
   get UNK1 long 0
   get UNK2 long 0
   get CH long 0
   get FREQ long 0
   get INTERLEAVE long 0
   get BLOCKS long 0
   getDstring DUMMY 0x28
   xmath SIZE "CH * BLOCKS * INTERLEAVE"
   string NAME p "%s_%d" BNAME i
   callfunction SS2 1
   math OFFSET += SIZE
next i

startfunction SS2
   xmath PSIZE "SIZE + 0x28"
   putVarChr MEMORY_FILE PSIZE 0
   log MEMORY_FILE 0 0
   set MEMORY_FILE binary "\x53\x53\x68\x64\x18\x00\x00\x00\x10\x00\x00\x00\xb0\x36\x00\x00\x02\x00\x00\x00\xc0\x2f\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\x53\x53\x62\x64\x00\xe8\x11\x00"
   append
   log MEMORY_FILE OFFSET SIZE 1
   append
   putVarChr MEMORY_FILE 0x24 SIZE long
   putVarChr MEMORY_FILE 0xc FREQ long
   putVarChr MEMORY_FILE 0x14 INTERLEAVE long
   putVarChr MEMORY_FILE 0x10 CH byte
   #get SIZE asize MEMORY_FILE
   string NAME += ".ss2"
   log NAME 0 PSIZE MEMORY_FILE
endfunction


Top
   
PostPosted: Fri Jan 21, 2022 4:33 pm 
Site Admin
User avatar

Joined: Wed Jul 30, 2014 9:32 pm
Posts: 12982
Ah yeah it's a multiplication and not a sum... all those asterisks in the adapted C code that I used as base for the bms confused me ahahaha
I fixed the script


Top
   
Display posts from previous:  Sort by  
Post new topic  Reply to topic  [ 5 posts ] 

All times are UTC


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Powered by phpBB® Forum Software © phpBB Limited