#! /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] [-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, ih -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
  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 {
  set `ls -s $1`
  echo "$1"
}

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
    docrlf=""
    if [ "$1" != "dconfig" ]; then docrlf="-t";fi
    if ! ${MYDIR}/do_mtools $APP_HDIMAGE mcopy -o $docrlf ${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
}

if [ -z $1 ]; then
  usage
fi

DDIR=`(cd ..; pwd -P)`
MYDIR=`pwd -P`
MKFAT=${DDIR}/src/tools/periph/mkfatimage16

TARGDIR="/var/lib/dosemu"
mkdir -p $TARGDIR

USE_FREE_DOS="1"
DOSPART="${DDIR}/contrib/dosC/dist"
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=""
DOSEMUCONF=""
DCONFIG=""
IOSYS="ipl.sys"
MSDOS="kernel.exe"
COMCOM="command.com"
BOOTSEC="boot.bin"
APPNAME="test"
APPEXE=""
FILES=""
EXITEMU="${DDIR}/commands/exitemu.com"

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

CONFIRM="noconfirm"

badcase=0
while getopts "b:s:S: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;;
    a) AUTOEXEC=$OPTARG;;
    d) DOSEMUCONF=$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
  APPNAME=`basename $DOSAPP .zip`
  if [ "$APPNAME" = "$DOSAPP" ]; then
    echo "the DOS application need to packed into a *.zip file"
    usage
  fi
  APP_HDIMAGE="${TARGDIR}/${APPNAME}.dexe"

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

if [ "$DCONFIG" = "" ]; then
  DCONFIG="${MYDIR}/dconfig.default"
fi

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


# extract the system, if we don't use FreeDos
if [ "$USE_FREE_DOS" = "0" ]; then
  ${MYDIR}/extract-dos $DOSPART ${TMP}/sys -i $IOSYS -m $MSDOS
  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
  (cd ${TMP}/app; if ! unzip $DOSAPP; then exit 1; fi)
else
  (cd ${DDIR}/commands; 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="${DDIR}/etc/config.test";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

MINTRACKS=`echo "$(( ($MINSIZE + ( CYLINDERSIZE - 1 ) ) / $CYLINDERSIZE ))"`
#echo "$MINTRACKS $CYLINDERSIZE $MINSIZE = $(( $MINTRACKS * $CYLINDERSIZE)) Kbytes"

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

# padding with zero, because mtools currently  can't expand the disk
PADDINGSIZE="$(( ($MINTRACKS * $CYLINDERSIZE ) - `fsize $APP_HDIMAGE` ))"
dd if=/dev/zero bs=1024 count=$PADDINGSIZE 2>/dev/null |cat >> $APP_HDIMAGE

# now we copy the whole application tree onto it,
# we use a modified version of mtools 'xcopy' script for that
pushd $TMP/app
  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

# 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


# we cleanup things
rm -rf $TMP
