#! /bin/bash
#
# (C) 1997 under GPL, Hans Lermen <lermen@fgan.de>
#
# Make a direct executable (bootable) hdimage by composing a minimum
# DOS together with a DOS application. This hdimage can then be given
# as input to the script 'dosexec'
# For a more detailed description see ./doc/README.dexe
#
# BIG NOTE:
# If you want to contribute a *.dexe file to the public,
# please do NOT use any other DOS than FreeDos else you would violate
# existing copyrights. This also (unfortunately) is true for OpenDos
# which can only be distributed after Caldera did allow you to do so :-(
# Of course you also should make sure the application can be distributed
# free.
#
# However, if you _have_ assembled a *.dexe, you may perhaps like to
# contribute it. In that case send me a mail and upload the stuff to
#
#   tsx-11.mit.edu:/pub/linux/ALPHA/dosemu/Development/incoming
#
# The aim is to build an archive with good old DOS applications, that
# otherwise would not have a chance to be ported to Linux.
#

 
function usage {
  echo 'USAGE:
  mkdexe [{ application | hdimage}]
                     [-b dospart] [{-s|-S} size] [-x appname]
                     [-c confsys] [-a autoexe] [-C comcom ] [-d dosemuconf]
                     [-i IOname] [-m MSname]
                     [-o <option> [-o ...]]

  application  the whole DOS application packet into a *.zip file
  hdimage      the name of the target hdimage, if -o noapp is give
               (see below)
  dospart      If not given, FreeDos will be used as system
               If given it must be either a bootable DOS partion (/dev/...)
               or a already made bootable dosemu hdimage
  -s size      The _additional_ free space (in Kbytes) on the hdimage
  -S size      The total size (in Kbytes) of the hdimage -s,-S are mutual
               exclusive.
  appname      The DOS filename of the application, that should be executed
  confsys      Template for config.sys
  autoexe      Template for autoexec.bat
  comcom       file name of the shell, usually command.com
  dosemuconf   Template for the dosemu.conf to use
  IOname       The name of DOS file, that usually is called IO.SYS,
               (default for FreeDos: IPL.SYS) this one is always put as
               first file onto the hdimage
  MSname       The name of DOS file, that usually is called MSDOS.SYS, 
               (default for FreeDos: MSDOS.SYS) this one is always put as
               second file onto the hdimage
  -o <option>  Following option flags are recognized:
                 confirm   offer config.sys, autoexec.bat and dconfig
                           to edit via $EDITOR
                 nocomcom  Omit command.com, because its not used anyway
                           when using  shell=c:\appname.exe
                 noapp     Make a simple bootable hdimage for standard
                           DOSEMU usage (replacement for hdimage.dist)
'
  exit 1
}


if [ "$(( `mtools -V|awk '{print $3}'|tr ',a-z' ' '|tr '.' '0'` < 306 ))" \
      = "1" ]; then
  echo "wrong mtools version installed, please upgrade to >= 3.6"
  exit 1
fi



unset POSIXLY_CORRECT  # ... else ls -s would count in 512 bytes units

function fsize {
  if [ -f $1 ]; then
    set `ls -s $1`
    echo "$1"
  else
    echo "0"
  fi
}

function copy_text_file {
# $1  = DOS filename
# $2  = if = 'confirm', then invoke editor to confirm
# $3  = unix file name
  fname=$3
  if [ "$fname" != "" ]; then cp $fname ${TMP}/$1;fi
  if [ "$2" = "confirm" ]; then
    editor=$EDITOR
    if [ "$editor" = "" ]; then editor=vi; fi
    if [ "$1" = "config.sys" ]; then
      if [ ! -f ${TMP}/$1 ]; then
        echo "buffers=20" >${TMP}/$1
        echo "files=20" >>${TMP}/$1
        echo "shell=c:\\${APPEXE}" >>${TMP}/$1
      fi
    fi
    $editor ${TMP}/$1
  fi
  if [ -f ${TMP}/$1 ]; then
    if [ "$1" = "dconfig" ]; then
      $DEXECONF -M -i ${TMP}/$1 $APP_HDIMAGE
    else
      if ! ${MYDIR}/do_mtools $APP_HDIMAGE mcopy -o -t ${TMP}/$1 W:/${1}; then
        echo "XXXX error during mcopy of $1 XXXX"
        echo "may be you choose the size of the hdimage too small"
        exit 1
      fi 
    fi
  fi
}

if [ -z $1 ]; then
  usage
fi

THISDIR=`pwd -P`

         # ISBINRELEASE will be changed to 1 (via sed) for bin releases
if [ "ISBINRELEASE" = "1" ]; then
  ROOTDIR="" # just for test purposes
  DDIR=${ROOTDIR}/var/lib/dosemu
  BINDIR=${ROOTDIR}/usr/bin
  MYDIR="${DDIR}/dexe"
  MKFAT="${BINDIR}/mkfatimage16"
  DEXECONF="${BINDIR}/dexeconfig"
  DOSPART="${DDIR}/dosC"
  DOSEMUCONF="${DDIR}/etc/config.test"
  cd $MYDIR
else
  DDIR=`(cd ..; pwd -P)`
  MYDIR=`pwd -P`
  MKFAT=${DDIR}/src/tools/periph/mkfatimage16
  DEXECONF=${DDIR}/src/tools/periph/dexeconfig
  DOSPART="${DDIR}/contrib/dosC/dist"
  DOSEMUCONF=${DDIR}/etc/config.test
fi

EXITEMU="${DDIR}/commands/exitemu.com"
COMMANDSDIR=${DDIR}/commands
USE_FREE_DOS="1"
CYLINDERSIZE=`echo "$(( 17 * 4 / 2 ))"`  # 17 sectors, 4 heads
PARTSIZE="1224"                          # in Kbytes
FIXSIZE="32"     # for cyl 0, FAT and dir
FREESIZE="64"    # min reserved size
CONFSYS=""
AUTOEXEC=""
DCONFIG=""
IOSYS="ipl.sys"
MSDOS="kernel.exe"
COMCOM="command.com"
BOOTSEC="boot.bin"
APPNAME="test"
APPEXE=""
FILES=""

case $1 in
  -*) DOSAPP="hdimage.dist"; NOAPP="1";;
  *)  DOSAPP=$1; NOAPP="0"; shift;;
esac

if [ "${DOSAPP#/*}" != "$DOSAPP" ]; then
  TARGDIR=`dirname $DOSAPP`
  DOSAPP=`basename $DOSAPP`
else
  TARGDIR="/var/lib/dosemu"
fi
install -d $TARGDIR

 
CONFIRM="noconfirm"

badcase=0
while getopts "b:s:S:c:C:a:d:i:m:x:o:" OPT; do
  case $OPT in
    b) DOSPART=$OPTARG
       USE_FREE_DOS="0"
       MSDOS="msdos.sys"
       IOSYS="io.sys"
    ;;
    S) PARTSIZE=$OPTARG;;
    s) FREESIZE=$OPTARG; PARTSIZE="1";;
    c) CONFSYS=$OPTARG;;
    C) COMCOM=$OPTARG;;
    a) AUTOEXEC=$OPTARG;;
    d) DCONFIG=$OPTARG;;
    i) IOSYS=$OPTARG;;
    m) MSDOS=$OPTARG;;
    x) APPEXE=$OPTARG;;
    o) case $OPTARG in
         confirm)  CONFIRM="confirm";;
         nocomcom) COMCOM="";;
         noapp)    NOAPP="1";;
       esac
    ;;
    ?) badcase=1
  esac
done

if [ $badcase -eq 1 ]; then usage; fi

if [ "$NOAPP" = "0" ]; then
  _DOSAPP=`basename $DOSAPP`
  APPNAME="${_DOSAPP%.zip}"
  APPTYPE="zip"
  if [ "$APPNAME" = "$_DOSAPP" ]; then
    APPNAME="${_DOSAPP%.tgz}"
    APPTYPE="tgz"
    if [ "$APPNAME" = "$_DOSAPP" ]; then
      echo "the DOS application need to packed into a *.zip or *.tgz file"
      usage
    fi
  fi
  APP_HDIMAGE="${TARGDIR}/${APPNAME}.dexe"

  if [ "$APPEXE" = "" ]; then
    APPEXE="${APPNAME}.exe"
  fi
else
  APP_HDIMAGE="${TARGDIR}/${DOSAPP}"
  APPEXE=""
fi

# we make a temp dir
TMP=~/.dosemu/tmp/mkdexe.$$
mkdir -p $TMP


# extract the system, if we don't use FreeDos
if [ "$USE_FREE_DOS" = "0" ]; then
  if [ "$COMCOM" = "" ]; then
    ${MYDIR}/extract-dos $DOSPART ${TMP}/sys -i $IOSYS -m $MSDOS
  else
    ${MYDIR}/extract-dos $DOSPART ${TMP}/sys -i $IOSYS -m $MSDOS -C $COMCOM
  fi
  DOSPART="${TMP}/sys"
  if strings ${TMP}/sys/boot.bin|grep 'WINBOOT SYS' >/dev/null 2>&1; then
    HAVE_W95="1"
  fi
fi

# first we unpack the application to a temp dir
#
mkdir -p ${TMP}/app
if [ "$NOAPP" = "0" ]; then
  if [ "${DOSAPP#/}" = "$DOSAPP" ]; then
    DOSAPP="${THISDIR}/${DOSAPP}"
  fi
  if [ "$APPTYPE" = "zip" ]; then
    (cd ${TMP}/app; if ! unzip $DOSAPP; then exit 1; fi)
  else
    (cd ${TMP}/app; if ! tar -xzf $DOSAPP; then exit 1; fi)
  fi
  if [ "$DCONFIG" = "" ]; then
    DCONFIG="${MYDIR}/dconfig.default"
  fi
else
  (cd $COMMANDSDIR; cp -f * ${TMP}/app)
  if [ "$CONFSYS" = "" ]; then CONFSYS="${TMP}/app/config.sys";fi
  if [ "$AUTOEXEC" = "" ]; then AUTOEXEC="${TMP}/app/autoexec.bat";fi
  if [ "$DCONFIG" = "" ]; then DCONFIG=$DOSEMUCONF;fi
  EXITEMU=""
fi

# we calculate the size for the systemfiles and basic stuff
SYSSIZE=" $((   `fsize ${DOSPART}/${IOSYS}` \
              + `fsize ${DOSPART}/${MSDOS}` \
              + $FIXSIZE + $FREESIZE ))"
if [ "$COMCOM" != "" ]; then
SYSSIZE=" $((   $SYSSIZE \
              + `fsize ${DOSPART}/${COMCOM}` ))"
fi

# now we acculate the size of the application files
APPSIZE=`du -ks $TMP/app |awk '{print $1}'`

# ... and them together
MINSIZE=`echo "$(( $APPSIZE + $SYSSIZE ))"`

if [ "$(( $MINSIZE < $PARTSIZE ))" = "1" ]; then
  MINSIZE="$PARTSIZE"
fi

# padding with zero, because mtools currently  can't expand the disk
PADDING_OPT="-p"

# we create the bootable hdimage
_COMCOM=$COMCOM
if [ "$_COMCOM" != "" ]; then _COMCOM=${DOSPART}/${COMCOM};fi
$MKFAT -b ${DOSPART}/$BOOTSEC -k $MINSIZE $PADDING_OPT -f $APP_HDIMAGE \
   ${DOSPART}/${IOSYS} ${DOSPART}/${MSDOS} ${_COMCOM} $EXITEMU

# now we copy the whole application tree onto it,
# we use a modified version of mtools 'xcopy' script for that
pushd $TMP/app >/dev/null
  if ! ${MYDIR}/do_mtools $APP_HDIMAGE ${MYDIR}/myxcopy ./ W:/; then
    echo "XXXX error during mcopy XXXX"
    echo "may be you choose the size of the hdimage too small"
    echo "Use the -s option to give more space on the hdimage"
    exit 1
  fi
popd >/dev/null

# we copy the configuration files
# ... dosemu.conf first

if [ "$NOAPP" = "0" ]; then
  copy_text_file dconfig $CONFIRM $DCONFIG
fi

if [ "$HAVE_W95" = "1" ]; then
  copy_text_file msdos.sys $CONFIRM ${TMP}/sys/msdos.sys
fi

_CONFIRM=$CONFIRM
if [ "$CONFSYS" = "" ]; then _CONFIRM=confirm;fi
copy_text_file config.sys $_CONFIRM $CONFSYS

copy_text_file autoexec.bat $CONFIRM $AUTOEXEC

# make it executable
chmod 755 $APP_HDIMAGE

# we cleanup things
rm -rf $TMP
