[PSP][InternetRadioExt][PRS] A script that generates PRS formatted files (for PSP FW 3.80)
前回の記事の説明があまりに不親切だったので、コードにしてみた。以下のスクリーンショットは、このブログの favicon をアイコン画像にしてみた例。
use strict; use IO::Handle; use IO::Simple qw(slurp); use constant { MAGIC => 'PRSF', }; use constant { HEADER_SIZE => 64 }; use constant { PROP_ENTRY_STD => 1, PROP_ENTRY_INFO => 2, PROP_ENTRY_WHAT => 3, PORP_ENTRY_ICON => 4, }; use vars qw(@PROPS %PROP_DESC); @PROPS = ( 'title', 'info', 'comment', 'copyright', 'author', 'radioplayer_url', 'homepage_url', 'version', ); %PROP_DESC = ( 'title' => { 'type' => PROP_ENTRY_STD }, 'info' => { 'type' => PROP_ENTRY_INFO }, 'comment' => { 'type' => PROP_ENTRY_STD }, 'copyright' => { 'type' => PROP_ENTRY_STD }, 'author' => { 'type' => PROP_ENTRY_STD }, 'radioplayer_url' => { 'type' => PROP_ENTRY_STD }, 'homepage_url' => { 'type' => PROP_ENTRY_STD }, 'version' => { 'type' => PROP_ENTRY_STD }, ); sub align { return $_[0] + pad_len(@_); } sub pad_len { return ($_[1] - 1 - ($_[0] + $_[1] - 1) % $_[1]); } sub gen { my %params = @_; my $str_table_blk = ''; my %str_table_info = (); my $icon_blk = $params{'icon'}; # build string table $str_table_blk .= "radioplayer\0"; $str_table_info{'icon'} = { 'offset' => length($str_table_blk) }; $str_table_blk .= "icon\0"; for my $key (@PROPS) { my $offset = length($str_table_blk); $str_table_blk .= pack('A*x', $key); if ($PROP_DESC{$key}->{'type'} == PROP_ENTRY_STD) { my $offset_val = length($str_table_blk); $str_table_blk .= pack('A*x', $params{$key}); $str_table_info{$key} = { 'offset' => $offset, 'offset_val' => $offset_val, 'value_len' => length($params{$key}) }; } else { $str_table_info{$key} = { 'offset' => $offset, }; } } # compose descriptor blk my $desc_blk = pack('VVVVVVVVVVV', 0, 2, -1, -1, -1, 0x3c, 0x3c, $str_table_info{'icon'}->{'offset'}, 0x6, 0x0, length($icon_blk) ); for my $key (@PROPS) { my $type = $PROP_DESC{$key}->{'type'}; if ($type == PROP_ENTRY_STD) { $desc_blk .= pack('VVVV', $str_table_info{$key}->{'offset'}, 3, $str_table_info{$key}->{'offset_val'}, $str_table_info{$key}->{'value_len'} ); } elsif ($type == PROP_ENTRY_INFO) { $desc_blk .= pack('VVVVVVV', $str_table_info{$key}->{'offset'}, 6, 0, -1, -1, -1, -1 ); } } # compose header blk my $off_str_table = HEADER_SIZE + align(length($desc_blk), 16); my $off_icon = $off_str_table + align(length($str_table_blk), 16); my $header_blk = pack('A4VVVVx4VVVx4Vx4VV@'. HEADER_SIZE, MAGIC, $params{'file_version'}, HEADER_SIZE, length($desc_blk), $off_str_table, $off_str_table, length($str_table_blk), $off_icon, $off_icon, $off_icon, align(length($icon_blk), 16) ); return $header_blk . $desc_blk. pack('x'. pad_len(length($desc_blk), 16)) . $str_table_blk. pack('x'. pad_len(length($str_table_blk), 16)) . $icon_blk. pack('x'. pad_len(length($icon_blk), 16)); } STDOUT->write(gen( 'file_version' => 0x00000100, 'title' => 'Internet Radio Player (1)', 'comment' => 'Internet Radio Player (1). This player is using the SHOUTcast directory service.', 'copyright' => 'C) 2007 SCEI ALL RIGHTS RESERVED.', 'author' => 'SCEI', 'radioplayer_url' => 'https://www.example.com/internetRadioPlayerV1/internetRadioPlayerV1.html', 'homepage_url' => 'http://www.playstation.com/psp-app/radio.html', 'version' => '1.0', 'icon' => scalar(slurp('icon.png')) ));