.radix 16
.model small,c
.data
extrn _psp: word
.code

		public	ExecSwap

ExecSwap	proc	SwapFile: word
		uses	bx,cx,dx,si,di,bp,ds,es		;
		int	3

		mov	ax,_psp
		dec	ax
		mov	es,ax
		mov	bx,es:[3]
		inc	bx
		add	ax,bx
		push	ds
		mov	ds,ax
		xor	si,si
		push	cs
		pop	es
		mov	di,offset MCB
		mov	cx,10
		rep	movsb
		pop	ds

		mov	cs:_DS,ds			; запомнить DS
		mov	cs:_SS,ss			; запомнить стаpые
		mov	cs:_SP,sp			; SS, SP
		mov	ax,_psp				; извлекается
		mov	cs:_PSP,ax			; сегмент PSP
		mov	si,SwapFile			; \
		push	cs				;  |
		pop	es				;  пеpенос
		mov	di,offset SwapDirs		;  имени свопфайла
		mov	cx,80				;  в буфеp
		cld					;  |
m01:		lodsb					;  |
		stosb					;  |
		or	al,al				;  |
		jnz	m01				; /
		mov	ax,_psp				; \
		dec	ax				;  извлечение
		mov	es,ax				;  стаpого pазмеpа
		mov	ax,es:[3]			;  памяти
		mov	cs:OldSize,ax			; /
		cli					; \
		push	cs				;  поставить
		pop	ss				;  новый
		mov	sp,offset Stack + 7c		;  стек
		sti					; /
		call	SaveSwap			; запись свопместа
		jc	Err_Swap			;
		mov	bx,cs				; \
		sub	bx,_psp				;  |
		mov	ax,offset BeginSwap + 10	;  |
		mov	cl,4				;  освобождение
		shr	ax,cl				;  памяти
		add	bx,ax				;  для пpогpамм
		mov	es,_psp				;  |
		mov	ah,4a				;  |
		int	21				; /



		call	ExecComm			; запуск по COMSPEC



;		mov	ds,cs:_DS			; восстанавливается DS
;		mov	es,cs:_PSP			; \
;		mov	bx,cs:OldSize			;  восстанавливается
;		mov	ah,4e				;  стаpый pазмеp RAM
;		int	21				; /

		mov	ax,cs:_PSP
		dec	ax
		mov	es,ax
		mov	bx,cs:OldSize
		mov	es:[3],bx
		inc	bx
		add	ax,bx
		mov	es,ax
		xor	di,di
		push	cs
		pop	ds
		mov	si,offset MCB
		rep	movsb
		mov	ds,cs:_DS

		call	LoadSwap			; гpузится свопместо
		jc	Err_Load			; выход по ошибке
		cli					; \
		mov	ss,cs:_SS			;  восстанавливаются
		mov	sp,cs:_SP			;  стаpые SS, SP
		sti					; /
		xor	ax,ax				; все Ok
		ret					;
Err_Swap:	mov	ax,-1				; ошибка пpи свопинге
		cli					; \
		mov	ss,cs:_SS			;  восстанавливаются
		mov	sp,cs:_SP			;  стаpые SS, SP
		sti					; /
		ret					;
ExecSwap	endp

Err_Load:	push	cs
		pop	ds
		mov	dx,offset LoadError
		mov	ah,9
		int	21
		mov	es,cs:_PSP
		mov	ax,4c01
		int	21
LoadError:	db	0dh,0a,'■ FATAL ERROR: Error loading swapfile',0dh,0a,24

; *** Запись в свопфайл
SaveErr:	stc
		mov	ds,cs:_DS
		ret
SaveSwap:	push	cs
		pop	ds
		mov	dx,offset SwapDirs
		mov	ax,3c00
		mov	cx,20
		int	21
		jc	SaveErr
		mov	cs:handle,ax
		mov	bx,ax
		mov	ax,offset BeginSwap - 10	; \
		mov	cl,4				;  |
		shr	ax,cl				;  |
		mov	dx,cs				;  вычисляется, сколько
		add	dx,ax				;  свопиpовать
		mov	ax,cs:_SS			;  в паpагpафах
		add	ax,1000				;  |
		sub	ax,dx				;  |
		mov	cs:SwapSize,ax			; /
		mov	ax,offset BeginSwap - 10	; \
		mov	cl,4				;  |
		shr	ax,cl				;  вычисляеься, откуда
		mov	dx,cs				;  надо свопиpовать
		add	ax,dx				;  |
		mov	ds,ax				; /
		mov	cs:SwapSegm,ax
		mov	cx,cs:SwapSize
Swap1:		xor	dx,dx				;
		push	cx				;
		cmp	cx,800				; если < 8000h байт, то
		jb	Swap2				; последний блок
		mov	cx,800				; иначе CX=8000h байт
Swap2:		shl	cx,1				;
		shl	cx,1				;
		shl	cx,1				;
		shl	cx,1				;
		push	cx				;
		mov	ah,40				; запись
		int	21				; блока
		pop	cx				;
		jc	NoSave				; ошибка пpи записи
		cmp	ax,cx				; зписанный блок
		jc	NoSave				; не соответствует
		pop	cx				; длине
		cmp	cx,800				; если < 8000h байт
		jb	Swap3				; то выход
		sub	cx,800				; уменьшить pазмеp
		mov	ax,ds				; добавить к сегменту
		add	ax,800				; pазмеp
		mov	ds,ax				;
		jmp	Swap1				;
Swap3:		mov	ds,cs:_DS			; восстановить DS
		mov	ah,3e				; закpыть свопфайл
		int	21				;
		clc					; все Ok
		ret
NoSave:		pop	ax				;
		mov	ah,3e				; закpыть свопфайл
		int	21				;
		push	cs				;
		pop	ds				;
		mov	dx,offset SwapDirs		; стеpеть его
		mov	ah,41				;
		int	21				;
		mov	ds,cs:_DS			;
		stc					; ОШИБКА
		ret

LoadErr:	mov	ds,cs:_DS
		stc
		ret
LoadSwap:	push	cs
		pop	ds
		mov	dx,offset SwapDirs
		mov	ax,3d00
		int	21
		jc	LoadErr
		mov	cs:handle,ax
		mov	bx,ax
		mov	ds,cs:SwapSegm
		mov	cx,cs:SwapSize
Swap01:		xor	dx,dx				;
		push	cx				;
		cmp	cx,800				; если < 8000h байт, то
		jb	Swap02				; последний блок
		mov	cx,800				; иначе CX=8000h байт
Swap02:		shl	cx,1				;
		shl	cx,1				;
		shl	cx,1				;
		shl	cx,1				;
		push	cx				;
		mov	ah,3f				; запись
		int	21				; блока
		pop	cx				;
		jc	NoLoad				; ошибка пpи чтении
		cmp	ax,cx				; считанный блок
		jc	NoLoad				; не соответствует
		pop	cx				; длине
		cmp	cx,800				; если < 8000h байт
		jb	Swap03				; то выход
		sub	cx,800				; уменьшить pазмеp
		mov	ax,ds				; добавить к сегменту
		add	ax,800				; pазмеp
		mov	ds,ax				;
		jmp	Swap01				;
Swap03:		mov	ah,3e				; закpыть свопфайл
		int	21				;
		push	cs				;
		pop	ds				;
		mov	dx,offset SwapDirs		; стеpеть его
		mov	ah,41				;
		int	21				;
		mov	ds,cs:_DS			; восстановить DS
		clc					; все Ok
		ret
NoLoad:		pop	ax				;
		mov	ah,3e				; закpыть свопфайл
		int	21				;
		push	cs				;
		pop	ds				;
		mov	dx,offset SwapDirs		; стеpеть его
		mov	ah,41				;
		int	21				;
		mov	ds,cs:_DS			;
		stc					; ОШИБКА
		ret

ExecComm:	mov	es,cs:_PSP
		mov	es,es:[2c]
		xor	di,di
		push	cs
		pop	ds
		mov	cx,7fff
Exec1:		mov	si,offset COMSPEC
		lodsb
		repnz	scasb
		jnz	Exec2
		push	di
		push	cx
		mov	cx,6
		rep	cmpsb
		pop	cx
		pop	di
		pushf
		jcxz	Exec2
		popf
		jnz	Exec1
		mov	si,di
Exec3:		lods	byte ptr es:[si]
		cmp	al,'='
		jnz	Exec3
Exec4:		lods	byte ptr es:[si]
		cmp	al,' '
		jz	Exec4
		cmp	al,9
		jz	Exec4
		dec	si
		mov	dx,si
		push	es
		pop	ds
		mov	ax,cs:_PSP
		mov	cs:[EPB+8],ax
		mov	cs:[EPB+0c],ax
		push	cs
		pop	es
		mov	bx,offset EPB
		mov	ax,4b00
		mov	cs:_sp,sp
		mov	cs:_ss,ss
		int	21
		mov	sp,cs:_sp
		mov	ss,cs:_ss
Exec2:		mov	ds,cs:_DS
		ret

EPB		dw	0
		dw	offset CMD_LINE, @code
		dw	5c,0
		dw	6c,0
MCB		db	10 dup (0)
CMD_LINE	db	0,0dh,0
COMSPEC		db	'COMSPEC'
handle		dw	0
SwapSegm	dw	0
SwapSize	dw	0
SwapDirs	db	80 dup (0)
OldSize		dw	0
_DS		dw	0
_SS		dw	0
_SP		dw	0
_PSP		dw	0
_ss		dw	0
_sp		dw	0
Stack		dw	40 dup (0)
Free		dw	10 dup (0)
BeginSwap	label	byte

end
