gemot encubed  

Go Back   gemot encubed > Gemot > Technical Issues

Technical Issues For bug reports, problem solving, and help running Japanese software.

Reply
 
Thread Tools Display Modes
  #1  
Old 2007-06-10, 06:37
Unregistered
Guest
 
Posts: n/a
Default Yume Miru Kusuri game data extraction

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);
Reply With Quote
  #2  
Old 2007-06-10, 07:02
Unregistered
Guest
 
Posts: n/a
Default

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... :)
Reply With Quote
  #3  
Old 2007-06-10, 09:00
zalas zalas is offline
 
 
Join Date: Feb 2004
Location: fushigi misuterii
Posts: 1,831
Send a message via ICQ to zalas
Default

Quote:
Originally Posted by Unregistered View Post
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... :)
Not owning the game, my guess is that stuff other than Bgm.arc is probably compressed ;)
__________________
~Yoda is waiting in the air~ | HAVEN
Reply With Quote
  #4  
Old 2007-06-10, 10:28
Unregistered
Guest
 
Posts: n/a
Default

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);
Reply With Quote
  #5  
Old 2007-11-26, 01:43
Unregistered
Guest
 
Posts: n/a
Default

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.
Reply With Quote
  #6  
Old 2007-11-26, 19:47
fireshark fireshark is offline
Local
 
Join Date: May 2007
Posts: 105
Default

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.
Reply With Quote
  #7  
Old 2007-11-26, 23:07
Asceai's Avatar
Asceai Asceai is offline
Posts way too much
 
Join Date: Mar 2007
Posts: 1,413
Default

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.
Reply With Quote
  #8  
Old 2007-11-27, 04:14
Unregistered
Guest
 
Posts: n/a
Default

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...)
Reply With Quote
  #9  
Old 2007-11-27, 04:23
Asceai's Avatar
Asceai Asceai is offline
Posts way too much
 
Join Date: Mar 2007
Posts: 1,413
Default

Yeah, activestate does. I assumed he's double-clicking the .pl file or something, in which passing an argument might not be immediately obvious.
Reply With Quote
Reply

Thread Tools
Display Modes

Posting Rules
You may post new threads
You may post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump

Similar Threads
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


All times are GMT -8. The time now is 21:48.


Powered by vBulletin® Version 3.8.7
Copyright ©2000 - 2023, vBulletin Solutions, Inc.