![]() |
|
Technical Issues For bug reports, problem solving, and help running Japanese software. |
![]() |
|
Thread Tools | Display Modes |
#1
|
|||
|
|||
![]()
I couldn't find a Susie plugin for this - seen one?
The file format is extremely simple, so here is a 10 minute Perl script I knocked up... First argument is the archive file name, optional second argument is a specific file. Code:
#!/usr/bin/perl use strict; use warnings; use bytes; use Fcntl; my($buf, $arc); sysopen($arc, $ARGV[0]||die('filename plz'), O_RDONLY) || die($!); # Header sysread($arc, $buf, 16)||die($!); my($file_ext)=substr($buf, 4, 4); $file_ext=~s/\0+$//; my($num_files, $idx_elen)=unpack('VV', substr($buf, 8, 8)); # In all archives, 'idx_elen' has been set to 16... # All index entries seem to be 17 bytes. I can only assume this tells us the index length, and thereby the filename+padding length? Or perhaps that is fixed at 8 chars + null... who knows. $idx_elen++; my $fnlen=$idx_elen-8; print("num files: $num_files\n"); # Index entries my(%index); while($num_files--) { sysread($arc, $buf, $idx_elen)||die($!); my $fn=substr($buf, 0, $fnlen); $fn=~s/\0+$//; $fn.='.'.$file_ext; $index{$fn}={ filename => $fn, length => unpack('V', substr($buf, -8, 4)), offset => unpack('V', substr($buf, -4, 4)) }; } # Grab a chunk out of the file sub write_out($$$$) { my($src, $dst, $offset, $length)=@_; seek($src, $offset, 0)||die("Failed to seek to file location. Truncated archive?"); my $n; while($length && ($n=sysread($src, $buf, ($length>0x10000?0x10000:$length)))) { print("Read $n bytes...\n"); $length-=$n; syswrite($dst, $buf)||die("Failed to write to destination: $!"); } if(!defined($n)) { die("Failed to read to end of file: $!"); } elsif(!$n) { die("premature EOF"); } return(0); } # Extract my $file=$ARGV[1]; if($file) { if(!$index{$file}) { die("$file is not in this archive (case-sensitive)"); } print("Extracting $file...\n"); my $out; sysopen($out, $file, O_CREAT|O_WRONLY)||die("Failed to open output file: $!"); write_out($arc, $out, $index{$file}{offset}, $index{$file}{length}); close($out); } else { print("No filename supplied, extracting all...\n"); foreach $file (values(%index)) { print("Extracting $$file{filename}...\n"); my $out; sysopen($out, $$file{filename}, O_CREAT|O_WRONLY)||die("Failed to open output file: $!"); write_out($arc, $out, $$file{offset}, $$file{length}); close($out); } } close($arc); exit(0); |
#2
|
|||
|
|||
![]()
I only tested it on the Bgm.arc, since that was the only one I was interested in.
It seems it doesn't work on chip.arc for some reason. I'll fix that later if anyone cares. Also, remove the 'print("Read $n bytes...\n");' line - it was for debugging purposes and obscures the normal output... :) |
#3
|
|||
|
|||
![]() Quote:
|
#4
|
|||
|
|||
![]()
Ah, nothing as complicated as that :)
It seems the index is split up into multiple sections based on file extension. All the other archives have only a single file type in them, so I didn't account for it. Having just got back home I fixed up the script, and it seems to handle them all now: Code:
#!/usr/bin/perl use strict; use warnings; use bytes; use Fcntl; my($buf, $arc); sysopen($arc, $ARGV[0]||die('filename plz'), O_RDONLY) || die($!); # Number of file types present sysread($arc, $buf, 4)||die($!); my($num_types)=unpack('V', $buf); # Each file type gets it's own index block my(%types); while($num_types--) { sysread($arc, $buf, 12)||die($!); $_=substr($buf, 0, 4); s/\0+$//; $types{$_}={ extension => $_, num_files => unpack('V', substr($buf, 4, 4)), index_offset => unpack('V', substr($buf, 8, 4)) }; print("File set $_, $types{$_}{num_files} files\n"); } # Read each index block # Filename sans-extension seems fixed at 9 bytes (yay lets throw off alignment...) my(%index); foreach my $type (values(%types)) { seek($arc, $$type{index_offset}, 0)||die("Failed to seek to index for $$type{extension}: $!"); while($$type{num_files}--) { sysread($arc, $buf, 17); my $fn=substr($buf, 0, 9); $fn=~s/\0+$//; $fn.='.'.$$type{extension}; $index{$fn}={ filename => $fn, length => unpack('V', substr($buf, -8, 4)), offset => unpack('V', substr($buf, -4, 4)) }; } } sub write_out($$$$) { my($src, $dst, $offset, $length)=@_; seek($src, $offset, 0)||die("Failed to seek to file location. Truncated archive?"); my $n; while($length && ($n=sysread($src, $buf, ($length>0x10000?0x10000:$length)))) { $length-=$n; syswrite($dst, $buf)||die("Failed to write to destination: $!"); } if(!defined($n)) { die("Failed to read to end of file: $!"); } elsif(!$n) { die("premature EOF"); } return(0); } my $file=$ARGV[1]; if($file) { if(!$index{$file}) { die("$file is not in this archive (case-sensitive)"); } print("Extracting $file...\n"); my $out; sysopen($out, $file, O_CREAT)||die("Failed to open output file: $!"); write_out($arc, $out, $index{$file}{offset}, $index{$file}{length}); close($out); } else { print("No filename supplied, extracting all...\n"); foreach $file (values(%index)) { print("Extracting $$file{filename}...\n"); my $out; sysopen($out, $$file{filename}, O_CREAT|O_WRONLY)||die("Failed to open output file: $!"); write_out($arc, $out, $$file{offset}, $$file{length}); close($out); } } close($arc); exit(0); |
#5
|
|||
|
|||
![]()
I apologize for posting in a (possibly) deceased thread but I'm using ActivePerl 5.8.8 build 822 on Windows XP Professional and trying to extract the data from the Bgm.arc of Yume Miru Kusuri. I have moved both the Perl script as well as the arc file into the same folder and have changed the
$ARGV[0]||die('filename plz') to $ARGV[0]||die('Bgm.arc') When I attempt to run the Perl script via command prompt there is nothing produced except one line of data saying "Bgm.arc at {location of perl script} line 10." As I am incredibly inexperienced with Perl I would greatly appreciate any help informing me as to what I'm doing wrong. I love the music for this game and it would be incredibly helpful to be able to have it in a playable format. |
#6
|
|||
|
|||
![]()
uh, that line isn't where you're supposed to put the filename, youre supposed to specify it when you run the program.
________ New Jersey Dispensary Last edited by fireshark; 2011-03-09 at 08:32. |
#7
|
||||
|
||||
![]()
Or replace that entire line with
sysopen($arc, "bgm.arc", O_RDONLY); EDIT: Oh, and if you got the Yume Miru Kusuri DVD from JAST/Peach Princess/whoever's selling it, there should be a directory containing the game's music in the 'Yume Miru Extras' directory on the DVD. Last edited by Asceai; 2007-11-26 at 23:10. |
#8
|
|||
|
|||
![]()
It's expecting the filename as the first command line argument.
C:\yume_game_data_dir> perl script.pl bgm.arc (Presuming activestate installs perl in your PATH, I have no idea whether it does or not...) |
#9
|
||||
|
||||
![]()
Yeah, activestate does. I assumed he's double-clicking the .pl file or something, in which passing an argument might not be immediately obvious.
|
![]() |
Thread Tools | |
Display Modes | |
|
|
![]() |
||||
Thread | Thread Starter | Forum | Replies | Last Post |
Yume Miru Kusuri Scrip Extraction/decryption | Rec | Production & Help | 1 | 2011-12-22 19:52 |
yume miru kusuri script | Kurogasa | Production & Help | 2 | 2010-07-17 14:09 |
Yume Miru Kusuri internals | Noko | Technical Issues | 0 | 2008-10-11 11:39 |
Other endings to Yume Miru Kusuri? | Unregistered | General Discussion | 12 | 2008-02-14 07:55 |
PP releasing Yume Miru Kusuri | byndhrzn | General Discussion | 55 | 2007-06-08 01:06 |