mirror of https://github.com/nmlgc/ReC98.git
497 lines
9.0 KiB
NASM
497 lines
9.0 KiB
NASM
; master library - (pf.lib)
|
|
;
|
|
; Description:
|
|
; オートマチックモード。int 21hにフックする/解除する
|
|
;
|
|
; Functions/Procedures:
|
|
; void pfstart(const char *parfile);
|
|
; void pfend(void);
|
|
;
|
|
; Parameters:
|
|
; parfile parアーカイブファイル名
|
|
;
|
|
; Returns:
|
|
; none
|
|
;
|
|
; Binding Target:
|
|
; Microsoft-C / Turbo-C / Turbo Pascal
|
|
;
|
|
; Running Target:
|
|
; MS-DOS
|
|
;
|
|
; Requiring Resources:
|
|
; CPU: 186
|
|
;
|
|
; Notes:
|
|
;
|
|
;
|
|
; Assembly Language Note:
|
|
;
|
|
;
|
|
; Compiler/Assembler:
|
|
; TASM 3.0
|
|
; OPTASM 1.6
|
|
;
|
|
; Author:
|
|
; iR
|
|
; 恋塚昭彦
|
|
;
|
|
; Revision History:
|
|
; PFINT21.ASM 6,253 94-09-17 23:22
|
|
; 95/ 1/10 Initial: pfint21.asm/master.lib 0.23
|
|
|
|
; global C _fstrncpy : proc
|
|
;; global C printf : proc ;DBG
|
|
|
|
;;trapc dw 0 ;DBG
|
|
org_int21 dd 0
|
|
on_hook db 0
|
|
|
|
th03_archive_header_t struc
|
|
entries_size dw ?
|
|
unk dw ?
|
|
entries_count dw ?
|
|
key dw ?
|
|
zero db 8 dup(0)
|
|
th03_archive_header_t ends
|
|
|
|
func PFSTART ; pfstart() {
|
|
;arg parfile:dataptr
|
|
@@parfile = (RETSIZE+1)*2
|
|
if GAME eq 5
|
|
local @@parheader:th03_archive_header_t
|
|
|
|
enter size th03_archive_header_t, 0
|
|
push si
|
|
push di
|
|
else
|
|
push BP
|
|
mov BP,SP
|
|
|
|
CLD
|
|
endif
|
|
; すでに start してないかチェック
|
|
mov AX,word ptr CS:org_int21
|
|
or AX,word ptr CS:org_int21+2
|
|
if (GAME eq 2) or (GAME eq 5)
|
|
jnz short PFSTART_copy
|
|
else
|
|
jz short PFSTART_1
|
|
jmp PFSTART_copy
|
|
endif
|
|
|
|
PFSTART_1:
|
|
if (GAME eq 3) or (GAME eq 4)
|
|
push di
|
|
push si
|
|
push word ptr [bp+@@parfile+2]
|
|
push word ptr [bp+@@parfile]
|
|
call file_ropen
|
|
push size th03_archive_header_t
|
|
call hmem_allocbyte
|
|
mov di, ax
|
|
push ax
|
|
push 0
|
|
push size th03_archive_header_t
|
|
call file_read
|
|
mov ax, di
|
|
mov es, ax
|
|
mov di, es:[th03_archive_header_t.entries_size]
|
|
mov si, es:[th03_archive_header_t.key]
|
|
push ax
|
|
call hmem_free
|
|
elseif (GAME eq 5)
|
|
pushd dword ptr [bp+@@parfile]
|
|
call file_ropen
|
|
lea ax, @@parheader
|
|
push ss
|
|
push ax
|
|
push size th03_archive_header_t
|
|
call file_read
|
|
mov di, @@parheader.th03_archive_header_t.entries_size
|
|
mov si, @@parheader.th03_archive_header_t.key
|
|
endif
|
|
if GAME ge 3
|
|
push di
|
|
call hmem_allocbyte
|
|
mov pfint21_entries, ax
|
|
push ax
|
|
push 0
|
|
push di
|
|
call file_read
|
|
call file_close
|
|
mov cx, di
|
|
mov ax, pfint21_entries
|
|
mov es, ax
|
|
mov ax, si
|
|
xor bx, bx
|
|
|
|
PFSTART_decrypt:
|
|
xor es:[bx], al
|
|
sub al, es:[bx]
|
|
inc bx
|
|
loop PFSTART_decrypt
|
|
if GAME ne 5
|
|
pop si
|
|
pop di
|
|
endif
|
|
endif
|
|
; DOSファンクションリクエストのエントリを退避
|
|
msdos GetInterruptVector,21h
|
|
mov word ptr CS:org_int21,BX
|
|
mov word ptr CS:org_int21+2,ES
|
|
|
|
; 変数の初期化
|
|
mov pfint21_pf,0
|
|
mov pfint21_handle,-1
|
|
|
|
; 新しいファンクションリクエストエントリをセット
|
|
push DS
|
|
push CS
|
|
pop DS
|
|
mov DX,offset pfint21
|
|
msdos SetInterruptVector,21h
|
|
pop DS
|
|
|
|
PFSTART_copy:
|
|
;strcpy( parfilename, parfile )
|
|
if GAME le 4
|
|
push SI
|
|
push DI
|
|
endif
|
|
_push DS
|
|
|
|
mov CX,-1 ; CX = strlen(parfile)+1
|
|
mov AL,0
|
|
s_push DS
|
|
s_pop ES
|
|
_les DI,[BP+@@parfile]
|
|
repne scasb
|
|
not CX
|
|
sub DI,CX
|
|
|
|
mov SI,DI ; copy
|
|
mov DI,offset parfilename
|
|
_push DS
|
|
_push ES
|
|
_pop DS
|
|
_pop ES
|
|
shr CX,1
|
|
rep movsw
|
|
adc CX,CX
|
|
rep movsb
|
|
|
|
_pop DS
|
|
pop DI
|
|
pop SI
|
|
|
|
if GAME le 4
|
|
pop BP
|
|
else
|
|
leave
|
|
endif
|
|
ret (DATASIZE)*2
|
|
endfunc ; }
|
|
|
|
|
|
func PFEND ; pfend() {
|
|
mov AX,word ptr CS:org_int21
|
|
or AX,word ptr CS:org_int21+2
|
|
jz short PFEND_return
|
|
|
|
if GAME eq 5
|
|
push pfint21_entries
|
|
call hmem_free
|
|
endif
|
|
|
|
; ファンクションリクエストエントリを元に戻す
|
|
push DS
|
|
lds DX,CS:org_int21
|
|
msdos SetInterruptVector,21h
|
|
pop DS
|
|
xor AX,AX
|
|
mov word ptr CS:org_int21,AX
|
|
mov word ptr CS:org_int21+2,AX
|
|
|
|
; オープン中のハンドルがあればクローズ
|
|
cmp pfint21_pf,AX
|
|
je short PFEND_return
|
|
|
|
push pfint21_pf
|
|
_call PFCLOSE
|
|
|
|
if (GAME eq 3) or (GAME eq 4)
|
|
push pfint21_entries
|
|
call hmem_free
|
|
endif
|
|
|
|
PFEND_return:
|
|
ret
|
|
endfunc ; }
|
|
|
|
|
|
pfint21 proc far ; {
|
|
;; inc trapc ;DBG
|
|
cmp CS:on_hook,0
|
|
jz short _Hook
|
|
jmp dword ptr CS:org_int21
|
|
|
|
_Hook:
|
|
pusha ; push AX CX DX BX SP BP SI DI
|
|
push DS
|
|
push ES
|
|
mov BP,SP
|
|
mov DI,DGROUP
|
|
mov DS,DI
|
|
assume DS:DGROUP
|
|
|
|
_FLAGS = + 24
|
|
_CS = +22
|
|
_IP = +20
|
|
_AX = +18
|
|
_CX = +16
|
|
_DX = +14
|
|
_BX = +12
|
|
_SP = +10
|
|
_BP = +8
|
|
_SI = +6
|
|
_DI = +4
|
|
_DS = +2
|
|
_ES = +0
|
|
|
|
inc CS:on_hook
|
|
; 割込みフラグを割込み前に戻す
|
|
push word ptr [BP+_FLAGS]
|
|
popf
|
|
|
|
;; pusha ;DBG
|
|
;; call printf C,offset DGROUP:string,trapc,AX,BX,CX,DX
|
|
;; popa ;DBG
|
|
|
|
; AH(ファンクション)でswitch
|
|
mov byte ptr CS:default,AH
|
|
mov SI,offset switch_table - 4
|
|
i_switch:
|
|
add SI,4
|
|
cmp AH,CS:[SI]
|
|
jne short i_switch
|
|
mov DI,pfint21_handle
|
|
jmp word ptr CS:[SI + 2]
|
|
|
|
switch_table label word
|
|
dw OpenHandle, _Open
|
|
dw CloseHandle, _Close
|
|
dw ReadHandle, _Read
|
|
dw MoveFilePointer, _MoveFilePointer
|
|
dw ForceDuplicateFileHandle,_CheckHandle2
|
|
dw WriteHandle, _CheckHandle
|
|
dw DuplicateFileHandle, _CheckHandle
|
|
dw EndProcess, _Terminate
|
|
dw GetSetDateTimeofFile, _CheckHandle
|
|
dw LockUnlock, _CheckHandle
|
|
dw IOCTL, _IOCTL
|
|
default dw ?, _Thru ; 番兵
|
|
|
|
|
|
;-------------------------------------------------------------------
|
|
; OpenHandle
|
|
; DS:DX パス名
|
|
; AL ファイルアクセスコントロール
|
|
_Open:
|
|
test AL,0fh
|
|
if GAME le 4
|
|
jz _Open1 ; リードモードでない
|
|
jmp _Thru
|
|
_Open1:
|
|
or DI,DI
|
|
js _Open2 ; 既にオープンしている
|
|
jmp _Thru
|
|
else
|
|
jnz _Thru
|
|
or DI,DI
|
|
jns _Thru
|
|
endif
|
|
_Open2:
|
|
; mov DI,offset DGROUP:filename ; lea DI,filename
|
|
; call _fstrncpy C,DI,DS,DX,[BP+_DS],length filename
|
|
; call PFOPEN Pascal,offset DGROUP:[parfilename],DI
|
|
|
|
;call PFOPEN Pascal,offset DGROUP:[parfilename],DX
|
|
_push DS
|
|
push offset parfilename
|
|
push word ptr [BP+_DS]
|
|
push DX
|
|
_call PFOPEN
|
|
; この場合 DS==ssを確認したほうがよい
|
|
|
|
or AX,AX
|
|
if GAME le 4
|
|
jnz _Open3 ; 無条件にthruはよくないかも
|
|
jmp _Thru
|
|
_Open3:
|
|
else
|
|
jz _Thru
|
|
endif
|
|
mov pfint21_pf,AX
|
|
mov ES,AX
|
|
mov ES,ES:[pf_bf]
|
|
mov AX,ES:[b_hdl] ; pf->bf->handle
|
|
mov pfint21_handle,AX
|
|
jmp _OK
|
|
|
|
;-------------------------------------------------------------------
|
|
; CloseHandle
|
|
; BX ファイルハンドル
|
|
_Close:
|
|
cmp BX,DI ; ハンドルチェック
|
|
if GAME le 4
|
|
jz _Close1
|
|
jmp _Thru
|
|
_Close1:
|
|
else
|
|
jnz _Thru
|
|
endif
|
|
push pfint21_pf
|
|
_call PFCLOSE
|
|
|
|
mov pfint21_pf,0
|
|
mov pfint21_handle,-1
|
|
jmp _OK
|
|
|
|
;-------------------------------------------------------------------
|
|
; ReadHandle
|
|
; BX ファイルハンドル
|
|
; DS:DX バッファの位置
|
|
; CX 読み込むべきバイト数
|
|
_Read:
|
|
cmp BX,DI ; ハンドルチェック
|
|
jne short _Thru
|
|
|
|
;call PFREAD Pascal,[BP+_DS],DX,CX,pf
|
|
push word ptr [BP+_DS]
|
|
push DX
|
|
push CX
|
|
push pfint21_pf
|
|
_call PFREAD
|
|
|
|
jmp _OK
|
|
|
|
;-------------------------------------------------------------------
|
|
; MoveFilePointer
|
|
; BX ファイルハンドル
|
|
; CX:DX 移動するバイト数
|
|
; AL 移動方法 00:先頭 01:カレント 02:最後
|
|
_MoveFilePointer:
|
|
cmp BX,DI ; ハンドルチェック
|
|
jne short _Thru
|
|
|
|
or CX,CX
|
|
jl short _Error ; 負のオフセットは不可
|
|
cmp AL,1
|
|
je short i_seek
|
|
jl short i_seek_top
|
|
|
|
; ファイルの終りからの移動は、終わりに移動するだけ
|
|
mov ES,pfint21_pf
|
|
mov DX,word ptr ES:[pf_osize]
|
|
mov CX,word ptr ES:[pf_osize+2]
|
|
sub DX,word ptr ES:[pf_loc]
|
|
sbb CX,word ptr ES:[pf_loc+2]
|
|
jmp short i_seek
|
|
|
|
i_seek_top:
|
|
push CX
|
|
push DX
|
|
push pfint21_pf
|
|
_call PFREWIND
|
|
pop DX
|
|
pop CX
|
|
i_seek:
|
|
push pfint21_pf
|
|
push CX
|
|
push DX
|
|
_call PFSEEK ; 戻り値 DX AX が現在位置
|
|
|
|
; 現在位置を返す
|
|
mov [BP+_DX],DX
|
|
jmp short _OK
|
|
|
|
;-------------------------------------------------------------------
|
|
; EndProcess
|
|
;
|
|
_Terminate:
|
|
; フックを戻してから終了
|
|
lds DX,CS:org_int21
|
|
msdos SetInterruptVector,21h
|
|
jmp short _Thru
|
|
|
|
;-------------------------------------------------------------------
|
|
; IOCTRL
|
|
_IOCTL:
|
|
mov cl,AL
|
|
mov AX,1
|
|
shl AX,cl
|
|
test AX,CS:IOCTL_table
|
|
jnz short _CheckHandle
|
|
jmp short _Thru
|
|
|
|
IOCTL_table dw 0001010011001111b
|
|
; bit
|
|
; 0 Get IOCTL Data
|
|
; 1 Set IOCTL Data
|
|
; 2 Recieve IOCTL Character
|
|
; 3 Send IOCTL Character
|
|
; 6 Get Input IOCTL Status
|
|
; 7 Get Output IOCTL Status
|
|
; a IOCTL is Redirected Handle
|
|
; c Generic IOCTL (for handle)
|
|
|
|
;-------------------------------------------------------------------
|
|
; ハンドルのチェック
|
|
_CheckHandle2:
|
|
mov CX,DI ; ハンドルチェック
|
|
je short _Error ; エラーにしないでクローズする
|
|
; 方がよいかも
|
|
|
|
_CheckHandle:
|
|
cmp BX,DI ; ハンドルチェック
|
|
je short _Error
|
|
|
|
;-------------------------------------------------------------------
|
|
_Thru:
|
|
dec CS:on_hook
|
|
; mov CX,[org_int21.ofst]
|
|
; mov AX,[org_int21.sgmt]
|
|
; xchg CX,[BP+_CX]
|
|
; xchg AX,[BP+_AX]
|
|
; pop ES DS DI SI BP BX BX DX
|
|
push word ptr [BP+_FLAGS]
|
|
popf
|
|
; retf
|
|
pop ES
|
|
pop DS
|
|
popa
|
|
cli
|
|
jmp dword ptr CS:org_int21
|
|
|
|
;-------------------------------------------------------------------
|
|
_Error:
|
|
or byte ptr [BP+_FLAGS],01h ; stc
|
|
mov AX,1 ; 適切なエラーコードを返すべきだが
|
|
; とりあえず固定で1を返す
|
|
jmp short i_return
|
|
|
|
;-------------------------------------------------------------------
|
|
_OK:
|
|
and byte ptr [BP+_FLAGS],0feh ; clc
|
|
|
|
i_return:
|
|
mov [BP+_AX],AX
|
|
dec CS:on_hook
|
|
pop ES
|
|
pop DS
|
|
; assume DS:NOTHING
|
|
popa ; pop DI SI BP SP BX DX CX AX
|
|
iret
|
|
pfint21 endp ; }
|