; SHELL.ASM ; Copyright 1992, Alfred J. Heyman and Spectrum Research, Inc. .286P public _shell, _hookup, _swapvects, _storevects, _acadshell public _save_psp, _save_dta, _new_dta, _restore_dta, _shelldir public _new_psp, _restore_psp, _saveblocks, _save_cur_blks public _rest_old_blks, _rest_cur_blks, _program, _cmdline, _acadname public _write_swap, _read_swap, _install23, _install24, _lockname public _runname, _swapfile, _adr_afus, _cadr_afus, _shutdown public _swap_open, _swap_reopen, _swap_close, _swap_reset, _swap_zap public _setretry, _clrretry, _malloc256, _rollout, _rollin, _clear_cmdln public _getakey, _get_retcode, _install15, _uninstall15, _fin public _f88_i15, _geti21, _ts_enable, _clr_tskip, _biggestl public _detect, _hook19, _unhook19, _cli, _sti, _nmi public _file_handle, _release_all, _enable_a20, _restore_ps2r public _ems_open, _ems_close, _emm_load_flag,_emm_loaded, _emm_use_flag public _gen_swapname, _test_acadl, _botmsg, _copyright2, _thisprog public _run_acad, _get_box_id, _machine, _getenva, _get_run_name public __acrtused, __anchkstk, _stub, _psp_ascii, _orig_psp, _get_psp extrn _main: proc extrn _exec: proc extrn _clearwindow: proc extrn _gotoxy: proc extrn _setcolor: proc extrn _sprintstr: proc extrn _abortmsg: far extrn _FNAMEX: far extrn _EXTX: far ;--------------; ; DEFINITIONS ; ;--------------; DOSCALL MACRO CALL DOS ;Call dos far. ENDM BREAK MACRO IF1 %OUT Hard Break Inserted ENDIF INT 2 ENDM .MODEL compact .DATA stack db 64 dup ("*STACK**") ;64*8=512 endstack dw 0 ostacko dw 0 ;Stack pointers. ostacks dw 0 aostacko dw 0 ;Stack pointers. aostacks dw 0 o01o dw 0 o01s dw 0 o03o dw 0 o03s dw 0 o21o dw 0 ;Old interrupt 21 offset o21s dw 0 orig_dtao dw 0 ;Original DTA orig_dtas dw 0 _orig_psp dw 0 ;Original PSP old_dtao dw 0 old_dtas dw 0 old_psp dw 0 ts_ss dw 0 ;Storage for registers during stack switch. ts_sp dw 0 ;-------------- envseg dw 0 ;Parameter block passed to EXEC. cmdoff dw 80h cmdseg dw 0 fcb1ofs dw 5ch fcb1seg dw 0 fcb2ofs dw 6ch fcb2seg dw 0 ;-------------- exspace db "BIGSHELL=" ems_name db "BSHL" _psp_ascii db " ",0,0 retry db 0 tripskip dw 1 fattributes dw 0 bs_ds dw 0 ;Data segment of bigshell C code. bs_es dw 0 ;Extra segment of bigshell C code. writetop dw 0 writestart dw 0 mcbtype db 0 ;4D or 5A. ;---------------------------------------------------------------------- ; These memory allocation blocks are stored as they were ; when we were first loaded. (Before AutoCAD was executed). ;---------------------------------------------------------------------- blk_b4us db 16 dup (0) ;Copy of block before us. adr_b4us dw 0 ;Segment Address of block before us. blk_afus db 16 dup (0) ;Copy of block after us. _adr_afus dw 0 ;Segment address of block after us. ;---------------------------------------------------------------------- ; These memory allocation blocks are stored as they exist ; when autocad tries to shell out. ;---------------------------------------------------------------------- cadr_b4us dw 0 ;Segment Address of block before us. cblk_b4us db 16 dup (0) ;Copy of block before us. _machine dw 0 ;11h=Vectra. 20h=PS2. _cadr_afus dw 0 ;Segment address of block after us. cblk_afus db 16 dup (0) ;Copy of block after us. memtop dw 0a000h _file_handle dw 0ffffh ;Dos Handle for swap file. _cmdline db 80h dup (0) ;buffer for command line. _thisprog db 80 dup (0) ;This program. _program db 80 dup (0) ;Name of program to run. _runname db 80 dup (0) ;Program run name. _shelldir db 80 dup (0) ;Swap Shell directory. _swapfile db 80 dup (0) ;Swap file name. _acadname db 28 dup (0) ;Name of ACAD to run. errexx db "ERROR: EXECUTION FAILED",0 executing db "EXECUTING: ",0 _lockname db 80 dup (0) ;Name of lock file. locksize dw 0 ;Size of lock file. gdt db 6 dup (0) idt db 6 dup (0) ;EMS 4.0 Function 24, Move/Exchange Memory Region. db "EMM_TABLE" _biggestl dw 0 _biggesth dw 0 _swap_size_l dw 0 ;Biggest EMS size used. _swap_size_h dw 0 region_len_l dw 0 ;Length of Memory Region to move. region_len_h dw 0 Src_mem_type db 0 ;Memory Type, 0=Conventional, 1=EMS. src_handle dw 0 ;Handle Number, 0=N/A (Conventional Memory). src_init_ofs dw 0 ;Source Memory Initial Offset. src_init_seg dw 0 ;Source Memory Initial Segment or page. dest_mem_type db 0 ;Destination Memory Type, 0=Conventional, 1=EMS. dest_handle dw 0 ;Destination Memory Handle. 0=N/A (Conventional). dest_init_ofs dw 0 ;Destination Memory Offset. dest_init_seg dw 0 ;Destination Memory Segment or page. ems_handle dw 0 ;Handle of EMM memory that we use here. ems_offset dw 0 ;Current offset into 16K EMM page. ems_segment dw 0 ;Current page into 16K EMM page. ems_start_pgf dw 0 ;Number of initial paragraphs allocated. _emm_load_flag dw 0 ;0=Not Loaded, 1=Loaded. _emm_use_flag dw 0 ;0=Dont Use, 1=Do Use. ;---------------------------------------------------------------------- .CODE ;---------------------------------------------------------------------- DB 64 dup ("*ISTACK*") i_stack: _vector_table: db 1024 dup (0) ;Interrupt vector table. esize dw 0 ;Stored amount of extended memory avail. o15o dw 0 ;Offset to old INT 15 handler. o15s dw 0 test_int db 0 ;Temporary var. ;revectored dw 0 ;0=Normal 8259 IRQ vectors. clock1 dw 0 ;Timer tick clock. clock2 dw 0 ;NEW tick clock. release_all db 0 ;1=TenMenu product. downflag db 0 ;1=Last run through mem release code. psp256 dw 0 ;Segment of malloced 256 bytes for PHAR-PSP. psp256loc dw 0 errorlevel dw 0 ;Storage for shell programs error level. ;o08o dw 0 ;Old Int 08 Handler. ;o08s dw 0 ;n08o dw 0 ;New Int 08 Handler. ;n08s dw 0 ;------------------------------------------------------------------ ;_strcpy proc ; push bp ; mov bp,sp ; pop bp ; ret ;_strcpy endp ;;------------------------------------------------------------------ ;_strcmp proc ; push bp ; mov bp,sp ; pop bp ; ret ;_strcmp endp ;------------------------------------------------------------------ ; This routine allocates a small STUBBY memory block. ; This was needed because the "C" version allocated one. ; The ASM version logic would need to be changed if this didn't exist! ;------------------------------------------------------------------ _stub proc mov ah,48h mov bx,1 int 21h ret _stub endp ;------------------------------------------------------------------ _nmi proc int 2 ret _nmi endp ;------------------------------------------------------------------ __acrtused proc ret __acrtused endp ;------------------------------------------------------------------ __anchkstk proc ret __anchkstk endp ;------------------------------------------------------------------ _enable_a20 proc CALL AAHEnable ret _enable_a20 endp ;---------------------------------------------------------------------- PS2_PORTA equ 0092h PS2_A20BIT equ 00000010b _restore_ps2r proc in al,PS2_PORTA ;Get PS2 A20 line value. test al,PS2_A20BIT ;Test A20 line. jnz rpx ;Jump out if on already. or al,PS2_PORTA ;Set A20 on. out PS2_PORTA,al ;Turn on PS2 A20 Line. xor cx,cx rp1: in al,PS2_PORTA test al,PS2_A20BIT loopz rp1 rpx: ret _restore_ps2r endp ;*--------------------------------------------------------------------------* ;* * ;* AT_A20Handler - HARDWARE DEP. * ;* * ;* Enable/Disable the A20 line on non-PS/2 machines * ;* * ;* ARGS: AX = 0 for Disable, 1 for Enable * ;* RETS: AX = 1 for success, 0 otherwise * ;* REGS: AX, CX and Flags clobbered * ;* * ;*--------------------------------------------------------------------------* AT_A20Handler proc AAHEnable: call Sync8042 ; Make sure the Keyboard Controller is Ready jnz short AAHErr mov al,0D1h ; Send D1h out 64h,al call Sync8042 jnz short AAHErr mov al,0DFh ; Send DFh out 60h,al call Sync8042 jnz short AAHErr ; Wait for the A20 line to settle down (up to 20usecs) mov al,0FFh ; Send FFh (Pulse Output Port NULL) out 64h,al call Sync8042 AAHExit: AAHErr: ret AT_A20Handler endp ;*--------------------------------------------------------------------------* Sync8042 proc xor cx,cx S8InSync: in al,64h and al,2 loopnz S8InSync ret Sync8042 endp ;---------------------------------------------------------------------- _fin proc push bp mov bp,sp mov ax,[bp+4] ;Get error level. mov ah,4ch call dos pop bp ret _fin endp ;---------------------------------------------------------------------- _release_all proc mov cs:release_all,1 ret _release_all endp ;---------------------------------------------------------------------- _cli proc cli ret _cli endp ;---------------------------------------------------------------------- _sti proc sti ret _sti endp ;---------------------------------------------------------------------- _malloc256 proc mov ah,48h ;Malloc. mov bx,10h ;256 bytes. int 21h ;Call DOS. mov cs:psp256,ax ;Save the pointer. mov cs:psp256loc,ax ;Save the location. ret _malloc256 endp ;---------------------------------------------------------------------- _save_cur_blks proc push ds push es mov bx,adr_b4us ;Get block address before us. mov cadr_b4us,bx ;Store address push ds pop es mov ds,bx xor si,si ;ES:DI point to storage. lea di,cblk_b4us ;DS:SI point to block. mov cx,16 ;Store 16 bytes cld rep movsb add bx,ds:[0003] ;Add in memory used by our block. inc bx ;Add in size of block. mov ds,bx xor si,si ;DS:SI points to block after us. lea di,_cadr_afus mov es:[di],bx ;Store segment address of block after us. lea di,cblk_afus ;ES:DI points to storage. mov cx,16 rep movsb pop es pop ds ret _save_cur_blks endp ;---------------------------------------------------------------------- ; Converted from C code. ; ; ; gen_swapname() ; { if(shelldir != NULL) ; { strcpy(swapfile,shelldir); ; if(swapfile[strlen(swapfile)]!='\\') ; { strcat(swapfile,"\\"); }; ; }; ; _splitpath(swapfile,drive,dir,fname,ext); ; strcpy(fname,""); strcpy(ext,""); ; _makepath(swapfile,drive,dir,fname,ext); ; }; ; ; If SHELLDIR has anything in it, it is the SHELL_SWAP environment parm. ; If so, copy the SHELLDIR to SWAPFILE. ; ; If Not, Swapfile contains the executable file name of the program. ; Zap the filename and extension. ;---------------------------------------------------------------------- _GEN_SWAPNAME PROC push si push di push es mov si,ds mov es,si lea si,_shelldir lea di,_swapfile mov al,[si] ;Look at first character in shelldir. or al,al ;Set flags. jz dirnull ;Jump if string is NULL. cld ;Clear direction flag. mov cx,80 ;Copy shelldir to swapfile. rep movsb lea si,_swapfile ;Point back at destination. mov cx,80 ;Look through 80 characters max. xor ax,ax ;Clear AX. findnd: mov ah,al ;Save previous character loaded. mov al,[si] ;Get current character. inc si ;point at next. or al,al ;Test for ZERO. loopnz findnd ;Loop up again if NOT ZERO. dec si ;Point back at last character. cmp ah,"\" ;Is last character SLASH? jz dirnull ;Yes? Jump over. mov al,'\' ;Copy "\" and terminate string. xor ah,ah ;Clear AH. mov [si],ax jmp genx ;Finished. ;Execution here means that SWAPFILE=C:\ACAD\ACAD.EXE or similar. dirnull: mov cx,80 ;Look through 80 characters MAX. lea si,_swapfile ;Point at swap file. findnx: mov al,[si] ;Get current character. inc si ;point at next. or al,al ;Test for ZERO. loopnz findnx ;Loop up again if NOT ZERO. sub si,2 ;Point at last character. mov cx,80 xor ah,ah zapnxt: mov al,[si] ;Get last character. cmp al,"\" ;Is it a slash? jz genx ;Yes? Jump out. mov [si],ah ;ZAP the character. dec si ;Point at previous. loop zapnxt ;Loop back and look at another. genx: pop es pop di pop si ret _GEN_SWAPNAME ENDP ;---------------------------------------------------------------------- ; Converted From C. ; ;test_acadl() ; { _splitpath(program,drive,dir,fname,ext); ; strupr(ext); ; if(strcmp(ext,".EXE")==0) { return(0); }; ; if(strcmp(ext,".COM")==0) { return(0); }; ; return(-1); ; }; ;---------------------------------------------------------------------- _TEST_ACADL PROC PUSH SI PUSH DI lea si,_program mov cx,80 ;Look through 80 characters MAX. findnl: mov al,[si] ;Get current character. inc si ;point at next. or al,al ;Test for ZERO. loopnz findnl ;Loop up again if NOT ZERO. sub si,3 ;Point at last character. mov ax,[si] ;Get eXE or cOM. or ax,2020h ;Make lower case. cmp ax,"ex" ;Is it EXE? jz xorc ;Yes? Jump. cmp ax,"mo" ;Is it COM? jz xorc ;Yes? Jump. mov ax,0ffffh ;No? Return -1. jmp nxorc xorc: xor ax,ax ;Return 0. nxorc: POP DI POP SI RET _TEST_ACADL ENDP ;---------------------------------------------------------------------- ; Converted From C. ; ; botmsg(msgx) ; char msgx[]; ; { clearwindow(0,22,79,22,0x70); ; gotoxy(0,22); ; setcolor(0x70); ; sprintstr(msgx); ; setcolor(7); ; gotoxy(0,23); ; }; ; ; ;---------------------------------------------------------------------- _BOTMSG PROC push bp mov bp,sp push 70h ;Clearwindow(0,22,79,22,0x70); push 22 push 79 push 22 push 0 call _clearwindow push 22 ;Gotoxy(0,22); push 0 call _gotoxy push 70h call _setcolor ;Setcolor(0x70); push ds mov ax,[bp+4] push ax call _sprintstr push 7 ;Setcolor(0x70); call _setcolor push 23 ;Gotoxy(0,23); push 0 call _gotoxy add sp,26 ;Correct the stack. pop bp ret _BOTMSG ENDP ;---------------------------------------------------------------------- ; Converted From C. ; ; copyright2() ; { int retcode; ; strcpy(runname,thisprog); ; _splitpath(runname,drive,dir,fname,ext); /* Generate path to AutoCAD */ ; strcpy(fname,FNAMEX); ; strcpy(ext,EXTX); ; _makepath(runname,drive,dir,fname,ext); ; ; if(shell() == -1) { botmsg(abortmsg); }; ; ; retcode = get_retcode() & 255; ; if(retcode == 241) ; { release_all(); ; retcode--; ; }; ; if(retcode != 240) { return(-1); }; ; return(0); ; }; ;---------------------------------------------------------------------- _COPYRIGHT2 proc push bp mov bp,sp push es mov ax,ds mov es,ax lea si,_thisprog ;STRCPY(runname,thisprog); lea di,_runname mov cx,80 cld rep movsb lea di,_runname ;Find end of RUNNAME. mov cx,80 ;Look through 80 characters MAX. xor al,al cld repnz scasb sub di,2 ;Point at last character. std ;find the "\" mov al,"\" mov cx,13 repnz scasb add di,2 cld lea si,_FNAMEX ;Copy FNAMEX into place (10MENU or BSHELL). mov cx,6 rep movsb mov al,"." ;Copy a period before extension. stosb lea si,_EXTX ;Copy the extension. mov cx,4 rep movsb call _shell ;do the shell. cmp ax,-1 ;Error? jnz getret ;No? Jump over error print. lea si,_abortmsg ;Point at abort message. push ds push si call _botmsg pop si pop ds getret: call _get_retcode ;Get return code. xor ah,ah ;Zap the upper part. cmp ax,241 ;Does AX=252? jnz cmp251 ;No? Jump over. call _release_all ;Release. dec ax ;Set up for no error. cmp251: cmp ax,240 ;Is retcode equal to 251? jz zapax ;Yes? OK... Jump out and clear. mov ax,-1 ;No? Signal Error. jmp c2x ;Jump out... set to -1. zapax: xor ax,ax ;Clear jmp c2x c2x: pop es pop bp ret _COPYRIGHT2 endp ;---------------------------------------------------------------------- ; getenva("PATH=",&storage); ;---------------------------------------------------------------------- _getenva proc push bp mov bp,sp push ds push es mov ds,[bp+10] ;Get data segment. mov si,[bp+8] ;Get pointer to parameter to use. ;DS:SI points to parm to look for. mov ah,51h int 21h ;Get PSP in BX. mov es,bx ;Switch to PSP segment. mov bx,[es:2ch] ;Get ENV segment. mov es,bx ;Switch to environment segment. xor di,di ;ES:DI point to first environment parm. push di push si cld cmpagn: mov al,[si] ;Get a byte from the sample. or al,al ;Was this the last byte of sample? jz gdenv ;Yes? Jump out. cmpsb ;Compare the first bytes. jz cmpagn ;Compare another byte if same. ;------- nxtep: pop si ;Get SI off of the stack. push si ;Save it up there again. fndnx: inc di ;Point to next character in env string. mov ax,es:[di-1] ;Get word pointed to by ES:DI. or ax,ax ;End of environment? jz gexbad ;Yes? Jump out. or al,al ;End of environment string? jnz fndnx ;Loop up. Get next. jmp cmpagn ;Jump up to restart search on next var. ;------- gdenv: pop si ;ES:DI points to parameter data. pop si mov si,[bp+4] ;Get destination pointer. mov ds,[bp+6] mov [si],di ;Store destination address. mov [si+2],es ;Store destination segment (COMPACT MODE). jmp gex ;------- gexbad: pop si pop si gex: pop es pop ds pop bp ret _getenva endp ;---------------------------------------------------------------------- _get_run_name proc push ds push es mov ax,ds mov es,ax mov ah,51h int 21h ;Get PSP in BX. mov ds,bx ;Switch to PSP segment. mov bx,[ds:2ch] ;Get ENV segment. mov ds,bx ;Switch to environment segment. mov si,0ffffh ;ES:DI point to first environment parm. grn: inc si ;Increment environment pointer. cmp word ptr [si],0 ;Look for end of environment. jnz grn ;End? No? Jump up again. add si,4 ;Point to run name. cld ;DS:SI points to source. lea di,_thisprog ;ES:DI points to destination. mov cx,80 ;Transfer 80 characters. rep movsb ;Move um now. pop es pop ds ret _get_run_name endp ;---------------------------------------------------------------------- ; Converted From C. ; ;---------------------------------------------------------------------- ;run_acad() ; { setcolor(0x70); ; gotoxy(0,21); ; clearwindow(0,21,79,21,0x70); ; sprintstr(" EXECUTING: "); ; sprintstr(runname); ; gotoxy(0,24); ; ; if(shell() == -1) /* Run ACAD.EXE */ ; { clearwindow(0,22,79,22,0x70); ; gotoxy(1,22); ; setcolor(0x70); ; sprintstr("ERROR: EXECUTION FAILED"); ; gotoxy(0,23); ; }; ; }; ;---------------------------------------------------------------------- _RUN_ACAD PROC push bp push 70h call _setcolor push 21 push 0 call _gotoxy push 70h push 21 push 79 push 21 push 0 call _clearwindow push ds lea ax,executing push ax call _sprintstr push ds lea ax,_runname push ax call _sprintstr push 24 push 0 call _gotoxy add sp,28 ;Correct the stack. call _shell cmp ax,-1 jnz rax push 70h push 22 push 79 push 22 push 0 call _clearwindow push 22 push 1 call _gotoxy push 70h call _setcolor push ds lea ax,errexx push ax call _sprintstr push 23 push 0 call _gotoxy add sp,24 ;Correct the stack. rax: pop bp ret _RUN_ACAD ENDP ;---------------------------------------------------------------------- ; Converted From C. ; ; struct system_desc ; { int size; ; char model; ; char submodel; ; char bios_release; ; char features; ; } far *sys_desc; ; ; get_box_id() ; { inregs.h.ah=0xc0; ; int86x(0x15,&inregs,&outregs,&segregs); ; ; FP_SEG(sys_desc)=segregs.es; ; FP_OFF(sys_desc)=outregs.x.bx; ; ; FP_SEG(hpid)=0xf000; ; FP_OFF(hpid)=0x00f8; ; ; if((sys_desc->features & 2)==2) { machine = 0x20; }; /* Must be a PS2 */ ; if(*hpid==0x5048) { machine = 0x11; }; ; }; ;---------------------------------------------------------------------- _GET_BOX_ID PROC PUSH ES ;Save ES. PUSH DS ;UnNeeded, but what the hell. PUSHF ;Some Compaqs leave interrupts OFF here. MOV AH,0C0H INT 15h POPF POP DS mov al,es:[bx+5] ;Get Computer's Feature byte. and al,2 ;And it. Test for microchannel? jz test4hp mov ax,20h ;Mark as a PS2. mov _machine,ax jmp gbix test4hp:mov ax,0f000h ;Load segment of HP mark. mov es,ax mov bx,00f8h ;Load offset of HP mark. mov ax,es:[bx] ;Get HP byte. cmp ax,5048h ;Test for HP. jnz gbix ;Jump if no HP. mov ax,11h ;Mark machine as HP. mov _machine,ax gbix: POP ES RET _GET_BOX_ID ENDP ;---------------------------------------------------------------------- COMMENT* _rest_old_blks proc push ds push es cli mov es,_adr_afus ;Get address of block that was after us. xor di,di ;ES:DI point to destination. lea si,blk_afus ;DS:SI point to stored block. cld mov cx,16 rep movsb mov es,adr_b4us ;Get address of block that was before us. xor di,di ;ES:DI point to destination. lea si,blk_b4us ;DS:SI point to stored block. cld mov cx,16 rep movsb sti pop es pop ds ret _rest_old_blks endp * ;---------------------------------------------------------------------- _shutdown proc mov cs:downflag,1 ret _shutdown endp ;---------------------------------------------------------------------- _rest_old_blks proc push ax push bx push cx push dx push ds push es mov ah,51h int 21h ;Call Dos. Get PSP in BX. robl: call nextblock robn: or cx,cx ;FREE memory, or tied to a PSP? CX=0 if Free. jz robx cmp cx,adr_b4us jc robx push es push dx push cx push bx push ax cmp cs:downflag,1 ;1=Final call to routine. jz sdj cmp cs:release_all,1 ;1=Release all memory above us. jz sdj push ds mov ds,bx cmp word ptr ds:[0],20cdh ;are first two bytes CD 20? pop ds jnz sdj ;Not a psp? Then Jump over. mov es,bx mov ah,4ah mov bx,8 int 21h ;Resize PSP to 128 bytes. jmp isx ;--------- sdj: mov es,bx mov ah,49h ;Free Allocated memory. int 21h ;Call DOS. jmp isx ;--------- isx: pop ax pop bx pop cx pop dx pop es robx: cmp al,5Ah jnz robl pop es pop ds pop dx pop cx pop bx pop ax ret _rest_old_blks endp ;---------------------------------------------------------------------- nextblock proc push es dec bx mov es,bx inc bx ;BX points at current block. add bx,word ptr es:[3] ;Add in size of block. mov es,bx mov al,byte ptr es:[0] ; AL = Type (4D or 5A). inc bx ; BX = Data Address. mov cx,word ptr es:[1] ; CX = PSP. mov dx,word ptr es:[3] ; DX = Size. pop es ret nextblock endp ;---------------------------------------------------------------------- _rest_cur_blks proc push ds push es cli mov es,_cadr_afus ;Get address of block that was after us. xor di,di ;ES:DI point to destination. lea si,cblk_afus ;DS:SI point to stored block. cld mov cx,16 rep movsb mov es,cadr_b4us ;Get address of block that was before us. xor di,di ;ES:DI point to destination. lea si,cblk_b4us ;DS:SI point to stored block. cld mov cx,16 rep movsb sti pop es pop ds ret _rest_cur_blks endp ;-------------------------------------------------------------------------- _getakey proc xor ax,ax int 16h ret _getakey endp ;-------------------------------------------------------------------------- dos proc pushf cli call dword ptr cs:o21o ret dos endp ;-------------------------------------------------------------------------- _get_retcode proc mov ah,4dh call dos ret _get_retcode endp ;-------------------------------------------------------------------------- _f88_i15 proc mov ah,88h pushf ;Protect against ints being turned off. push ds int 15h pop ds popf mov cs:esize,ax ret _f88_i15 endp ;-------------------------------------------------------------------------- _get_psp proc mov ah,51h int 21h mov _orig_psp,bx ;Save the original PSP ret _get_psp endp ;-------------------------------------------------------------------------- _hookup proc push ds push es call _get_psp mov ah,2fh int 21h mov orig_dtao,bx ;Save original DTA mov orig_dtas,es mov ax,3521h ;Store vector to INT 21. int 21h mov o21o,bx mov o21s,es mov ax,3501h ;Store vector to INT 01 int 21h mov o01o,bx mov o01s,es mov ax,3503h ;Store vector to INT 03 int 21h mov o03o,bx mov o03s,es ;; mov ax,3508h ;Store vector to INT 08 ;; int 21h ;; mov cs:o08o,bx ;; mov cs:o08s,es mov ax,cs mov ds,ax mov dx,offset INT21 ;Hook up to INT 21 mov ax,2521h int 21h ;;; mov dx,offset INT08 ;Hook up to INT 08 ;;; mov ax,2508h ;;; int 21h pop es pop ds ret _hookup endp ;-------------------------------------------------------------------------- _clear_cmdln proc push si push ds push ax push bx mov ah,51h call dos ;Get PSP in BX. mov ds,bx mov si,81h mov cl,ds:[80h] and cx,00ffh jz ccmx ccloop: mov ax,[si] cmp ax,"p/" ;Clear ACS /P function. jz ccsmack cmp ax,"P/" jz ccsmack cmp ax,"R/" ;Used to determint if we need to free jz ccsmack ;TSRLOAD memory. cmp ax,"r/" jz ccsmack cmp ax,"9/" ;Clear ACS /9 function. jnz ccnmack ccsmack: mov word ptr [si],2020h ccnmack: inc si loop ccloop ccmx: pop bx pop ax pop ds pop si ret _clear_cmdln endp ;-------------------------------------------------------------------------- _ts_enable proc mov tripskip,0 ;Set initial trip skip. ret _ts_enable endp ;-------------------------------------------------------------------------- _geti21 proc push es mov ax,3521h ;Store vector to INT 21. int 21h mov o21o,bx mov o21s,es pop es ret _geti21 endp ;-------------------------------------------------------------------------- _install15 proc push ds push es mov ax,3515h ;Store vector to INT 15. int 21h mov cs:o15o,bx mov cs:o15s,es mov ax,cs mov ds,ax mov dx,offset INT15 ;Hook up to INT 15. mov ax,2515h int 21h pop es pop ds ret _install15 endp ;-------------------------------------------------------------------------- _uninstall15 proc push ds mov dx,cs:o15o mov ds,cs:o15s mov ax,2515h int 21h pop ds ret _uninstall15 endp ;-------------------------------------------------------------------------- _setretry proc mov cs:retry,1 ret _setretry endp ;-------------------------------------------------------------------------- _clrretry proc mov cs:retry,0 ret _clrretry endp ;-------------------------------------------------------------------------- _clr_tskip proc mov cs:tripskip,0 ret _clr_tskip endp ;-------------------------------------------------------------------------- ; This routine swaps stored values with those in vector table. ;-------------------------------------------------------------------------- _swapvects proc push ds push es push si push di push cx push bx xor ax,ax mov ds,ax mov si,ax ;ES:DI ->vector table. mov ax,cs mov es,ax mov di,offset _vector_table ;DS:SI ->0:0 mov cx,16h ;Swap vectors 00 - 0A. call swaploop add si,8 ;Skip vectors 0B & 0C. add di,8 mov cx,4 call swaploop ;Swap vectors 0D & 0E. add si,4 ;Skip vector 0F. add di,4 mov cx,200h - 20h ;Swap vectors 10 - FF. call swaploop ; mov cx,200h - 12h - 2 ; call swaploop ; ; add si,20h ;Swap vectors after INT 08. ; add di,20h ; mov cx,512 - 20h ; call swaploop ;;; cmp cs:revectored,0 ;Is phar lap running? ;;; jz no_revect ;;; call swap8 no_revect: pop bx pop cx pop di pop si pop es pop ds ret _swapvects endp swaploop: mov ax,ds:[si] ;Get data. mov bx,es:[di] mov ds:[si],bx mov es:[di],ax ;Swap data. inc si inc si ;Inc pointers. inc di inc di loop swaploop ;Loop up. ret ;----------------------------------------------------------------------------- _save_psp proc mov ah,51h ;Get current PSP. int 21h mov old_psp,bx ret _save_psp endp ;----------------------------------------------------------------------------- _save_dta proc push es mov ah,2fh int 21h ;Get current DTA. mov old_dtao,bx ;Save DTA. mov old_dtas,es pop es ret _save_dta endp ;----------------------------------------------------------------------------- _new_dta proc push ds mov ds,orig_dtas mov dx,orig_dtao ;Set DTA to us. mov ah,1ah int 21h pop ds ret _new_dta endp ;----------------------------------------------------------------------------- _new_psp proc mov bx,_orig_psp mov ah,50h int 21h ret _new_psp endp ;----------------------------------------------------------------------------- _restore_dta proc push ds mov dx,old_dtao mov ds,old_dtas mov ah,1ah int 21h pop ds ret _restore_dta endp ;----------------------------------------------------------------------------- _restore_psp proc mov bx,old_psp mov ah,50h int 21h ret _restore_psp endp ;----------------------------------------------------------------------------- _rollout proc ro_top: call _swap_open ;Open or create swap file. Handle in AX. mov _file_handle,ax ;Store file handle. call _write_swap ;Write the swap file to disk. cmp ax,0ffffh ;Did write fail? jnz ronxit ;No?, then return 0. cmp _emm_use_flag,1 ;Were we trying to use Expanded Memory? jnz roxit ;No? Then signal error. Return AX=FFFF. call _ems_close ;Close out EMS handle. mov _emm_use_flag,0 ;Signal NO EMS usage. call revert ;Signal that we are reverting to file. jmp ro_top ;Try again. roxit: ret ;Take file handle off of stack. ;--------------- ronxit: xor ax,ax ret _rollout endp ;----------------------------------------------------------------------------- revert proc push ds push dx push ax mov ax,cs mov ds,ax mov dx,offset revmsg mov ah,9 int 21h pop ax pop dx pop ds ret revmsg: db 7,0dh,0ah,"OUT OF EMS! SWITCHING TO DISK",0dh,0ah,7,"$" revert endp ;----------------------------------------------------------------------------- _rollin proc mov ax,_file_handle ;Get file handle. call _swap_reset ;Reset handle or ems. Stack has handle. call _read_swap ;Read in swap file. Stack has handle. cmp ax,0ffffh ;-1=Failed. jz rix ;Did it fail? Jump if -1. call _swap_reset ;Reset file or EMS pointer again. call _swap_zap ;Zap handle on stack. call _swap_close ;Close handle on stack. push ds ;Push segment of swapfile name. lea ax,_swapfile push ax ;Push offset of swapfile name. call _unlink ;Erase swapfile. add sp,4 ;adjust stack. xor ax,ax rix: ret ;Return and POP handle off of stack. _rollin endp ;----------------------------------------------------------------------------- _unlink proc push bp mov bp,sp push ds push dx mov ds,[bp+6] mov dx,[bp+4] ;DS:DX points to filename. mov ah,41h ;Delete the file. call dos ;Call DOS. pop dx pop ds pop bp ret _unlink endp ;----------------------------------------------------------------------------- _write_swap proc mov bx,_file_handle ;Get file handle from storage. mov di,_cadr_afus ;Move starting address to buffer. mov writestart,di mov _swap_size_l,0 ;Clear previous swap size. mov _swap_size_h,0 next_mcb: push es mov es,di ;DI holds segment of next write. mov si,di mov di,es:[0003] ;Move top to buffer mov cx,es:[0001] ;CX has owner. mov al,es:[0000] ;Get MCB type. inc di pop es add di,si mov writetop,di mov mcbtype,al or cx,cx ;0000=Free. jnz wsnorm ;Not 0000? Then Write Normally. call w_writestart ;Write segment to file. inc writestart call w_writestart ;Write the top to file. dec writestart push ds ;Write the memory block to disk. mov ds,writestart mov dx,0 mov cx,16 mov ah,40h call read_write ;Call DOS/EMM read write function. pop ds jc wsex ;CY=Error. Jump out. jmp wsnowrite ;Jump over data write. wsnorm: call w_writestart ;Write the segment to the file. jc wsex ;CY=Error. call w_writetop ;Write the top to the file. jc wsex ;CY=Error. call w_data ;Write the data now. jc wsex wsnowrite: mov di,writetop mov writestart,di cmp mcbtype,5Ah ;Was it the final MCB? jz ws1x ;Yes? Then Jump out. jmp next_mcb wsex: mov ax,0ffffh ret ws1x: mov writestart,0 ;****TEST**** call w_writestart ;****TEST**** call w_writestart ;****TEST**** ret _write_swap endp ;----------------------------------------------------------------------------- w_writestart: mov ah,40h ;Write the segment to the file. lea dx,writestart mov cx,2 call read_write ;Call DOS/EMM read/write function. ret ;----------------------------------------------------------------------------- w_writetop: mov ah,40h ;Write the top to the file. lea dx,writetop mov cx,2 call read_write ;Call DOS/EMM read/write function. ret ;----------------------------------------------------------------------------- accumulate: pushf push ds mov cx,dgroup mov ds,cx add _swap_size_l,ax ;Add bytes written to swap size. adc _swap_size_h,0 mov cx,_swap_size_h ;Get current swap size (high part). cmp _biggesth,cx ;Is it bigger than previous value? jz acxit0 ;Same? Jump to Compare low part. jc acxit3 ;Bigger? Jump to save new bigger value. jmp acxit2 ;Smaller? Jump and ignore values. acxit0: mov cx,_swap_size_l ;Get low part of current swap size. cmp _biggestl,cx ;Compare to previous saved value. jnc acxit2 ;Jump out if smaller. acxit3: mov cx,_swap_size_h ;Update biggest swap size used. mov _biggesth,cx mov cx,_swap_size_l mov _biggestl,cx acxit2: pop ds popf ret ;----------------------------------------------------------------------------- w_data: mov ah,40h ;DOS Write. mov si,writestart mov cx,writetop call readorwrite ret ;----------------------------------------------------------------------------- _read_swap proc mov bx,_file_handle ;Get dos file handle from storage. mov di,_cadr_afus ;Move starting address to buffer. mov writestart,di next_mcbr: mov ah,3fh mov cx,2 lea dx,writestart ;Get starting segment of write. call read_write ;Call DOS/EMM read/write function. jc rserror or ax,ax ;End of file? jz rsout ;Yes? Then jump out. cmp writestart,0 ;EMS End of Data? ****TEST**** jz rsout ; ****TEST**** mov ah,3fh mov cx,2 lea dx,writetop ;Get final read segment address. call read_write ;Call DOS/EMM read/write function. jc rserror or ax,ax ;End of file? jz rsout ;Yes? Then jump out. cmp writetop,0 ;EMS End of Data? ****TEST**** jz rsout ; ****TEST**** mov ah,3fh mov si,writestart mov cx,writetop call readorwrite ;Read in the data. jc rserror push es mov di,writestart ;Get segment of this MCB. mov es,di mov al,es:[0000] ;Get MCB type. pop es cmp al,5Ah ;Final one? jnz next_mcbr ;No? Jump to get another. rsout: clc ;Clear carry. ret ;Return to caller. rserror: mov ax,0ffffh ;Error condition. stc ;Set carry. ret _read_swap endp ;----------------------------------------------------------------------------- ;This function handles disk io. ; ; On Entry: ; ; AH=3F=Read ; 40=Write ; CX=Beginning SEG:0000 to write data from. ; SI=Number of paragraphs to write or read. ; ;----------------------------------------------------------------------------- readorwrite: push es push ds mov cs:writetop,cx mov cs:writestart,si rloop2: mov cx,cs:writetop sub cx,si ;DI = Pgphs from start to finish. cmp cx,4095 ;Compare number of paragraphs jc rrsw ;Number of pgfs in 64K-1. mov cx,4095 rrsw: mov ds,si xor dx,dx ;DS:DX points to data. add si,cx ;SI points to next start. shl cx,1 shl cx,1 shl cx,1 shl cx,1 ;CX holds bytes to read. or cx,cx ;Any data to write? jz none2writ push ax call read_write ;Handle dos/emm read/write. mov di,ax pop ax jc rswx none2writ: cmp di,cx ;Fewer than attempt? jc rswx ;Yes? Then Abort. or cx,cx ;Compare to ZERO. jnz rloop2 clc rswx: pop ds pop es ret ;-------------------------------------------------------------------------- _swap_reopen proc lea dx,_swapfile mov ah,3dh ;Open File. mov al,82h ;Read,Write,NoInherit. call dos jc sobxx ;Jump out on error. ret ;Return. sobxx: mov ax,0ffffh ret _swap_reopen endp ;-------------------------------------------------------------------------- _swap_open proc cmp _emm_use_flag,1 ;Are we using Expanded Memory? jz sobx ;Yes? Jump out. lea dx,_swapfile mov ah,5ah ;Create the Unique swapfile. mov cx,0 call dos jc sobx ;Jump out on error. mov bx,ax mov ah,3eh ;Close the file. call dos lea dx,_swapfile mov ah,3dh ;Open File. mov al,82h ;Read,Write,NoInherit. call dos jc sobx ;Jump out on error. ret ;Return. sobx: mov ax,0ffffh ret _swap_open endp ;-------------------------------------------------------------------------- _swap_close proc cmp _emm_use_flag,1 ;Are we using Expanded Memory? jz scxx ;Yes? Jump out. mov ah,3eh ;Close file function. mov bx,_file_handle ;Get DOS file handle. call dos ;Close the handle. scxx: ret _swap_close endp ;-------------------------------------------------------------------------- _swap_reset proc cmp _emm_use_flag,1 ;Do we reset swap file, or ems. jz sruemm ;Use EMM? Jump to emm handler. sruf: mov ax,4200h mov bx,_file_handle xor cx,cx xor dx,dx call dos ret ;Exit #1. sruemm: xor ax,ax mov cs:ems_offset,ax mov cs:ems_segment,ax ret ;Exit #2. _swap_reset endp ;-------------------------------------------------------------------------- ; Zap the swap file by writing ZERO bytes to it at current location. ;-------------------------------------------------------------------------- _swap_zap proc mov ah,40h ;Dos Write function. mov bx,_file_handle ;Get handle. xor cx,cx ;Write ZERO bytes. call dos ;Call DOS to write. ret _swap_zap endp ;-------------------------------------------------------------------------- ; This procedure sets the EMM_LOADED flag, and returns 0 or 1 for EMM-LOADED. ;-------------------------------------------------------------------------- _emm_loaded proc push es push bx mov _emm_load_flag,0 mov ax,3567h int 21h ;Get vector to EMM. mov di,0ah ;ES:000A points to "EMMXXXX0" cmp word ptr es:[di],"ME" jnz elnz cmp word ptr es:[di+2],"XM" jnz elnz cmp word ptr es:[di+4],"XX" jnz elnz cmp word ptr es:[di+6],"0X" jnz elnz mov _emm_load_flag,1 ;EMM is loaded. ;;; mov _emm_use_flag,1 ;Use EMM. elnz: mov ax,_emm_load_flag ;Return status. pop bx pop es ret _emm_loaded endp ;-------------------------------------------------------------------------- ; This procedure allocates and saves an EMM handle. ;-------------------------------------------------------------------------- _ems_open proc push bp mov bp,sp mov bx,[bp+4] ;Get number of 16K pages. pop bp mov ah,43h mov ems_start_pgf,bx int 67h or ah,ah ;AH=0 if OK. jnz esbx ;Jump out if unsuccessful. mov ems_handle,dx mov ax,5301h ;Set name of EMM handle. mov dx,ems_handle or dx,dx jz esxx lea si,ems_name int 67h xor ax,ax esxx: ret esbx: mov ax,0ffffh ;Signal BAD result. ret _ems_open endp ;-------------------------------------------------------------------------- ; This procedure deallocates the EMM handle. ;-------------------------------------------------------------------------- _ems_close proc mov ah,45h ;EMS DeAllocate function. mov dx,ems_handle ;Get the EMS handle. or dx,dx ;Is it a valid handle? jz ecxx ;No? Jump out. int 67h ecxx: mov ems_handle,0 ;Reset to ZERO. ret _ems_close endp ;-------------------------------------------------------------------------- ;-------------------------------------------------------------------------- read_write proc cmp cs:_emm_use_flag,1 ;Are we using expanded memory? jz erwx ;Yes, Jump to EMM routines. call dos ;No? Call DOS. ret erwx: cmp ah,40h jz _ems_write cmp ah,3fh jz _ems_read ret read_write endp ;-------------------------------------------------------------------------- ; Read EMS procedure. ; ; On Entry: AH = 3fh ; Just for grins. ; BX = EMM Handle. ; DS:DX = Segment:Offset of Location to read from. ; CX = Number of bytes to read. ; ;-------------------------------------------------------------------------- _ems_read proc push cx push bx push si push ds mov cs:dest_init_seg,ds mov cs:dest_init_ofs,dx mov cs:dest_handle,0 ;Handle N/A to conventional RAM. mov cs:dest_mem_type,0 ;Conventional Memory. mov cs:region_len_l,cx ;Store length of memory move. mov cs:region_len_h,0 mov cs:src_mem_type,1 ;Signal Move FROM EMS. mov bx,cs:ems_handle ;Get EMM Handle. mov cs:src_handle,bx ;Store EMM Handle. mov dx,cs:ems_offset mov bx,cs:ems_segment push dx and dx,3fffh mov cs:src_init_ofs,dx ;Store offset into EMM page. pop dx clc rcl dx,1 ;Multiply High part X 4 since rcl bx,1 ;Segment will be 16K page and ;Not 64K page. rcl dx,1 rcl bx,1 mov cs:src_init_seg,bx ;Store segment into page. mov ax,5700h lea si,cs:region_len_l push ds push cs pop ds int 67h pop ds add cs:ems_offset,cx adc cs:ems_segment,0 pop ds pop si pop bx pop cx mov ax,cx ;Return bytes read. clc ret _ems_read endp ;-------------------------------------------------------------------------- ; Write EMS procedure. ; ; On Entry: AH = 40h ; Just for grins. ; BX = EMM Handle. ; DS:DX = Segment:Offset of Location to write to from. ; CX = Number of bytes to read. ; ;-------------------------------------------------------------------------- _ems_write proc push cx push bx push si push ds mov cs:src_init_seg,ds mov cs:src_init_ofs,dx mov dx,cs mov ds,dx mov cs:src_handle,0 ;Handle N/A to conventional RAM. mov cs:src_mem_type,0 ;Conventional Memory. mov cs:region_len_l,cx ;Store length of memory move. mov cs:region_len_h,0 mov cs:dest_mem_type,1 ;Signal Move TO EMS. mov bx,cs:ems_handle mov cs:dest_handle,bx ;Store EMM Handle. mov dx,cs:ems_offset mov bx,cs:ems_segment push dx and dx,3fffh mov cs:dest_init_ofs,dx ;Store offset into EMM page. pop dx clc rcl dx,1 ;Multiply High part X 4 since rcl bx,1 ;Segment will be 16K page and ;Not 64K page. rcl dx,1 rcl bx,1 mov cs:dest_init_seg,bx ;Store segment into page. mov ax,5700h lea si,cs:region_len_l int 67h or ah,ah ;Get status. jz ewok xor cx,cx ewok: add cs:ems_offset,cx adc cs:ems_segment,0 pop ds pop si pop bx mov ax,cx ;Return bytes written. call accumulate ;Add in size of data written. pop cx or ax,ax ;Were any bytes written? jnz ewx1 ;Yes? Then Jump out. stc ;NO? Then AX=0,CY and exit. ret ewx1: clc ret _ems_write endp ;-------------------------------------------------------------------------- copy_cmd proc push ds push es lea di,_cmdline ;ES:DI points to our command line. mov si,cmdoff mov ds,cmdseg ;DS:SI point to ACAD passed cmd line. mov cx,80h cld rep movsb pop es pop ds ret copy_cmd endp ;-------------------------------------------------------------------------- copy_env proc push ds push es mov es,envseg ;Get segment of environment. xor si,si ;Initialize pointer. xor cx,cx ;Initialize count. not_end_env: inc cx mov ax,es:[si] inc si or ax,ax jnz not_end_env add cx,64 ;Add in extra space to be allocated. shr cx,1 shr cx,1 shr cx,1 shr cx,1 ;Figure segment to use. xor ax,ax mov envseg,ax ;ZAP environment segment for now. mov ah,48h mov bx,cx int 21h ;Allocate space. AX:0 points to block jc envabort mov envseg,ax mov dx,es mov ds,dx ;DS:0 points to source. mov es,ax ;ES:0 points to destination. xor si,si mov di,si copyloop: mov ax,[si] ;Get a word. mov es:[di],al ;Put one byte down. inc si ;Increment pointers. inc di or ax,ax ;Is it final set of ZEROS? jnz copyloop copyend: mov si,DGROUP mov ds,si ;DS:SI points to our env setting. lea si,exspace mov cx,26 rep movsb ;Copy the dummy into place. envabort: pop es pop ds ret copy_env endp ;-------------------------------------------------------------------------- free_env proc mov es,envseg mov ah,49h int 21h ret free_env endp ;-------------------------------------------------------------------------- INT15: cmp ah,88h jz get_e_sz cmp ax,0 jnz i15x cmp bx,0ffffh jnz i15x cmp cx,0ffffh jnz i15x mov ax,5342h iret i15x: jmp dword ptr cs:o15o get_e_sz: mov ax,cs:esize iret ;-------------------------------------------------------------------------- o21f19o dw 0 o21f19s dw 0 cur_drive db 0 ;--------------- _hook19: ; push es ; push ds ;REMOVED IN VERSION 1.10. ; ; mov ah,19h ; int 21h ; mov cs:cur_drive,al ; ; mov ax,3521h ; int 21h ; mov cs:o21f19o,bx ; mov cs:o21f19s,es ; ; mov ax,cs ; mov ds,ax ; mov dx,offset i21f19 ; mov ax,2521h ; int 21h ; ; pop ds ; pop es ret ;--------------- _unhook19: ; push ds ; push es ; ; mov ax,2521h ; mov ds,cs:o21f19s ; mov dx,cs:o21f19o ; int 21h ; ; pop es ; pop ds ret ;-------------------------------------------------------------------------- ; This function returns the Error Level from ; executed shell program, to the parent program. ;-------------------------------------------------------------------------- get_elevel proc mov ax,cs:errorlevel iret get_elevel endp ;--------------- ; ;i21f19: cmp ah,19h ; jnz i21xa ; mov al,cs:cur_drive ; iret ; ; i21xa: cmp ah,0eh ; jnz i21xb ; mov cs:cur_drive,dl ; ; i21xb: jmp dword ptr cs:o21f19o ; ;-------------------------------------------------------------------------- i21x: jmp dword ptr cs:o21o ;-------- INT21: cmp ah,4dh ;Retreive error level? jz get_elevel ;Yes? Get error level and return it. cmp ah,4bh ;Call to exec? jz i21nx ;Yes, then jump to continue. cmp ah,48h ;Call to malloc? jnz i21x ;No? Then jump out. cmp bx,10h ;Is it malloc of 256 bytes? jnz i21x ;No? Then jump out. cmp cs:psp256,0 ;Is the memory still ours? jz i21x ;No? Then jump out. mov ax,cs:psp256 ;Give it to Phar-Lap. mov cs:psp256,0 ;Offically. sti PUSH BP ;Get previous flags off of stack. PUSH AX MOV BP,SP MOV AX,[BP+8] PUSH AX POPF ;Put them in place IN FLAGS. POP AX POP BP CLC retf 2 ;-------- i21nx: cmp cs:tripskip,1 ;Skip this trip? jnz i21go ;Yes? Then Jump. jmp i21x i21go: mov cs:tripskip,1 ;Set semiphore. cli mov cs:ts_ss,ss mov cs:ts_sp,sp mov sp,cs mov ss,sp mov sp,offset I_STACK sti push ax push bx push cx push dx push si push di push bp push ds push es ;;;;;; call find_irq0 cld push ds push es mov si,DGROUP mov es,si lea di,_program ;ES:DI point to buffer to hold program name. mov si,dx ;DS:SI point to program name to run. mov cx,80 rep movsb ;Copy name of program to run. pop es pop ds mov si,es mov ds,si mov si,bx ;DS:SI points to passed parm block. mov cx,DGROUP mov es,cx lea di,envseg ;ES:DI points to our parm block area. movsw ;Copy env seg, cmd ofs, cmd seg. movsw movsw mov ds,cx ;DS=ES=DGROUP call _exec pop es pop ds pop bp pop di pop si pop dx pop cx pop bx pop ax cli mov sp,cs:ts_ss mov ss,sp mov sp,cs:ts_sp sti cmp cs:retry,1 ;If original attempt failed, try normal. jnz i21done mov cs:tripskip,0 jmp dword ptr cs:o21o ;Jump to DOS. i21done: mov cs:tripskip,0 PUSH BP ;Get previous flags off of stack. PUSH AX MOV BP,SP MOV AX,[BP+8] PUSH AX POPF ;Put them in place IN FLAGS. POP AX POP BP clc ;Return OK to AutoCAD. retf 2 ;;;;;;; iret ;Fixed in Big-Shell 2.0. ;---------------------------------------------------------------------- INT24: mov al,0 ;IGNORE ERROR. INT23: iret ;---------------------------------------------------------------------- _shell proc push bp mov bp,sp push bx push cx push dx push es push ds push si push di mov bs_ds,ds ;Save "C" Data segment. mov bs_es,es ;Save "C" Extra segment. mov ostacko,sp ;Store the current stack. mov ostacks,ss mov ah,51h ;Get psp to bx call dos ;Get it. mov cmdseg,bx mov fcb1seg,bx mov fcb2seg,bx ;Store segments. push ds mov ds,bx mov bx,ds:[2ch] ;Get environment segment. pop ds mov envseg,bx ;Store environment segment. lea dx,_runname ;DS:DX point to run name. lea bx,envseg ;Get pointer to parameter block mov ax,DGROUP mov es,ax ;ES:BX point to parameter block. mov ax,4b00h pushf cli call dword ptr cs:o21o ;Call dos via a fake call. mov ax,DGROUP mov ds,ax jnc noerror ;If it returned CY as shell result: mov ax,0ffffh noerror: cli ;Restore stack with interrupts off. mov sp,ostacks mov ss,sp mov sp,ostacko sti pop di pop si pop ds pop es pop dx pop cx pop bx pop bp ret _shell endp ;-------------------------------------------------------------------------- _acadshell proc push bp mov bp,sp push bx push cx push dx push es push ds push si push di db 0fh,0a0h ;PUSH FS db 0fh,0a8h ;PUSH GS mov ax,ds mov es,ax mov aostacko,sp ;Store the current stack. mov aostacks,ss mov ah,51h ;Get psp to bx call dos ;Get it. mov fcb1seg,bx mov fcb2seg,bx ;Store segments. call copy_cmd ;Copy command line. lea bx,_cmdline ;Store pointer to "saved" command line. mov cmdoff,bx mov cmdseg,ds cmp envseg,0 ;Is there a valid env segment? (cadkey mod) jz no_env call copy_env ;Allocate space and copy environment into place. no_env: lea dx,_program ;DS:DX point to autocad shelled program name. lea bx,envseg ;Get pointer to parameter block mov ax,4b00h pushf cli call dword ptr cs:o21o ;Call dos via a fake call mov ax,DGROUP mov ds,ax mov es,ax mov ah,4dh ;Get the error level that program returned. pushf cli call dword ptr cs:o21o mov cs:errorlevel,ax ;Store it locally. cli ;Restore stack with interrupts off. mov sp,aostacks mov ss,sp mov sp,aostacko sti cmp envseg,0 ;Is there a valid env segment? (cadkey mod) jz no_denv call free_env ;Free allocated environment space. no_denv: db 0fh,0a9h ;POP GS db 0fh,0a1h ;POP FS pop di pop si pop ds pop es pop dx pop cx pop bx pop bp ret _acadshell endp ;-------------------------------------------------------------------------- _install23 proc pushf push es cli xor ax,ax mov es,ax mov di,8ch mov ax,offset INT23 mov es:[di],ax ;Store offset of NEW INT 23 handler. mov ax,cs mov es:[di+2],ax ;Store segment of NEW INT 23 handler. pop es popf ret _install23 endp ;-------------------------------------------------------------------------- _install24 proc pushf push es cli xor ax,ax mov es,ax mov di,90h mov ax,offset INT24 mov es:[di],ax ;Store offset of NEW INT 24 handler. mov ax,cs mov es:[di+2],ax ;Store segment of NEW INT 24 handler. pop es popf ret _install24 endp ;-------------------------------------------------------------------------- ; This routine saves vectors. ;-------------------------------------------------------------------------- _storevects proc push ds push es push si push di xor ax,ax mov ds,ax mov si,ax ;ES:DI ->vector table. cld mov ax,cs mov es,ax mov di,offset _vector_table ;DS:SI ->0:0 mov cx,512 ;512 words to swap. rep movsw pop di pop si pop es pop ds ret _storevects endp ;------------------------------------------------------------------------- ; This procedure: ; ; 1: Saves the SEG address for the Memory Control Block that holds our PSP. ; 2: Saves the SEG address of the NEXT MCB after us. ;------------------------------------------------------------------------- _saveblocks proc push ds push es mov ah,51h ;Get PSP. int 21h dec bx ;Get address of block before PSP. mov adr_b4us,bx ;Store address push ds pop es mov ds,bx xor si,si ;ES:DI point to storage. lea di,blk_b4us ;DS:SI point to block. mov cx,16 ;Store 16 bytes cld rep movsb add bx,ds:[0003] ;Add in memory used by our block. inc bx ;Add in size of block. mov ds,bx xor si,si ;DS:SI points to block after us. lea di,_adr_afus mov es:[di],bx ;Store segment address of block after us. lea di,blk_afus ;ES:DI points to storage. mov cx,16 rep movsb pop es pop ds ret _saveblocks endp ;-------------------------------------------------------------------------- ; ;_fill proc ; ; xor ax,ax ; push ax ; ; mov bx,0ffffh ;Request max block size. ; ;fretry: cmp bx,0 ; jz fillx ; ; mov ah,48h ;Allocate memory. ; int 21h ;Call DOS. BX holds max block size. ; jc fretry ; ; push ax ;Push block seg address onto stack. ; jmp fretry ; ;fillx: mov ah,62h ; int 21h ;Get PSP ; mov cx,bx ;CX holds PSP segment. ; ;daloop: pop ax ; ; or ax,ax ;Was it 0000? ; jz fx2 ;Yes? Then exit. ; ; cmp ax,cx ;Is it above PSP? ; jc daloop ;No? Jump up again. ; ; push es ; mov es,ax ; mov ah,49h ;Deallocate block. ; int 21h ; pop es ; jmp daloop ; ; ;fx2: ret ; ; ;_fill endp ; ; ; ;-------------------------------------------------------------------------- _detect proc mov ah,62h int 21h dec bx mov es,bx inc bx add bx,es:[3] mov es,bx mov al,es:[0] xor ah,ah ret _detect endp ;-------------------------------------------------------------------------- ;-------------------------------------------------------------------------- _start proc mov ax,DGROUP mov ds,ax mov es,ax mov ss,ax lea sp,endstack call _main mov ah,4ch int 21h ret _start endp end _start