#!/bin/bash
#
# Start the Bochs emulator.
# This script is a Unix-friendly wrapper to the bochs-executable (version 2.x)
#
# $Author: bablokb $
# $Revision: 1.14 $
#
# License: GPL2 (see LICENSE)
# -----------------------------------------------------------------------------

. `dirname $0`/bxtfuncs.inc
pgmDir=`dirname $0`

# usage message   -------------------------------------------------------------

usage() {
  echo -e "\n`basename $0`: start the bochs-emulator\n\
  \nusage: `basename $0` [options] [additional bochs arguments]\n\
  possible options:\n\
    -V                    show version\n\
    -h                    show this help\n\
    -q                    run quiet (default)\n\
    -v                    verbose messages\n\
    -s                    only simulate\n\
    -C cylinders          number of cylinders (default: autodetect)\n\
    -H heads              number of heads (default: autodetect)\n\
    -S spt                number of sectors-per track (default: autodetect)\n\
    -b floppy|disk|cdrom: boot from floppy (default), first disk or cdrom\n\
    -t tranlation-mode:   format: 1=mode[,2=mode] (default: 1=auto,2=auto)\n\
    -f filename:  path to floppy-image (default: /dev/fd0)\n\
    -1 filename:  path to hda-image (default: no first disk)\n\
    -c filename:  path to cdrom-image (default: /dev/cdrom)\n\
    -2 filename:  path to hdb-image (default: no second disk)\n\
"
  exit 3
}

# set system defaults   -------------------------------------------------------

setDefaults() {
  quiet=1; simulate=0;
  [ -z "$BOCHS" ] && BOCHS="bochs"
  boot="boot: floppy"
  floppyPath="/dev/fd0"
  floppySize="1_44"
  hdaPath=""
  hdaMode="auto"
  hdaCyl=""; hdaHeads=""; hdaSpt=""
  hdbPath=""
  hdbMode="auto"
  cdromPath="/dev/cdrom"
  extraBochsArgs=""
}

# parse arguments and set variables -------------------------------------------

parseArguments() {
  while getopts ":C:H:S:b:t:f:1:c:2:Vhqvs" opt; do
    case $opt in
      b) boot="boot: $OPTARG";;
      t) tMode="$OPTARG";;
      f) floppyPath=$OPTARG;;
      1) hdaPath=$OPTARG;;
      C) hdaCyl=$OPTARG;;
      H) hdaHeads=$OPTARG;;
      S) hdaSpt=$OPTARG;;
      c) cdromPath=$OPTARG;;
      2) hdbPath=$OPTARG;;
      V) showCopyright `basename $0` "start the bochs-emulator";;
      h) usage;;
      q) quiet=1;;
      v) quiet=0;;
      s) simulate=1;;
      ?) echo "error: illegal option: $OPTARG" >&2
           usage;;
    esac
  done
  let OPTIND-=1
  shift $OPTIND
  extraBochsArgs="$@"
}

# check arguments   -----------------------------------------------------------

checkArguments() {
  if [ "$floppyPath" != "/dev/fd0" ]; then
    if [ ! -f $floppyPath ]; then
      echo "error: floppy-image $floppyPath does not exist" >&2
      exit 3
    fi
  fi
  if [ ! -z "$hdaPath" ]; then
    if [ ! -f "$hdaPath" ]; then
      echo "error: disk-image $hdaPath does not exist!" >&2
      exit 3
    fi
    if [ -n "$hdaCyl" ]; then
      if [ -z "$hdaHeads" -o -z "$hdaSpt" ]; then
        echo "error: geometry only partly specified!" >&2
        exit 3
      fi
    fi
  fi
  
  if [ ! -z "$hdbPath" ]; then
    if [ ! -f "$hdbPath" ]; then
      echo "error: disk-image $hdbPath does not exist!" >&2
      exit 3
    fi
  fi
  
  if [ ! -z "$cdromPath" ]; then
    if [ "$cdromPath" != "/dev/cdrom" -a ! -f $cdromPath ]; then
      echo "error: cdrom-image $cdromPath does not exist" >&2
      exit 3
    fi
  fi
}

# set floppy-size   -----------------------------------------------------------

setFloppySize() {
  if [ "$floppyPath" != "/dev/fd0" ]; then
    floppySize=`find $floppyPath -follow -printf "%s"`
    if [ $floppySize -eq 1474560 ]; then
      floppySize="1_44"
    elif [ $floppySize -eq 2949120 ]; then
      floppySize="2_88"
    else
      echo "error: invalid size for floppy-image" >&2
      exit 3
    fi
  fi
}

# parse disk-tranlation mode   ------------------------------------------------

parseMode() {
  local info=$1
  [ -z "$info" ] && return
  local disk=${info%%=*}
  if [ $disk -eq 1 ]; then
    hdaMode=${info##*=}
  elif [ $disk -eq 2 ]; then
    hdbMode=${info##*=}
  fi
}

# main program   --------------------------------------------------------------

setDefaults
parseArguments "$@"
checkArguments
setFloppySize
parseMode ${tMode%%,*}
parseMode ${tMode##*,}

floppyArg="floppya: $floppySize=$floppyPath, status=inserted"

if [ ! -z "$hdaPath" ]; then
  if [ -z "$hdaCyl" ]; then
    hdGeom=`"$pgmDir"/bxtptinfo -b $hdaPath 2>/dev/null`
  else
    hdGeom="cylinders=$hdaCyl, heads=$hdaHeads, spt=$hdaSpt"
  fi
  if [ -z "$hdGeom" ]; then
    echo "error: unknown geometry for $hdaPath!" >&2
    exit 3
  fi
  hdaArg="ata0-master: translation=$hdaMode, type=disk, path=$hdaPath, $hdGeom"
fi

if [ ! -z "$hdbPath" ]; then
  hdGeom=`"$pgmDir"/bxtptinfo -b $hdbPath 2>/dev/null`
  if [ -z "$hdGeom" ]; then
    echo "error: unknown geometry for $hdbPath!" >&2
    exit 3
  fi
  hdbArg="ata0-slave: translation=$hdbMode, type=disk, path=$hdbPath, $hdGeom"
fi

if [ ! -z "$cdromPath" ]; then
  cdromArg="ata1-master: type=cdrom, path=$cdromPath, status=inserted"
fi

${BOCHS} -q "$boot" "$floppyArg" "$hdaArg" "$hdbArg" "$cdromArg" "$extraBochsArgs"
