1#!/usr/bin/env bash 2 3############################################################################### 4# 5# Copyright (C) 2009-2013 Nintendo. All rights reserved. 6# 7# These coded instructions, statements, and computer programs contain 8# proprietary information of Nintendo of America Inc. and/or Nintendo 9# Company Ltd., and are protected by Federal copyright law. They may 10# not be disclosed to third parties or copied or duplicated in any form, 11# in whole or in part, without the prior written consent of Nintendo. 12# 13############################################################################### 14 15############################################################################### 16# main 17############################################################################### 18 19# Check arg 20if [ "$#" -ne 2 ]; then 21 echo "Usage: $0 AOC_ROOT_DIR AOC_NAME" 22 exit 1 23fi 24if [[ ! -d "$1" ]]; then 25 echo "[ERROR] $1 is not a directory!" 26 exit 1 27fi 28 29# Set variables 30AOC_ROOT_DIR=`cygpath -w -a "$1"` 31OUT_DIR="`cygpath -w -a "$AOC_ROOT_DIR"/outdir`" 32AOC_NAME="$2" 33APP_TITLE_ID=0005000C10000000 34APP_GROUP_ID=00000000 35APP_TITLE_VERSION=0000 36CAFE_BASEFILE_PATH="`cygpath -w "$CAFE_ROOT"/system/bin/tool/mastering/resources`" 37 38TOOL_DIR=`dirname "$0"` 39TOOL_DIR=`cygpath -w -a "$TOOL_DIR"` 40DEFAULT_DDF="`cygpath -w "$CAFE_ROOT"/system/bin/tool/mastering/resources/default_aoc.ddf`" 41COMMON_DDF_FILE="`cygpath -w "$OUT_DIR"/common_aoc.ddf`" 42INDIVIDUAL_DDF_FILE="`cygpath -w "$AOC_ROOT_DIR"/code/$AOC_NAME.ddf`" 43 44SECTION_ENTRY_HASH_OPTION="-filename_addhash" 45 46AOC_APP_XML="$AOC_ROOT_DIR/code/app.xml" 47AOC_COS_XML="$AOC_ROOT_DIR/code/cos.xml" 48AOC_META_XML="$AOC_ROOT_DIR/meta/meta.xml" 49META_DEFAULT_XML="$CAFE_ROOT/system/bin/ghs/cafe/boot/meta_default.xml" 50 51# Source function library. 52source "$TOOL_DIR/masteringfunctions.sh" 53 54 55############################################################################### 56# extract_info_from_app_xml 57# $1 - Path to app.xml 58############################################################################### 59extract_info_from_app_xml() 60{ 61 arg_num_check $# 1 62 local APP_XML_FILE="$1" 63 64 # get title id 65 APP_TITLE_ID=`sed -n 's|.*<title_id .*>\(.*\)</.*>|\1|p' "$APP_XML_FILE"` 66 APP_GROUP_ID=`sed -n 's|.*<group_id .*>\(.*\)</.*>|\1|p' "$APP_XML_FILE"` 67 APP_TITLE_VERSION=`sed -n 's|.*<title_version .*>\(.*\)</.*>|\1|p' "$APP_XML_FILE"` 68 69 echo "App Title ID : $APP_TITLE_ID" 70 echo "App Group ID : $APP_GROUP_ID" 71 echo "App Title Version : $APP_TITLE_VERSION" 72} 73 74 75# Create directories, if not exist 76if [[ ! -e "$AOC_ROOT_DIR/code" ]]; then 77 mkdir "$AOC_ROOT_DIR/code" 78fi 79if [[ ! -e "$AOC_ROOT_DIR/meta" ]]; then 80 mkdir "$AOC_ROOT_DIR/meta" 81fi 82if [[ ! -e "$OUT_DIR" ]]; then 83 mkdir "$OUT_DIR" 84fi 85 86# Copy default xml files, if not exist 87if [[ ! -e "$AOC_APP_XML" ]]; then 88 cp $CAFE_ROOT/system/bin/ghs/cafe/boot/app_default.xml $AOC_APP_XML 89 # Replace the value in <app_type>: 80000000 -> 0800000E 90 sed -i -e "s|\(<app_type.*>\)\(.*\)\(</app_type.*>\)|\10800000E\3|" $AOC_APP_XML 91 # Replace the value in <title_id>: XXXXXXXXXXXXXXXX -> XXXXXXXCXXXXXXXX 92 sed -i -e "s|\(<title_id.*>\)\(.\{7\}\)\(.\)\(.\{8\}\)\(</title_id.*>\)|\1\2C\4\5|" $AOC_APP_XML 93# sed -i -e "s|\(<title_id.*>\)\(.*\)\(</title_id.*>\)|\1XXXXXXXCXXXXXXXX\3|" $AOC_APP_XML 94fi 95if [[ ! -e "$AOC_COS_XML" ]]; then 96 cp $CAFE_ROOT/system/bin/ghs/cafe/boot/cos_default.xml $AOC_COS_XML 97fi 98if [[ ! -e "$AOC_META_XML" ]]; then 99 cp $CAFE_ROOT/system/bin/ghs/cafe/boot/meta_default.xml $AOC_META_XML 100fi 101 102# Copy default masterinfo.xml, if not exist 103DEFAULT_MASTERINFO_XML="$CAFE_ROOT/system/bin/tool/mastering/resources/masterinfo_aoc.xml" 104DEST_MASTERINFO_XML="$AOC_ROOT_DIR/code/masterinfo.xml" 105if [[ ! -e "$DEST_MASTERINFO_XML" ]]; then 106 cp -u "$DEFAULT_MASTERINFO_XML" "$DEST_MASTERINFO_XML" 107fi 108 109# Replace the GameType with "GA" (Game Add-on contents) 110sed -i -e "s|\(<GameType.*>\)\(.*\)\(</GameType.*>\)|\1GA\3|" "$DEST_MASTERINFO_XML" 111 112# Copy default iconTex.tga, if not exist 113DEFAULT_ICON_TEX_TGA="$CAFE_ROOT/system/bin/ghs/cafe/meta/iconTex.tga" 114DEST_ICON_TEX_TGA="$AOC_ROOT_DIR/meta/iconTex.tga" 115if [ ! -f "$DEST_ICON_TEX_TGA" ]; then 116 cp -u "$DEFAULT_ICON_TEX_TGA" "$DEST_ICON_TEX_TGA" 117fi 118 119# Call extract_info_from_app_xml 120extract_info_from_app_xml $AOC_APP_XML 121 122# set NDEBUG OS version 123G_OS_VERSION=`sed -n 's|.*<os_version.*>\(.*\)</os_version>|\1|p' "$META_DEFAULT_XML"` 124G_OS_VERSION=`echo $G_OS_VERSION | grep -Eo "[0-9a-fA-F]+"` 125if [ "${G_OS_VERSION:12:1}" == "8" ]; then 126 G_OS_VERSION="${G_OS_VERSION::12}4${G_OS_VERSION:13}" 127fi 128 129update_app_xml "$AOC_APP_XML" 130update_meta_xml "$AOC_META_XML" 131update_cos_xml "$AOC_COS_XML" 132 133check_appconf_version "$DEST_MASTERINFO_XML" 134 135# embed info 136# embed_sdk_version_to_masterinfo "$DEST_MASTERINFO_XML" 137embed_tool_version_to_masterinfo "$DEST_MASTERINFO_XML" 138embed_os_version_to_masterinfo "$DEST_MASTERINFO_XML" 139embed_mastering_sdk_version "$DEST_MASTERINFO_XML" 140reset_mastering_flag "$DEST_MASTERINFO_XML" "$AOC_META_XML" 141 142# Generate common_aoc.ddf 143echo " 144[Input] 145DiscHeaderBaseFileName=\"$CAFE_BASEFILE_PATH\\discheader_base.bin\" 146VolumeHeaderBaseFileName=\"$CAFE_BASEFILE_PATH\\volheader_base.bin\" 147 148[Output] 149LayoutFileName=\"$OUT_DIR\\$AOC_NAME.dlf\" 150OutputDirectory=\"$OUT_DIR\" 151AppName=\"$AOC_NAME\" 152 153[DiscID] 154GameType=GA 155TitleId=0x$APP_TITLE_ID 156GroupId=0x$APP_GROUP_ID 157GameVersion=`expr $(printf %d 0x$APP_TITLE_VERSION) / 16` 158 159[PathList] 160CODE_DIR=\"code\", \"$AOC_ROOT_DIR\\code\" 161META_DIR=\"meta\", \"$AOC_ROOT_DIR\\meta\" 162CONTENT_DIR=\"content\", \"$AOC_ROOT_DIR\\content\" 163" > "$COMMON_DDF_FILE" 164 165# Generate individual ddf file, if not exist 166if [[ ! -e $INDIVIDUAL_DDF_FILE ]]; then 167 echo "Generate individual_aoc.ddf" 168 169 # Get max section number 170 NUM_CONTENT_SUBDIR=`ls -1 "$AOC_ROOT_DIR/content" | wc -l` 171 (( MAX_SECTION = NUM_CONTENT_SUBDIR + 15 )) 172 if [[ ! -d "$AOC_ROOT_DIR/content/"`printf %04x $MAX_SECTION` ]]; then 173 echo "Error: $AOC_ROOT_DIR/content/`printf %04x $MAX_SECTION` not found" 174 exit 3 175 fi 176 echo "MAX_SECTION: `printf %04x $MAX_SECTION`" 177 if [[ $MAX_SECTION -ge 2016 ]]; then 178 echo "Error: Too many contents" 179 exit 4 180 fi 181 182 # Use hex number array instead of using printf, since printf is too slow 183 HEX_CHAR=(0 1 2 3 4 5 6 7 8 9 a b c d e f) 184 for (( i=0; i < 256; i++ )) { 185 (( hi = i / 16 )) 186 (( lo = i % 16 )) 187 HEX_STR[$i]="${HEX_CHAR[$hi]}${HEX_CHAR[$lo]}" 188 } 189 190 echo "Writing [SectionList]..." 191 { 192 echo "[SectionList]" 193 for (( i=0x0010; i<=MAX_SECTION; i++ )) { 194 (( hi = i / 256 )) 195 (( lo = i % 256 )) 196 SUBDIR_NAME="${HEX_STR[$hi]}${HEX_STR[$lo]}" 197 198 (( seclist_param = 100000 + 0x0010 - i )) 199 echo "\"ADDONCONTENT$SUBDIR_NAME\" = -$seclist_param" 200 } 201 echo "" 202 } >> "$INDIVIDUAL_DDF_FILE" 203 204 echo "Writing [SectionAssign]..." 205 { 206 echo "[SectionAssign]" 207 for (( i=0x0010; i<=MAX_SECTION; i++ )) { 208 (( hi = i / 256 )) 209 (( lo = i % 256 )) 210 SUBDIR_NAME="${HEX_STR[$hi]}${HEX_STR[$lo]}" 211 212 (( seclist_param = 100000 + 0x0010 - i )) 213 echo "-$seclist_param = \"content/$SUBDIR_NAME/*\", \"ADDONCONTENT$SUBDIR_NAME\", 0x040" 214 } 215 echo "" 216 } >> "$INDIVIDUAL_DDF_FILE" 217 218 echo "Writing [SectionParam]..." 219 { 220 echo "[SectionParam]" 221 echo "\"CONTENTDIR\" = 0x0000000000000000, 0x$APP_GROUP_ID, 0x02" 222 for (( i=0x0010; i<=MAX_SECTION; i++ )) { 223 (( hi = i / 256 )) 224 (( lo = i % 256 )) 225 SUBDIR_NAME="${HEX_STR[$hi]}${HEX_STR[$lo]}" 226 227 echo "\"ADDONCONTENT$SUBDIR_NAME\" = 0x0000000000000000, 0x$APP_GROUP_ID, 0x02" 228 } 229 echo "" 230 } >> "$INDIVIDUAL_DDF_FILE" 231else 232 cd $AOC_ROOT_DIR 233 # Force replace the GameType with "GA" (Game Add-on contents) 234 235 sed -i -e "s|\(GameType *= *\).*|\1GA|" "$INDIVIDUAL_DDF_FILE" 236 237 # Force replace the permission of ADDONCONTENT section with 0x040 238 sed -i -e "s|\(-[0-9]* *= *\"content/[0-9A-Fa-f]\{4\}/\*\", *\"ADDONCONTENT[0-9A-Fa-f]\{4\}\", *0x\)[0-9]\{3\}|\1040|" "$INDIVIDUAL_DDF_FILE" 239 240 # Force replace the OwnerId of ADDONCONTENT section with 0x0000000000000000 241 APP_GROUP_ID=`sed -n 's|\"ADDONCONTENT0010\" *= *0x[0-9A-Fa-f]*, *0x\([0-9A-Fa-f]*\), *0x[0-9A-Fa-f]*|\1|p' "$INDIVIDUAL_DDF_FILE"` 242 sed -i -e "/\"CONTENTDIR\" *= *0x[0-9A-Fa-f]*, *0x[0-9A-Fa-f]*, *0x[0-9A-Fa-f]*/d" "$INDIVIDUAL_DDF_FILE" 243 sed -i -e "s|\[SectionParam\]|\[SectionParam\]\n\"CONTENTDIR\" = 0x0000000000000000, 0x$APP_GROUP_ID, 0x02|" "$INDIVIDUAL_DDF_FILE" 244 sed -i -e "s|\(\"ADDONCONTENT[0-9A-Fa-f]\{4\}\" *= *\)0x[0-9A-Fa-f]*\(, *0x[0-9A-Fa-f]*, *0x[0-9A-Fa-f]*\)|\10x0000000000000000\2|" "$INDIVIDUAL_DDF_FILE" 245 cd - 246fi 247 248embed_ddf_info_to_masterinfo "$INDIVIDUAL_DDF_FILE" "$DEST_MASTERINFO_XML" 249check_section_entry_hash 250update_xml_flag_section_entry_hash "$DEST_MASTERINFO_XML" "$AOC_META_XML" 251 252"$MAKEDLF" -uf -mss=4024 -mi="$DEST_MASTERINFO_XML" "$DEFAULT_DDF" "$COMMON_DDF_FILE" "$INDIVIDUAL_DDF_FILE" "$SECTION_ENTRY_HASH_OPTION" 253 254"$MAKEIDBE" "$AOC_ROOT_DIR\\code\\masterinfo.xml" "$AOC_ROOT_DIR\\meta\\iconTex.tga" "$OUT_DIR\\icon.db" 255 256"$MAKEMASTER" -v -nc "-wd=./workdir" "$OUT_DIR\\$AOC_NAME.dlf" "$CAFE_BASEFILE_PATH\\masterheader_base.bin" "$AOC_ROOT_DIR\\code\\masterinfo.xml" "$OUT_DIR\\$AOC_NAME.wumad" "-rl=$OUT_DIR\\icon.db" "$SECTION_ENTRY_HASH_OPTION" 257 258# Show messages 259show_msg 260 261rm -Rf "./workdir" 262 263exit 0 264