;; # @(#) launch.asm Version 1.1 (12/29/94). Copyright Venue  #
;************************************************************************
;*                                                                      *
;*                        l a u n c h . a s m                           *
;*                                                                      *
;*      This is the launcher for Medley on DOS.  It:                    *
;*                                                                      *
;*      * Looks for and validates any -m memsize argument on the        *
;*        command line.  Only values in the range 8 - 32 are allowed.   *
;*                                                                      *
;*      * Loads the real Medley emulator, emul.exe, from the same       *
;*        directory that the launcher came from.                        *
;*                                                                      *
;*      * Sets the Intel DOS Extender's profile to the requested        *
;*        memory size + 3Mb (to allow for the emulator, internal        *
;*        data areas, etc.)                                             *
;*                                                                      *
;*      * Set the termination address in the child process's PSP,       *
;*        so control returns to the launcher when Medley terminates.    *
;*                                                                      *
;*      * Jumps to the emulator's start address.                        *
;*                                                                      *
;*      * Upon return, just terminates cleanly.                         *
;*                                                                      *
;*      [We could perhaps do some diagnosis here of error returns?]     *
;*                                                                      *
;*                                                                      *
;*                                                                      *
;************************************************************************

;************************************************************************/
;*                                                                      */
;*      (C) Copyright 1993, 1994  Venue. All Rights Reserved.           */
;*      Manufactured in the United States of America.                   */
;*                                                                      */
;************************************************************************/

.model small
.386p
.stack 100h
.data 
	align 8
    ;********************************************************
    ;*  Parameter block for INT 214B, that loads medley.exe *
    ;********************************************************
envseg  DW      0       ; environment (0 = copy mine)
cmdip   DW      ?       ; command-line-tail pointer
cmdcs   DW      ?
fcb1    DD      ?       ; dummy first FCB to fill in
fcb2    DD      ?       ; " 2nd FCB, not here in DOS 4.01???
stk     DD      ?       ;  SS:SP for emul.exe, filled in by loader
csip    DD      ?       ; start addr for emul.exe, filled in by loader



retad   DD      FAR PTR myret   ; cs:ip return address, to put in
				; child PSP, so we get control back.


    ;* Error messages, misc strings, and work areas*
	align   8
memval  dd      0
errstg  DB      'ERROR:  Couldn''t free excess storage.',13,10,'$'
noload  db      'ERROR: Loading emulator failed:  $'
loaded  db      'LOAD SUCCESSFUL.',13,10,'$'
nominfo db      'ERROR: -m must be followed by a number 8 - 64.',13,10,'$'
badexe  db      'ERROR: emul.exe is corrupted.',13,10,'$'
emulpath DB     'emul.exe',0    ; name of the real emulator.
mflag   db      '-m'            ; to search for -m/-M in cmd line
mmflag  db      '-M'    
profile db      'PRO'           ; to find the DOS extender profile
cmdline db      128 dup (?)             ; hold the cmd line tail for real emulator

	;* Error-message table for failures loading emul.exe
	align   2
errtbl  dw      OFFSET ng0msg   ; 0 = unknown failure
	dw      OFFSET ng1msg   ; 1 = "invalid function"
	dw      OFFSET ng2msg   ; 2 = file not found
	dw      OFFSET ng3msg   ; 3 = path not found
	dw      OFFSET ng4msg   ; 4 = too many open files
	dw      OFFSET ng5msg   ; 5 = access denied
	dw      OFFSET ng0msg   ; 6 = not possible error
	dw      OFFSET ng0msg   ; 7 = not possible error
	dw      OFFSET ng8msg   ; 8 = insufficient storage
	dw      OFFSET ng0msg   ; 9 = not possible
	dw      OFFSET ngamsg   ; A = bad environment
	dw      OFFSET ngbmsg   ; B = bad format (corrupt .exe?)a

ng0msg  db      'Unknown problem',13,10,'$'
ng1msg  db      'Invalid Function',13,10
	db      'Make sure you are running DOS 4.0 or later.',13,10,'$'
ng2msg  db      'File not found.',13,10
	db      'CD to proper directory, or set PATH.',13,10,'$'
ng3msg  db      'Path not found.',13,10
	db      'CD to proper directory, or set PATH.',13,10,'$'
ng4msg  db      'Too many files open.',13,10
	db      'Shut down some TSRs that have file open?',13,10,'$'
ng5msg  db      'Access denied.',13,10
	db      'Make sure of your access rights to emul.exe?',13,10,'$'
ng8msg  db      'Not enough memory.',13,10
	db      'Shut down some TSR applications?',13,10,'$'
ngamsg  db      'Environment corrupt.',13,10
	db      'Check using SET; You may need to re-boot.',13,10,'$'
ngbmsg  db      'EXE file corrupted.',13,10,'$'
	db      'You may need to restore from backup or re-install.',13,10,'$'
.code



;************************************************************************
;*                                                                      *
;*                              M A C R O S                             *
;*                                                                      *
;*      prints  Given a string ptr in DX, print it to the display.      *
;*                                                                      *
;*      kill    Exit cleanly, using INT 21/4C                           *
;*                                                                      *
;************************************************************************

prints  macro   text
	mov     dx, OFFSET text
	mov     ah,9
	int     21h
	endm

kill    macro
	mov ah,4ch
	int 21h
	endm



;************************************************************************
;*                                                                      *
;*                      M A I N   E N T R Y                             *
;*                                                                      *
;*                                                                      *
;*                                                                      *
;*                                                                      *
;*                                                                      *
;************************************************************************

PUBLIC  main
main    PROC    NEAR

	mov     ax,ds           ; Save memory-block start for freeing
	mov     es,ax           ; excess memory in a bit.

	mov     ax,@data        ; DS points to start of data segment
	mov     ds,ax

	mov     cmdcs, ax       ; Copy the command line for the emulator
	mov     cmdip, OFFSET cmdline

	mov     di, OFFSET cmdline
	mov     cx,128
	mov     bx,es
	mov     dx,ds
	mov     es,dx
	mov     ds,bx
	mov     si,80h

	rep
	movsb

	mov     es,bx           ; Free the excess memory that DOS gives
	mov     ds,dx           ; us (we need it for the emulator)

	mov     ax,4a00h
	mov     bx,090h         ; We only need 900h bytes for this program
	int 21h
	jnc     freeok

	prints errstg           ; Couldn't free spare space; punt.
	kill

	;************************************************
	;*  Search the command line for -m or -M        *
	;************************************************
freeok: 
	mov     di,81h          ; start of command line tail
	mov     si, OFFSET mflag
	mov     cx, 2

	mov     bx,81h
	add     bl,es:[80h]

m1lp:   call strcmp
	je      fndm

	add     di, 1
	cmp     di, bx
	jl      m1lp

	mov     di,81h          ; start of command line tail
	mov     si, OFFSET mmflag

m2lp:   call strcmp
	je      fndm

	add     di, 1
	cmp     di, bx
	jl      m2lp

	mov     memval,02400000h        ; memory value not set--use 35MB total.
	jmp     doload

fndm:   add     di,2            ; Found "-m".  Now look for a number
	cmp     di,bx           ; (Make sure it's not end of line)
	jnl     nogoodm

ok1:
	mov     edx, 0          ; Holds the memory-requirement value
	mov     ax,0            ; holds characters as we read

	;************************************************
	;*  Skip over spaces/tabs before any number     *
	;************************************************
skiplp:
	mov     al, es:[di]
	inc     di
	cmp     al, 20h         ; spaces
	je      skiplp
	cmp     al,  09h        ; tabs
	je      skiplp
	cmp     di,bx           ; make sure we're still in the string
	jle     cnvst           ; Yup, we've got the first char, so enter
				; the conversion loop part-way down.

nogoodm:
	prints  nominfo         ; no arg to -m, or it's bad; Punt.
	kill

	;********************************************************
	;   Convert the numeric argument to -m; result in edx.  *
	;********************************************************
cnvlp:  mov     al,es:[di]
	add     di, 1
cnvst:  cmp     al, 30h
	jl      endcnv
	cmp     al, 39h
	jg      endcnv
	sub     al, 30h
	imul    dx, 10
	add     dx, ax
	jmp     cnvlp

endcnv:
	cmp     edx,0           ; if still 0, no valid chars!
	je      nogoodm
	cmp     edx, 8          ; must be in the range [8, 32]
	jl      nogoodm
	cmp     edx,64
	jg      nogoodm

	add     edx, 3          ; add 3mb for data areas, etc, and
	sal     edx, 20         ; convert to megabytes
	mov     memval, edx     ; save memory requested

	;************************************************
	;*  Load the real emulator .EXE file, emul.exe  *
	;************************************************
doload: mov     dx, OFFSET emulpath
	mov     ax, seg envseg
	mov     es, ax
	mov     bx, OFFSET envseg
	mov     ax,4b01h        ; load-don't-start
	int 21h
	jnc     loadok

	add     ax,ax
	mov     si,ax
	prints  noload
	mov     bx,OFFSET errtbl
	mov     dx,ds:[bx+si]
	mov     ah,9
	int 21h
	kill

loadok:                         ; Load succeeded.
	mov     ah,51h          ; get PSP address for child
	int     21h
	mov     es, bx          ; get segment for DI addressing

;       mov     cx,128          ; copy the command line tail
;       mov     di,80h          ; (which appears to be flaky in DOS 4)
;       mov     si, offset cmdline
;       rep
;       movsb

	mov     eax,retad
	mov     dword ptr es:[+0ah], eax        ; set up return address.

	cmp     memval, 0       ; If no -m value given, just
	je      dorun           ; go start the emulator.

	mov     di,0            ; Search for the Intel Extender's PROFILE
	mov     si, OFFSET profile      ; (see extender.h)
	mov     cx, 3           ; (length is 3 bytes)

srchlp: call    strcmp
	je      gotprof         ; found the profile; fix it.
	add     di, 1
	cmp     di, 2048
	jle     srchlp

	prints  badexe          ; No extender profile, so the emulator
	kill                    ; EXE must be corrupt.  Punt.

gotprof:
	mov     eax,memval              ; Fill in the memory requirement.
	mov     es:[di+1bch], eax

;********************************************************
;*                                                      *
;*      Set up the stack seg/pointer & start medley.    *
;*                                                      *
;********************************************************
dorun:  lss     sp,stk          ; load stack SS & SP regs
	mov     ax, es          ; copy PSP ptr to ax & ds, since some
	mov     bx, ds          ; code expects it in both places.
	mov     fs,bx           ; Also, copy DS to FS, so we still have
	mov     ds,ax           ; a base for the indirect jump . . .
	jmp     fs:[csip]       ; to start-of-medley.

myret:  kill                    ; we get back here, so quit gracefully.

main    endp



;************************************************************************/
;*                                                                      */
;*                              s t r c m p                             */
;*                                                                      */
;*      Compare [ds]di and es:[si] for (CX) characters.  If the         */
;*      strings are equal, the Zero flag is set when this returns.      */
;*                                                                      */
;*      All registers are preserved.                                    */
;*                                                                      */
;************************************************************************/

strcmp  proc    near
	cld
	push di
	push si
	push cx

	repe
	cmpsb

	pop     cx
	pop     si
	pop     di
	ret
strcmp  endp

END
