Skip to content

Instantly share code, notes, and snippets.

@mirai-iro
Last active December 26, 2019 10:09
Show Gist options
  • Save mirai-iro/bbc4e6d963e6f56c3b2f054f2a3dfad6 to your computer and use it in GitHub Desktop.
Save mirai-iro/bbc4e6d963e6f56c3b2f054f2a3dfad6 to your computer and use it in GitHub Desktop.
コロムビアさん MASTER BOX DSはまだですか……

VIMJ utils

ファイルの説明

  • vimj_cut.pl
    • F_XXX.BIN & F_XXX.IDX からファイルを取り出します
  • vimj_sss2s14.pl
    • MIDステレオの楽曲データ(*.SSS)を2つの *.S14 ファイルに分割します
  • vimj_s14stereo.pl
    • デコードしたMIDステレオのデータを合成します
  • vimj_add_wav_header.pl
    • デコードしたRAWなPCMデータにヘッダをつけてWAVEデータにします

必要なもの

  • perl 処理系
  • 元データ(VIMJ.NDS) : 詳細はアレな感じで書けないので各自でどうにかしてください
  • G.722.1 Annex C のデコーダ (評価版のデコーダでよいです, どうにかして探してください)

S14のデコードパラメータ

decode.exe 0 *.S14 *.RAW 24000 14000
# usage: perl vimj_add_wav_header.pl XXX.RAW is_stereo
# (is_stereo value: songs=1, bgms=0)
# -> create *.wav
# use bigint;
my @wav_header = (
0x52, 0x49, 0x46, 0x46, 0x00, 0x00, 0x00, 0x00, 0x57, 0x41, 0x56, 0x45, 0x66, 0x6d, 0x74, 0x20,
0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0xd8, 0x7f, 0x00, 0x00, 0xb1, 0xff, 0x00, 0x00,
0x02, 0x00, 0x10, 0x00, 0x64, 0x61, 0x74, 0x61, 0x00, 0x00, 0x00, 0x00
);
my($file, $is_stereo) = @ARGV;
my $size = -s $file;
my($fp, $buffer, $file1, $fp1, $size1);
$buffer = '';
$size1 = $size + 36;
$wav_header[4] = ($size1 ) & 0xff;
$wav_header[5] = ($size1 >> 8) & 0xff;
$wav_header[6] = ($size1 >> 16) & 0xff;
$wav_header[7] = ($size1 >> 24) & 0xff;
$wav_header[40] = ($size ) & 0xff;
$wav_header[41] = ($size >> 8) & 0xff;
$wav_header[42] = ($size >> 16) & 0xff;
$wav_header[43] = ($size >> 24) & 0xff;
if($is_stereo){
$wav_header[22] = 2; # 2ch
# 32728.5 * 2 * 2 = 130914d -> 01FF62h
$wav_header[28] = 0x62;
$wav_header[29] = 0xff;
$wav_header[30] = 0x01;
$wav_header[31] = 0x00;
$wav_header[32] = 4; # 4byte
}
open($fp, '<', $file) || die "file error: $file";
binmode($fp);
read($fp,$buffer,$size);
close($fp);
$file1 = $file.'.wav';
die "file exist: $file1" if -f $file1;
open($fp1, '>', $file1) || die "file error: $file1";
binmode($fp1);
foreach $c (@wav_header){print $fp1 chr($c);}
print $fp1 $buffer;
close($fp1);
# usage: perl vimj_cut.pl F_XXX
# -> parse files to ./F_XXX/*
use strict;
$| = 1;
my $zero_char = chr(0);
my($file) = @ARGV;
my $file_idx = './'.$file.'.IDX';
my $file_bin = './'.$file.'.BIN';
my $dir = './'.$file;
mkdir($dir) unless (-d $dir);
open(FILE_IDX, $file_idx) || die "file error: $file_idx"; binmode(FILE_IDX);
open(FILE_BIN, $file_bin) || die "file error: $file_bin"; binmode(FILE_BIN);
my($file_name_base_addr,$file_cnt);
seek(FILE_BIN, 0x0C, 0);
$file_name_base_addr = ord(getc(FILE_BIN));
$file_name_base_addr += ord(getc(FILE_BIN)) * 256;
$file_name_base_addr += ord(getc(FILE_BIN)) * 65536;
$file_name_base_addr += ord(getc(FILE_BIN)) * 16777216;
seek(FILE_IDX, 0x0C, 0);
$file_cnt = ord(getc(FILE_IDX));
$file_cnt += ord(getc(FILE_IDX)) * 256;
$file_cnt += ord(getc(FILE_IDX)) * 65536;
$file_cnt += ord(getc(FILE_IDX)) * 16777216;
my($i,$j,$k,$l, $c,$c2, $data_offset,$data_size,$file_name_offset,$back_pos,$file_name, $buffer, $disp,$len,$dest,$from, @tmp,$r, $file1);
for($i=0; $i<$file_cnt; $i++){
$data_offset = ord(getc(FILE_IDX));
$data_offset += ord(getc(FILE_IDX)) * 256;
$data_offset += ord(getc(FILE_IDX)) * 65536;
$data_offset += ord(getc(FILE_IDX)) * 16777216;
$data_size = ord(getc(FILE_IDX));
$data_size += ord(getc(FILE_IDX)) * 256;
$data_size += ord(getc(FILE_IDX)) * 65536;
$data_size += ord(getc(FILE_IDX)) * 16777216;
$file_name_offset = ord(getc(FILE_IDX));
$file_name_offset += ord(getc(FILE_IDX)) * 256;
$file_name_offset += ord(getc(FILE_IDX)) * 65536;
$file_name_offset += ord(getc(FILE_IDX)) * 16777216;
$file_name = '';
if($file_name_offset > 0){
$file_name_offset += $file_name_base_addr;
seek(FILE_BIN, $file_name_offset, 0);
for(;;){
$c = getc(FILE_BIN);
last if ($c eq $zero_char);
last if (eof(FILE_BIN));
$file_name .= $c;
}
}
else{
$file_name = sprintf("%s_%04d.bin", $file, $i);
}
printf "%08X %08X %s", $data_offset,$data_size,$file_name;
if($data_size < 1){
print ' - skip.'."\n";
next;
}
seek(FILE_BIN, $data_offset, 0);
$buffer = '';
$r = 0;
@tmp = ();
if($data_size & 0x10000000){
$data_size = $data_size & 0xFFFFFFF;
# header
$c = ord(getc(FILE_BIN));
$c = ord(getc(FILE_BIN));
$c = ord(getc(FILE_BIN));
$c = ord(getc(FILE_BIN));
for($j=0; $j<$data_size; ){
$c = ord(getc(FILE_BIN)); # read flag
foreach $k (0..7){
if($c & 0x80){ # Compressed
$c2 = ord(getc(FILE_BIN)) * 256;
$c2 += ord(getc(FILE_BIN));
$disp = $c2 & 0xFFF;
$len = ( ($c2 >> 12) & 0xF ) + 3;
$from = $r - $disp - 1;
$from += 0x1000 if $from < 0;
foreach(1..$len){
$buffer .= $tmp[$from];
$tmp[$r++] = $tmp[$from];
$r = $r & 0xFFF;
$from++;
$from = $from & 0xFFF;
}
$j += $len;
}
else{ # Uncompressed
$c2 = getc(FILE_BIN);
$buffer .= $c2;
$tmp[$r++] = $c2;
$r = $r & 0xFFF;
$j++;
}
$c = $c << 1;
last if ($j >= $data_size);
}
last if ($j >= $data_size);
}
}
else{
read(FILE_BIN,$buffer,$data_size);
}
$file1 = $dir.'/'.$file_name;
open(FILE1, "> $file1") || die "file error: $file1";
binmode(FILE1);
print FILE1 $buffer;
close(FILE1);
print ' - OK!'."\n";
}
# usage: perl vimj_s14stereo.pl XXX_L.RAW XXX_R.RAW XXX.RAW
# -> create XXX.RAW
# use bigint;
my($fileL, $fileR, $fileS) = @ARGV;
my($fpL,$fpR,$fpS, $sizeL,$sizeR);
$sizeL = -s $fileL;
$sizeR = -s $fileR;
die "file size invalid. (L = $sizeL, R = $sizeR)" if $sizeL != $sizeR;
die "file exist: $fileS" if -f $fileS;
open($fpS, '>', $fileS) || die "file error: $fileS"; binmode($fpS);
open($fpL, '<', $fileL) || die "file error: $fileL"; binmode($fpL);
open($fpR, '<', $fileR) || die "file error: $fileR"; binmode($fpR);
my($c, $c1, $c2, $l,$r);
while(!eof($fpL)){
read($fpL,$c,2); $c1 = unpack('s',$c);
read($fpR,$c,2); $c2 = unpack('s',$c);
$l = ($c1 + $c2) / 2;
$r = ($c1 - $c2) / 2;
print $fpS pack('s',$l);
print $fpS pack('s',$r);
}
close($fpL);
close($fpR);
close($fpS);
# usage: perl vimj_sss2s14.pl XXX.SSS
# -> create XXX_L.S14 and XXX_R.S14
# use bigint;
my($file) = @ARGV;
my($fp, $buffer, $file0, $file1, $fp1, $file2, $fp2 );
$buffer = '';
open($fp, '<', $file) || die "file error: $file"; binmode($fp);
$file0 = $file;
if($file =~ /^(.+)\.SSS$/){$file0 = $1;}
$file1 = $file0.'_L.S14'; die "file exist: $file1" if -f $file1; open($fp1, '>', $file1) || die "file error: $file1"; binmode($fp1);
$file2 = $file0.'_R.S14'; die "file exist: $file2" if -f $file2; open($fp2, '>', $file2) || die "file error: $file2"; binmode($fp2);
while(!eof($fp)){
read($fp, $buffer, 60); print $fp1 $buffer;
read($fp, $buffer, 60); print $fp2 $buffer;
}
close($fp);
close($fp1);
close($fp2);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment