# vim:set ft=sh:

SHORTNAME=quake
LONGNAME="Quake (including mission packs)"

IDMIRRORFILE=/etc/game-data-packager/idstuff-mirrors

if [ "$0" = "./game-data-packager" ]; then
    IDMIRRORFILE="./etc/idstuff-mirrors"
fi

quake106_zip_sha256=ec6c9d34b1ae0252ac0066045b6611a7919c2a0d78a3a66d9387a8f597553239
quake_pak0sum_106=5906e5998fc3d896ddaf5e6a62e03abb
quake_pak0sum_101=85fc9cee2035b66290da1e33be2ac86b

quake_usage() {
        printf "game-data-packager ${SHORTNAME} [-m|-d|-mp1|-mp2] <path>\n\
game-data-packager ${SHORTNAME} -s [<path>]\n\
game-data-packager ${SHORTNAME} -c [<device>]\n\
\n\
-m <path>\tpath to a mounted Quake CD-ROM\n\
-d <path>\tpath to an unpacked Quake directory\n\
-s\t\tdownload Quake shareware, version 1.06\n\
-s <path>\tpath to a Quake shareware ZIP\n\
-mp1 <path>\tpath to an unpacked Scourge of Armagon directory\n\
\t\tor a mounted Scourge of Armagon CD\n\
-mp2 <path>\tpath to an unpacked Dissolution of Eternity directory\n\
\t\tor a mounted Dissolution of Eternity CD\n\
<path>\t\tpath to any of the above (game-data-packager will guess)\n\
--music [<cd>]\trip CD audio from block device <cd>, default /dev/cdrom\n\
--music <path>\tcopy pre-ripped 02*.ogg, ..., 11*.ogg from <path>\n\
--mp1-music [<cd>|<path>] same as --music but for Scourge of Armagon\n\
--mp2-music [<cd>|<path>] same as --music but for Dissolution of Eternity\n\
"
}

get_mirror () {
    (
        grep -v '^#' "${IDMIRRORFILE}" | sed 's#$#/quake#'
    ) | sort -R | head -n1
}

copyin () {
    install -d `dirname "$2"`
    install -m644 "$1" "$2"
}

mountpoint=""
method="guess"
verify_args() {
    case $# in
        0)
            quake_usage
            exit 0
            ;;
        1)
            case "$1" in
                (-s|--shareware)
                    mountpoint=""
                    method="swzip"
                    ;;
                (--music|--mp1-music|--mp2-music)
                    mountpoint="/dev/cdrom"
                    method="$1"
                    method="${method#--}"
                    ;;
                (-*)
                    usage >&2
                    quake_usage >&2
                    exit 1
                    ;;
                (*)
                    mountpoint="$1"
                    ;;
            esac
            ;;
        2)
            mountpoint="$2"
            if [ "$1" = "-m" ]; then
                method="cdrom"
            elif [ "$1" = "-d" ]; then
                method="dir"
            elif [ "$1" = "-s" ]; then
                method="swzip"
            elif [ "$1" = "-mp1" ]; then
                method="mp1"
            elif [ "$1" = "-mp2" ]; then
                method="mp2"
            elif [ "$1" = "--music" ] || [ "$1" = "--mp1-music" ] || \
                [ "$1" = "--mp2-music" ]; then
                method="$1"
                method="${method#--}"
            else
                usage >&2
                quake_usage >&2
                exit 1
            fi
            ;;
        *)
            usage >&2
            quake_usage >&2
            exit 1
            ;;
    esac
}

go() {
    
    verify_args "$@"
    case "$method" in
        "guess")
            guess_method
            ;;
        "cdrom")
            cdrom_method
            ;;
        "dir")
            dir_method
            ;;
        "swzip")
            swzip_method
            ;;
        "mp1")
            mp1_method
            ;;
        "mp2")
            mp2_method
            ;;
        "music"|"mp1-music"|"mp2-music")
            music_method "$method" "$mountpoint"
            ;;
        *)
            die "internal error"
            ;;
     esac
}

guess_method() {
    if [ -f "$mountpoint" ]; then
        debug "treating $mountpoint like a shareware ZIP"
        method="swzip"
        swzip_method
    elif [ -f "$(ifind "$mountpoint" "id1/pak0.pak")" ]; then
        debug "treating $mountpoint like an installed directory"
        method="dir"
        dir_method
    elif [ -f "$mountpoint/q101_int.1" ]; then
        debug "treating $mountpoint like a CD-ROM"
        method="cdrom"
        cdrom_method
   elif [ -f "$mountpoint/hipnotic/pak0.pak" ]; then
        debug "treating $mountpoint like a Scourge of Armagon directory or CD"
        method="mp1"
        mp1_method
    elif [ -f "$mountpoint/rogue/pak0.pak" ]; then
        debug "treating $mountpoint like a Dissolution of Eternity directory or CD"
        method="mp2"
        mp2_method
    elif [ -b "$mountpoint" ]; then
        printf "Unable to determine which CD-ROM is at $mountpoint.\n\
For Quake 1 please use:\n\
\t$0 $SHORTNAME --music $mountpoint\n\
For Mission Pack 1, Scourge of Armagon please use:\n\
\t$0 $SHORTNAME --mp1-music $mountpoint\n\
For Mission Pack 2, Dissolution of Eternity please use:\n\
\t$0 $SHORTNAME --mp2-music $mountpoint\n\
" >&2
        die "Please specify --music, --mp1-music or --mp2-music."
    else
        die "couldn't figure out what method to use for mountpoint $mountpoint"
    fi
}

unpack_quake106_pak0 () {
    require_program lha lhasa
    mirror=

    set +u
    zipfile="$1"
    set -u

    if [ -n "$zipfile" ]; then
        :
    elif [ -f "$WORKDIR/quake106.zip" ]; then
        zipfile="$WORKDIR/quake106.zip"
    else
        zipfile="$WORKDIR/quake106.zip"
        echo "downloading quake106.zip..." >&2
        mirror=`get_mirror`
        wget -O "$zipfile" "$mirror/quake106.zip" >&2
    fi

    exp=$quake106_zip_sha256
    real=`sha256sum -b "$zipfile" | cut -d ' ' -f1`

    if [ "x$real" != "x$exp" ]; then
        warn "$zipfile sha256sum does not match expected value"
        [ -z "$mirror" ] || warn "downloaded: $mirror/quake106.zip"
        warn "expected: $exp"
        warn "     got: $real"
        die "please obtain a correct copy of quake106.zip" 1
    fi

    (
        cd "$WORKDIR"
        gdp_unzip_paths "$zipfile" . resource.1
        mv resource.1 resource.exe
        lha xq resource.exe id1/pak0.pak
        rm resource.exe
    )

    pak0="$WORKDIR/id1/pak0.pak"
}

# check that the pak0/pak1 for original Quake are recognised.
# detect older versions and automatically replace with 1.06
verify_quake() {
    pak1sum=d76b3e5678f0b64ac74ce5e340e6a685          # 1.06
    pak1sum=$pak1sum,d76b3e5678f0b64ac74ce5e340e6a685 # 1.01

    verify_file "$pak0"
    [ "$pak1" = "" ] || verify_file "$pak1"

    # pak0 for shareware or registered Quake 1.06 is identical, and the
    # 1.01 to 1.06 patch only upgrades pak0 anyway, so if we find
    # that we have a 1.01 pak0, we can quietly upgrade it to 1.06
    # by downloading the shareware version.

    sum=`md5sum "$pak0" | cut -d' ' -f1`

    case "$sum" in
        ($quake_pak0sum_106)
            # OK
            ;;
        (*)
            # Not 1.06. Upgrade it using the shareware version.
            echo "Your copy of Quake is not 1.06. Upgrading it by" \
                "downloading quake106.zip" >&2
            require_program lha lhasa
            unpack_quake106_pak0
            ;;
    esac

    [ "$pak1" = "" ] || verify_md5sum_alternatives "$pak1" "$pak1sum"
}

cdrom_method() {
    bit1="$mountpoint/q101_int.1"
    bit2="$mountpoint/q101_int.2"
    bit1sum=752f49131bb3ba832346e873c1bcfdc6
    bit2sum=9ed67b39020575771e29645d977c9216
    
    require_program lha lhasa
    verify_file "$bit1"
    verify_file "$bit2"
    verify_md5sum "$bit1" "$bit1sum"
    verify_md5sum "$bit2" "$bit2sum"
    
    cat "$bit1" "$bit2" > "$WORKDIR/unpackme.exe"
    (
      cd "$WORKDIR"
      lha xq unpackme.exe
      rm unpackme.exe
    )
    
    pak0="$WORKDIR/id1/pak0.pak"
    if ! test -f "$pak0"; then
        pak0="$WORKDIR/ID1/PAK0.PAK"
    fi
    pak1="$WORKDIR/id1/pak1.pak"
    if ! test -f "$pak1"; then
        pak1="$WORKDIR/ID1/PAK1.PAK"
    fi
    suffix=registered
    folder=id1
    verify_quake
    common_method
}

dir_method() {
    pak0=$(ifind "$mountpoint" "id1/pak0.pak" | head -1)
    pak1=$(ifind "$mountpoint" "id1/pak1.pak" | head -1)
    suffix=registered
    folder=id1

    if [ -z "$pak0" ]; then
        die "id1/pak0.pak not found in $mountpoint" 1
    fi

    if [ -z "$pak1" ]; then
        die "id1/pak1.pak not found in $mountpoint" 1
    fi

    verify_quake
    common_method
}

swzip_method() {
    if [ -n "$mountpoint" ]; then
        zipfile=$(unravel "$mountpoint")
    else
        zipfile=""
    fi

    unpack_quake106_pak0 "$zipfile"
    pak1=""

    suffix=shareware
    folder=id1

    verify_file "$pak0"
    verify_md5sum_alternatives "$pak0" "$quake_pak0sum_106"
    common_method
}

mp1_method() {
    pak0="$mountpoint/hipnotic/pak0.pak"
    # MD5 sum for original CD version
    pak0sum=0ab83681aaf841c4320269e02941a14a
    # MD5 sum for glQuake-compatible version (see
    # http://speeddemosarchive.com/quake/qdq/movies/sds.html for more
    # info)
    pak0sum=$pak0sum,f05b7452ae725e060fb3d14f7731fb00
    pak1=""
    suffix=armagon
    folder=hipnotic

    verify_file "$pak0"
    verify_md5sum_alternatives "$pak0" "$pak0sum"
    common_method
}

mp2_method() {
    pak0="$mountpoint/rogue/pak0.pak"
    # MP2 CD
    pak0sum=f8898a483b131de21581656c94f3c1a4
    # MD5 sum for Steam-supplied version
    pak0sum=$pak0sum,f71428763229bdb373f00a547296efe3
    # MP2 as supplied with MP1 on a single CD
    pak0sum=$pak0sum,c38a4e04219c317cd1b02f386bdfe11f
    pak1=""
    suffix=dissolution
    folder=rogue

    verify_file "$pak0"
    verify_md5sum_alternatives "$pak0" "$pak0sum"
    common_method
}

# Requires the following variables on entry:
# pak0 - full path of the pak0.pak file to include
# pak1 - full path of the pak1.pak file to include (optional)
# suffix - package suffix to use
# folder - base folder for the PAK files
common_method() {
    DEBBASE="quake-${suffix}_${GAME_PACKAGE_VERSION}_all.deb"
    OUTFILE=`unravel "$OUTDIR"`"/$DEBBASE"
    cp -p "$DATADIR/$DEBBASE" "$OUTFILE"

    # force lower case for our copy of the files
    ln -s `unravel "$pak0"` "$WORKDIR/pak0.pak"
    [ "$pak1" = "" ] || ln -s `unravel "$pak1"` "$WORKDIR/pak1.pak"

    if [ "$pak1" = "" ]; then
        slipstream "$OUTFILE" "usr/share/games/quake/${folder}" \
            "$WORKDIR/pak0.pak"
    else
        slipstream "$OUTFILE" "usr/share/games/quake/${folder}" \
            "$WORKDIR/pak0.pak" "$WORKDIR/pak1.pak"
    fi
    [ -d "$WORKDIR/${folder}" ] && rm -rf "$WORKDIR/${folder}"
    [ ! -f "$WORKDIR/pak1.pak" ] || rm "$WORKDIR/pak1.pak"
    rm "$WORKDIR/pak0.pak"
    rm -f "$WORKDIR/quake106.zip"
}

music_method () {
    case "$1" in
        (mp1-music)
            suffix="armagon-music"
            folder="hipnotic"
            # this is just for error messages, we will actually copy
            # whatever we find
            max=09
            ;;
        (mp2-music)
            suffix="dissolution-music"
            folder="rogue"
            max=09
            ;;
        (*)
            suffix="music"
            folder="id1"
            max=11
            ;;
    esac

    audio="$2"

    deb="quake-${suffix}"
    DESTDIR="$WORKDIR/slipstream.unpacked"

    if [ -z "$OUTDIR" ]; then
        OUTFILE="$WORKDIR/out.deb"
    else
        OUTFILE=`unravel "$OUTDIR"`"/${deb}_${GAME_PACKAGE_VERSION}_all.deb"
    fi

    install -d "$DESTDIR/usr/share/games/quake/$folder"

    # DarkPlaces wants one of
    # {sound/cdtracks,music,music/cdtracks}/track{02,002}.ogg
    # QuakeSpasm specifically wants music/track02.ogg
    # => we use music/track02.ogg
    if [ -d "$audio" ]; then
        if ! ( [ -f "$audio"/02*.ogg ] || [ -f "$audio"/track02*.ogg ] ); then
            die "expected a directory containing [track]02*.ogg, ..., [track]${max}*.ogg" 1
        fi

        t=02
        while [ -f "$audio/$t"*.ogg ]; do
            copyin "$audio/$t"*.ogg \
                "$DESTDIR/usr/share/games/quake/${folder}/music/track${t}.ogg"
            t=$(( ${t#0} + 1 ))
            if [ $t -lt 10 ]; then
                t=0$t
            fi
        done
        t=02
        while [ -f "$audio/track$t"*.ogg ]; do
            copyin "$audio/track$t"*.ogg \
                "$DESTDIR/usr/share/games/quake/${folder}/music/track${t}.ogg"
            t=$(( ${t#0} + 1 ))
            if [ $t -lt 10 ]; then
                t=0$t
            fi
        done
    else
        packages="cdparanoia vorbis-tools"
        require_program cdparanoia $packages
        require_program oggenc $packages

        t=02
        while cdparanoia -d "$audio" $t "${WORKDIR}/tmp.wav"; do
            oggenc -o "$DESTDIR/usr/share/games/quake/$folder/music/track${t}.ogg" "${WORKDIR}/tmp.wav"
            rm -f "${WORKDIR}/tmp.wav"
            t=$(( ${t#0} + 1 ))
            if [ $t -lt 10 ]; then
                t=0$t
            fi
        done
    fi

    copyin "$DATADIR/changelog.gz" \
        "$DESTDIR/usr/share/doc/${deb}/changelog.gz"
    copyin "$DATADIR/quake/${deb}.copyright" \
        "$DESTDIR/usr/share/doc/${deb}/copyright"

    # slipstream_instsize, slipstream_repack assume that slipstream.unpacked
    # and DEBIAN are in the same place
    copyin "$DATADIR/quake/${deb}.control" \
        "$WORKDIR/DEBIAN/control"
    copyin "$DATADIR/quake/${deb}.md5sums" \
        "$WORKDIR/DEBIAN/md5sums"

    # we still need to md5sum the actual tracks - their contents
    # depend on the user's copy of oggenc
    ( cd "$DESTDIR" && md5sum usr/share/games/quake/*/music/*.ogg \
            >> ../DEBIAN/md5sums )

    debug "building .deb: $OUTFILE"
    ( cd "$WORKDIR" && slipstream_instsize )
    ( cd "$WORKDIR" && slipstream_repack "$OUTFILE" )

    rm -fr "$WORKDIR/DEBIAN"
    rm -fr "$DESTDIR"
}
