;
; CONTROL.EXE Swap Out Program
;
		.286
_TEXT		SEGMENT  WORD PUBLIC 'CODE'
_TEXT		ENDS
_DATA		SEGMENT  WORD PUBLIC 'DATA'
_DATA		ENDS
CONST		SEGMENT  WORD PUBLIC 'CONST'
CONST		ENDS
_BSS		SEGMENT  WORD PUBLIC 'BSS'
_BSS		ENDS
_INST		SEGMENT  WORD PUBLIC 'INST'
_INST		ENDS

DGROUP		GROUP	_TEXT, CONST, _BSS, _DATA, _INST

extrn		End_of_Prog:word

_DATA		segment

Swap_Prog	db	'T_OAK2.EXE',0
Swap_Psp	dw	?
Swap_Fp		dw	?
Swap_Size	dw	?
Work_Size	dw	?
Mcb_Top		dw	?
Far_Jmp		dd	far
Old_Alc		dw	?
Tmp_File	db	128 dup (0)
Err_Msg		db	'致命的なエラ−が発生しましたRESETしてください'
		db	07h,0Dh,0Ah,'$'

_DATA		ends

_TEXT		segment
		ASSUME CS: DGROUP, DS: DGROUP, ES:nothing

		public	swap_load
swap_load	proc	near

		cmp	word ptr [Swap_Psp],0
		jne	swap_load_go
		ret

swap_load_go:	mov	es,[Swap_Psp]
		mov	bx,[Swap_Size]	; 16 Byte
		mov	ah,4Ah		; ReSize Mem Block
		int	21h
		jc	swap_load_err

		mov	ax,[Swap_Psp]
		dec	ax
		mov	es,ax
		mov	ax,[Swap_Psp]
		mov	es:[1],ax

		mov	ax,3D00h	; Open Tmp File
		mov	dx,offset DGROUP:Tmp_File
		int	21h
		jc	swap_load_err
		mov	[Swap_Fp],ax

		mov	ax,[Swap_Size]
		mov	[Work_Size],ax

		push	ds
		pop	es		; ES = DS

		ASSUME ES: DGROUP, DS:nothing

		mov	ds,es:[Swap_Psp]
		xor	dx,dx
		mov	bx,es:[Swap_Fp]

swap_read:	mov	cx,0800h
		cmp	cx,es:[Work_Size]
		jbe	swap_read2
		mov	cx,es:[Work_Size]

swap_read2:	shl	cx,4
		mov	ah,3Fh		; Read File
		int	21h
		jc	swap_load_err2
		cmp	cx,ax
		jne	swap_load_err2

		shr	cx,4
		mov	ax,ds
		add	ax,cx
		mov	ds,ax
		mov	ax,es:[Work_Size]
		sub	ax,cx
		mov	es:[Work_Size],ax
		jne	swap_read

		push	es
		pop	ds

		ASSUME DS: DGROUP, ES:nothing

		mov	bx,[Swap_Fp]
		mov	ah,3Eh		; File Close
		int	21h

		mov	dx,offset DGROUP:Tmp_File
		mov	ah,41h		; Delete File
		int	21h

		ret

swap_load_err2:	push	es
		pop	ds

swap_load_err:	mov	dx,offset DGROUP:Err_Msg
		mov	ah,09h		; Disp Msg
		int	21h
		jmp	swap_load_err

swap_load	endp

		public	move_proc
move_proc	proc	near
		mov	ax,5800h	; alloc mode get
		int	21h
		mov	[Old_Alc],ax
		mov	ax,5801h	; alloc mode set
		mov	bx,02h		; upper mem
		int	21h

		mov	bx,offset DGROUP:End_of_Prog
		add	bx,15
		shr	bx,4
		mov	cx,bx
		mov	ah,48h		; Alloc mem
		int	21h
		jnc	move_next
		jmp	move_proc_end

move_next:	mov	es,ax
		sub	si,si
		sub	di,di
		shl	cx,3		; * 16 / 2 = 8
	rep	movsw

		mov	dx,es
		mov	ah,55h		; Dup PSP
		int	21h

		mov	ax,ds:[16h]	; pid
		mov	es:[16h],ax

		mov	bx,es
		mov	ah,50h
		int	21h		; Set Current PSP

		push	es
		mov	ax,ds:[2Ch]	; Env Seg
		dec	ax
		mov	es,ax
		mov	bx,es:[3]	; Env Seg Size
		mov	cx,bx
		mov	ah,48h		; Alloc mem
		int	21h
		jc	move_env_skip

		push	ds
		mov	es,ax
		mov	dx,ds:[2Ch]	; Env Seg
		mov	ds,dx		; DX = Old Seg
		sub	si,si
		sub	di,di
		shl	cx,3		; * 16 / 2 = 8
	rep	movsw
		pop	ds

		mov	ds:[2Ch],es	; New Env Seg
		mov	es,dx		; Old Seg = DX
		mov	ah,49h		; Free Mem Block
		int	21h

move_env_skip:	pop	es
		mov	ax,ds:[2Ch]
		mov	es:[2Ch],ax

		mov	word ptr [Far_Jmp],offset DGROUP:move_flush
		mov	word ptr [Far_Jmp+2],es
		jmp	[Far_Jmp]

move_flush:	mov	bx,ds
		mov	ax,es
		mov	ds,ax
		mov	ss,ax

		mov	es,bx
		mov	ah,49h		; Free Mem Block
		int	21h

		mov	ax,cs
		dec	ax
		mov	es,ax
		mov	es:[1],cs	; Onwer ID Cheng

		mov	ax,ds:[2Ch]	; Env Seg
		dec	ax
		mov	es,ax
		mov	es:[1],cs	; Onwer ID Cheng

move_proc_end:	mov	ax,5801h	; alloc mode set
		mov	bx,[Old_Alc]
		int	21h
		ret

move_proc	endp

mcb_chk		proc	near
		push	es
		push	bx
		push	ax

		mov	bx,es
		dec	bx
		mov	es,[Mcb_Top]

mcb_chk_loop:	mov	ax,es
		cmp	bx,ax
		je	mcb_chk_hit

		cmp	byte ptr es:[0],'Z'
		je	mcb_chk_non
		mov	ax,es
		add	ax,es:[3]
		inc	ax
		mov	es,ax
		jmp	mcb_chk_loop

mcb_chk_hit:	clc
		jmp	mcb_chk_end

mcb_chk_non:	stc

mcb_chk_end:	pop	ax
		pop	bx
		pop	es
		ret
mcb_chk		endp

serch_prog	proc	near

		mov	ah,52h		; Get DOS para
		int	21h
		mov	dx,es:[bx-2]
		mov	[Mcb_Top],dx

serch_loop:	mov	es,dx
		mov	ax,es:[1]	; PSP Seg
		or	ax,ax
		je	serch_chk
		mov	es,ax
		call	mcb_chk
		jc	serch_chk

		mov	ax,es:[2Ch]	; Env Seg
		or	ax,ax
		je	serch_chk
		mov	es,ax
		call	mcb_chk
		jc	serch_chk

		sub	bx,bx
serch_next:	mov	al,es:[bx]
		inc	bx
		or	al,al
		jne	serch_next
		mov	al,es:[bx]
		inc	bx
		or	al,al
		jne	serch_next

		add	bx,2
		mov	si,bx

serch_path:	mov	al,es:[bx]
		inc	bx
		cmp	al,'\'
		je	serch_path1
		cmp	al,':'
		jne	serch_path2
serch_path1:	mov	si,bx
serch_path2:	or	al,al
		jne	serch_path

		mov	di,offset DGROUP:Swap_Prog
serch_cmp:	mov	al,es:[si]
		cmp	al,'a'
		jb	serch_toup
		cmp	al,'z'
		ja	serch_toup
		and	al,0DFh
serch_toup:	cmp	al,[di]
		jne	serch_chk
		or	al,al
		je	serch_hit
		inc	si
		inc	di
		jmp	serch_cmp

serch_hit:	mov	es,dx
		mov	ax,es:[1]	; PSP Seg
		mov	es,ax
		clc
		ret

serch_chk:	mov	es,dx
		cmp	byte ptr es:[0],'Z'
		je	serch_end
		add	dx,es:[3]
		inc	dx
		jmp	serch_loop

serch_end:	stc
		ret

serch_prog	endp

get_tmp_env	proc	near
		mov	es,ds:[2Ch]	; Env Seg
		xor	bx,bx
		mov	di,offset DGROUP:Tmp_File

get_tmp_loop:	cmp	byte ptr es:[bx],0
		je	get_tmp_end

		mov	ax,es:[bx]
		and	ax,0DFDFh
		cmp	ax,'M'*256+'T'
		jne	get_tmp_skip
		mov	ax,es:[bx+2]
		and	ax,0FFDFh
		cmp	ax,'='*256+'P'
		jne	get_tmp_skip

		add	bx,4
get_tmp_set:	mov	al,es:[bx]
		cmp	al,0
		je	get_tmp_set2
		mov	ds:[di],al
		inc	di
		inc	bx
		jmp	get_tmp_set

get_tmp_set2:	mov	al,es:[bx-1]
		cmp	al,'\'
		je	get_tmp_end
		mov	byte ptr ds:[di],'\'
		inc	di
		jmp	get_tmp_end

get_tmp_skip:	mov	al,es:[bx]
		inc	bx
		cmp	al,0
		jne	get_tmp_skip
		jmp	get_tmp_loop

get_tmp_end:	mov	word ptr ds:[di+0],'R'*256+'O'
		mov	word ptr ds:[di+2],'T'*256+'I'
		mov	word ptr ds:[di+4],'P'*256+'M'
		mov	word ptr ds:[di+6],'$'*256+'.'
		mov	word ptr ds:[di+8],'$'*256+'$'
		mov	byte ptr ds:[di+10],0
		ret

get_tmp_env	endp

		public	swap_save
swap_save	proc	near

		call	serch_prog
		jnc	swap_save_go
		jmp	swap_not

swap_save_go:	mov	[Swap_Psp],es
		call	get_tmp_env

		mov	dx,offset DGROUP:Tmp_File
		mov	ah,41h		; Delete File
		int	21h		; Dummy Delete

		mov	ah,5Bh		; Create Tmp File
		mov	cx,02h		; No Serch Attr
		mov	dx,offset DGROUP:Tmp_File
		int	21h
		jc	swap_not
		mov	[Swap_Fp],ax

		mov	ax,[Swap_Psp]
		dec	ax
		mov	es,ax		; PSP MCB Seg
		mov	ax,es:[3]	; MCB Size
		mov	[Swap_Size],ax	; x16 Byte Size
		mov	[Work_Size],ax	; x16 Byte Size

		push	ds
		pop	es		; ES = DS

		ASSUME ES: DGROUP, DS:nothing

		mov	ds,es:[Swap_Psp]
		xor	dx,dx
		mov	bx,es:[Swap_Fp]

swap_write:	mov	cx,0800h
		cmp	cx,es:[Work_Size]
		jbe	swap_write2
		mov	cx,es:[Work_Size]

swap_write2:	shl	cx,4
		mov	ah,40h		; Write File
		int	21h
		jc	swap_error2
		cmp	cx,ax
		jne	swap_error2

		shr	cx,4
		mov	ax,ds
		add	ax,cx
		mov	ds,ax
		mov	ax,es:[Work_Size]
		sub	ax,cx
		mov	es:[Work_Size],ax
		jne	swap_write

		push	es
		pop	ds

		ASSUME DS: DGROUP, ES:nothing

		mov	bx,[Swap_Fp]
		mov	ah,3Eh		; File Close
		int	21h

		mov	es,[Swap_Psp]
		mov	bx,1		; 16 Byte
		mov	ah,4Ah		; ReSize Mem Block
		int	21h
		jc	swap_error

		ret

swap_error2:	push	es
		pop	ds

swap_error:	mov	bx,[Swap_Fp]
		mov	ah,3Eh		; File Close
		int	21h

		mov	dx,offset DGROUP:Tmp_File
		mov	ah,41h		; Delete File
		int	21h
		
swap_not:	mov	word ptr [Swap_Psp],0
		ret

swap_save	endp

_TEXT		ends

		end
