
; Public Domain

; test install command: install; patchqry; patchqry uninstall
; test run command: ; .; .

%include "lmacros3.mac"

%include "eld.mac"
%include "eldcall.mac"
%include "elddata.mac"


%assign _CATCHINT0C 0
%assign _CATCHINT0D 0
%assign _CATCHINTFAULTCOND 0
%assign _LOADER 0
%assign _DEBUG 0
%assign _DELAY_BEFORE_BP 0
%assign _DHIGHLIGHT 0
%assign _GETLINEHIGHLIGHT 0
%assign _IMMASM 0
%assign _INPUT_FILE_BOOT 0
%assign _INPUT_FILE_HANDLES 0
%assign _MS_0RANGE_COMPAT 0
%assign _PM 1
%assign _BREAK_INSTALLDPMI 0
%assign _RH 0
%assign _SYMBOLIC 0
%assign _VXCHG 0
%include "options.mac"


	cpu 8086

	addsection RELOCATEDDATA, nobits vstart=_ELD_RELOC_VSTART
relocateddata:

	addsection HEADER, start=0

	istruc ELD_HEADERX
at eldhxHeader
		; ELD executable header
	istruc ELD_HEADER
at eldhSignature,	db "ELD1"
			db 0,0,0
			db 26
at eldhCodeOffset,	dd CODEOFFSET
at eldhCodeImageLength,	dw code_size
at eldhCodeAllocLength,	dw 0
at eldhDataOffset,	dd DATAOFFSET
at eldhDataImageLength,	dw data_size
at eldhDataAllocLength,	dw total_data_size - data_size
at eldhCodeEntrypoint,	dw linker - code
at eldhReserved
at eldhExtensionSize,	dw header_extension_end - $$
	iend
at eldhxDescriptionOffset,	dd description
at eldhxHelpOffset,		dd DATAOFFSET + msg.help - datastart
PUT_ELDHX_DATETIME_OFFSET
header_extension_end:
	iend

description:		asciz "Patch lDOS iniload query patch site."


	align 16, db 0

	eldstrict on

CODEOFFSET equ $ - $$
	addsection CODE, follows=HEADER vstart=_ELD_CODE_VSTART
%define CODEFIXUP - code + 0
code:
		; ELD instance header
	istruc ELD_INSTANCE
at eldiStartCode
at eldiEndCode
at eldiStartData
at eldiEndData
at eldiIdentifier,	fill 8, 32, db "PATCHQRY"
at eldiListing,		asciz _ELD_LISTING
	iend


command:
	jmp strict short .entry
.chain:
	extcall cmd3_not_ext, required	; must NOT be extcallcall
	times 10 - ($ - command) nop
.entry:
	push si
	cmp al, '-'
	jne @F
	extcallcall skipcomma
@@:
	dec si

reloc	mov dx, msg.patchqry
internaldatarelocation
	extcallcall isstring?
	je .ours
	pop si
	dec si
	lodsb
	jmp .chain

.ours:
	pop ax
	extcallcall skipcomma
	dec si
reloc2	mov word [relocateddata], relocateddata
linkdatarelocation lastcmd, -4
linkdatarelocation dmycmd
reloc	mov dx, relocateddata
linkdatarelocation msg.uninstall
	extcallcall isstring?
	je uninstall

	call run
	extcallcall cmd3

uninstall:
	lodsb
	extcallcall chkeol

	call get_es_ext

	push es
	pop ds
	xor bx, bx		; = 0 (no prior, modify ext_command_handler)
reloc	mov di, command		; di -> us
internalcoderelocation
reloc	mov si, word [ss:relocateddata]
linkdatarelocation ext_command_handler
				; si -> first
	test si, si		; none installed ?
	jz .error		; error -->

.loop:
	cmp di, si		; found ?
	je .bx			; yes, use bx -->
	mov bx, si		; bx -> prior handler
	lodsw			; skip entrypoint jmp strict short
	lodsb			; get first byte of chainer
	cmp al, 0E9h		; expecting jmp near ?
	jne .error		; no, error -->
	lodsw			; get rel16 displacement
	add si, ax		; -> next handler
	jmp .loop

.bx:
	test bx, bx		; any prior ?
	jnz .bxnz		; yes -->
	scasw			; skip entrypoint jmp strict short
	cmp byte [di], 0E8h	; is it a call to cmd3_not_ext ?
	jne @F			; no -->
				; yes, reset ext_command_handler to zero
.setbx:
reloc	mov word [ss:relocateddata], bx
linkdatarelocation ext_command_handler
	jmp .done

@@:
	cmp byte [di], 0E9h	; validate
	jne .error		; failure -->
	inc di			; -> rel16 displacement
	mov bx, word [di]	; get displacement
	scasw			; -> after jmp near
	add bx, di		; -> next handler
	jmp .setbx		; set ext_command_handler to next

.bxnz:
	mov si, bx		; -> prior handler with us as downlink
	xchg di, si		; si -> ours, di -> prior
	cmpsw			; skip entrypoint jmp strict short
	movsb			; copy 0E8h/0E9h
	lodsw			; ax = near rel16 displacement
	add ax, si		; add in our base (= absolute offset)
	sub ax, di
	dec ax
	dec ax			; subtract new base (= relative displacement)
	stosw			; store new rel16 displacement
	movsw			; jmp strict short
	movsw			; linkcall target
	movsb			; trailer
.done:
reloc	clropt [code + eldiFlags], eldifResident
internalcoderelocation -3	; mark block as free
reloc	mov dx, msg.uninstall_done
internaldatarelocation
@@:
	push ss
	pop ds
	extcallcall putsz
	extcallcall cmd3	; return

.error:
	mov ax, 0E01h
	extcallcall setrc
reloc	mov dx, msg.uninstall_error
internaldatarelocation
	jmp @B


get_es_ext:
reloc	mov es, word [relocateddata]
linkdatarelocation extdssel
	extcallcall ispm
	jz @F
reloc	mov es, word [relocateddata]
linkdatarelocation extseg
@@:
	retn


%assign ELD 1
%assign _PM 1
%assign _LOADER 0
%assign _ONLY386 0
%assign _ONLYNON386 0
%assign _SWHILEBUFFER 0
%assign _SCOUNT 1
%assign _SDUMP 1
%assign _SDUMPDISPLACEMENT 1
%assign _SREVERSE 1
%assign _AUXBUFFSIZE 8192 + 16
%define lDEBUG_CODE CODE
%define lDEBUG_DATA_ENTRY DATA
%define dualcall call
	cpu 8086
%assign _WPT_LABELS 0

%include "386.mac"


run:
	push ss
	pop es
	extcallcall skipcomma
	extcallcall iseol?
	je onlinehelp
	lframe
	lvar word, addresssegment
	lvar dword, addressstart
	lvar dword, addressend
	lvar word, base
	lvar word, replace_plus_minus
	lvar word, first
	lvar word, initial_msg
	lvar word, separator_msg
	lvar word, final_msg
	lvar word, value
	lenter
	xor dx, dx
	 push dx
	lvar word, mode
	 push dx
	lvar word, offset
	 push dx
	lvar word, addressset
	 push dx
	lvar word, wantreplace
	 push dx
	lvar word, want
	 push dx
	lvar word, wantplus
	 push dx
	lvar word, wantminus
	dec dx
	 push dx
	lvar word, query

.loopkeyword:
	dec si
reloc	mov dx, msg.keyword_range
internaldatarelocation
	extcallcall isstring?
	je .range
reloc	mov dx, msg.keyword_show
internaldatarelocation
	extcallcall isstring?
	je .show
reloc	mov bx, table
internaldatarelocation
@@:
	mov dx, [bx]
	test dx, dx
	jz .no_keyword
	extcallcall isstring?
	je .got
	lea bx, [bx + 3]
	jmp @B
.no_keyword:
	extcallcall skipcomma
	extcallcall iseol?
	je .show_dec
.error_keyword:
	dec si
reloc	mov dx, msg.invalidkeyword
internaldatarelocation
	extcallcall putsz
	mov dx, si
	xor cx, cx
@@:
	inc cx
	lodsb
	cmp al, 32
	je @F
	cmp al, 9
	je @F
	cmp al, ':'
	je @F
	cmp al, ','
	je @F
	cmp al, '='
	je @F
	extcallcall iseol?
	jne @B
@@:
	dec cx
	extcallcall puts
reloc	mov dx, msg.linebreak
internaldatarelocation
	extcallcall putsz
	mov ax, 0E80h
	extcallcall setrc
	jmp .done

.range:
	extcallcall skipcomma
reloc	mov bx, [relocateddata]
linkdatarelocation reg_cs
	_386_PM_o32
	xor dx, dx		; init edxh = 0
	_386_PM_o32
	xor cx, cx		; init ecxh = 0
	mov cx, 4096
	extcallcall getrange
	mov byte [bp + ?addressset], -1
	mov word [bp + ?addresssegment], bx
	_386_PM_o32
	mov word [bp + ?addressstart], dx
	_386_PM_o32
	mov word [bp + ?addressend], cx
	extcallcall skipcomm0
	jmp .loopkeyword

.show_dec:
	dec si
.show:
	lodsb
	extcallcall chkeol
	dec si
	mov byte [bp + ?mode], -1
	jmp .getnumber

.got:
	mov al, byte [bx + 2]
	mov byte [bp + ?mode], al
	mov byte [bp + ?offset], al
.getnumber:
	mov byte [bp + ?first], -1
	jmp @F
.loopnumber:
	mov byte [bp + ?first], 0
@@:
	extcallcall skipcomma
	extcallcall iseol?
	je .do

	mov word [bp + ?base], 10
	and word [bp + ?replace_plus_minus], 0
	cmp al, '+'
	jne @F
	extcallcall skipcomma
	mov byte [bp + ?replace_plus_minus], 1
	jmp .gotplus

@@:
	cmp al, '-'
	jne @F
	extcallcall skipcomma
	mov byte [bp + ?replace_plus_minus], 2
	jmp .gotminus

@@:
	mov byte [bp + ?wantreplace], -1
.gotplus:
.gotminus:
	cmp al, '('
	je .expr

	dec si
	mov bx, si
	xor di, di
.numberpre:
	lodsb
	cmp al, '_'
	je .numberpre
	cmp al, '0'
	jb .predone
	cmp al, '9'
	jbe .numberpre
	extcallcall uppercase
	cmp al, 'A'
	jb .predone
	cmp al, 'Z'
	jbe .numberpre
.predone:
	dec si
	mov cx, si
	sub cx, bx
	jz error
	dec si
	lodsb
	extcallcall uppercase
	mov ah, al
	cmp al, 'H'
	jne @F
	mov byte [bp + ?base], 16
	dec si
	inc di
	jmp .donumber

@@:
	cmp byte [bx], '0'
	jne @F
	mov al, [bx + 1]
	extcallcall uppercase
	cmp al, 'X'
	jne .notx
	mov byte [bp + ?base], 16
	inc bx
	inc bx
	jmp .donumber

.notx:
	cmp al, 'B'
	jne @F
	mov byte [bp + ?base], 2
	inc bx
	inc bx
	jmp .donumber

@@:
	cmp ah, 'B'
	jne @F
	mov byte [bp + ?base], 2
	dec si
	inc di
	jmp .donumber

@@:
.donumber:
	xchg bx, si
	cmp bx, si
	je error

	xor dx, dx
.loopdigits:
	cmp si, bx
	jae .havedigits
	lodsb
	cmp al, '_'
	je .loopdigits
	extcallcall uppercase
	sub al, '0'
	cmp al, 9
	jbe @F
	sub al, -('9' + 1) +'A'
@@:
	cmp al, [bp + ?base]
	jae .invalid
	mov ah, 0		; ax = next digit
	push ax
	mov ax, [bp + ?base]
	mul dx			; (dx:)ax = prior times base
	pop dx			; dx = next digit
	test ah, ah		; > 255 ?
	jnz .invalid
	add dx, ax		; dx = prior times base plus next digit
	jc .invalid
	test dh, dh
	jnz .invalid
	jmp .loopdigits

.expr:
	lodsb
	extcallcall getbyte
	cmp al, ')'
	jne error
	db __TEST_IMM16
.havedigits:
	add si, di
	extcallcall skipcomma
	dec si
	mov byte [bp + ?query], 0

	cmp byte [bp + ?replace_plus_minus], 1
	je .doplus
	ja .dominus
.doreplace:
	rol byte [bp + ?first], 1
	jc @F
.invalid:
reloc	mov dx, msg.invalidchoice
internaldatarelocation
	extcallcall putsz
	mov ax, 0E81h
	extcallcall setrc
	jmp .done

@@:
	mov byte [bp + ?want], dl
	mov byte [bp + ?wantplus], 0
	mov byte [bp + ?wantminus], 0
	jmp .loopnumber

.doplus:
	or byte [bp + ?wantplus], dl
	not dl
	and byte [bp + ?wantminus], dl
	jmp .loopnumber

.dominus:
	or byte [bp + ?wantminus], dl
	not dl
	and byte [bp + ?wantplus], dl
	jmp .loopnumber

.do:
	rol byte [bp + ?addressset], 1
	jc .gotaddr
reloc	mov bx, word [relocateddata]
linkdatarelocation reg_cs
	extcallcall verifysegm_or_error
	mov word [bp + ?addresssegment], bx
	_386_PM_o32
	xor dx, dx
	_386_PM_o32
	mov word [bp + ?addressstart], dx
	mov dx, 4096 + 256 - 1
	_386_PM_o32
	mov word [bp + ?addressend], dx

.gotaddr:

reloc	testopt [relocateddata], opt7_debug_run
linkdatarelocation options7, -3
	jz @F

reloc	mov di, msg.dump.offset
internaldatarelocation
	mov al, [bp + ?offset]
	extcallcall hexbyte

reloc	mov di, msg.dump.mode
internaldatarelocation
	mov al, [bp + ?mode]
	extcallcall hexbyte

reloc	mov di, msg.dump.wantplus
internaldatarelocation
	mov al, [bp + ?wantplus]
	extcallcall hexbyte

reloc	mov di, msg.dump.wantminus
internaldatarelocation
	mov al, [bp + ?wantminus]
	extcallcall hexbyte

reloc	mov di, msg.dump.want
internaldatarelocation
	mov al, [bp + ?want]
	extcallcall hexbyte

reloc	mov di, msg.dump.wantreplace
internaldatarelocation
	mov al, [bp + ?wantreplace]
	extcallcall hexbyte

reloc	mov dx, msg.dump
internaldatarelocation
	extcallcall putsz
@@:

	houdini
	mov es, word [bp + ?addresssegment]
	_386_PM_o32
	mov cx, word [bp + ?addressend]
	_386_PM_o32
	mov di, word [bp + ?addressstart]
	_386_PM_o32
	sub cx, di	; = 0 for 1-byte range,
			;  = FFFFh for 64 KiB range
	jb .error_notfound
	_386_PM_o32
	sub cx, strict byte pattern.size - 1
			; if pattern were 1 byte: -0, = 0 for 1-byte range
			;  = FFFFh for 64 KiB range
	jae @F
.error_notfound:
reloc	mov dx, msg.notfound
internaldatarelocation
	extcallcall putsz
	mov ax, 0E82h
	extcallcall setrc
	jmp .done

@@:
	_386_PM_o32
	inc cx		; if pattern were 1 byte: +1, = 1 for 1-byte range
			;  = (1)0000h for 64 KiB range

.loopmatch:
	_386_PM_o32
	push di
	_386_PM_o32
	push cx
_386_PM	xor esi, esi
reloc	mov si, pattern
internaldatarelocation
_386_PM	xor ecx, ecx
	mov cx, pattern.size

_386_PM	mov ax, [es:edi + pattern.patchword - pattern]
_386_PM	jmp @F
	mov ax, [es:di + pattern.patchword - pattern]
@@:
	mov word [si + pattern.patchword - pattern], ax

	_386_PM_a32
	repe cmpsb

	_386_PM_o32
	pop cx
	_386_PM_o32
	pop di
	je .found
	_386_PM_o32
	inc di
	_386_PM_a32
	loop .loopmatch
	jmp .error_notfound

.found:
	_386_PM_o32
	add di, strict byte pattern.patchword - pattern
	_386_PM_o32			; es:edi -> patch word
	mov si, di			; es:esi -> likewise
	_386_PM_o32
	xor cx, cx			; ecxh = 0
	mov cx, word [bp + ?offset]	; ecx = offset

	_386_PM_a32
	add si, cx			; skip (e)cx bytes
	_386_PM_a32
	add di, cx			; skip (e)cx bytes

	rol byte [bp + ?query], 1
	jc @F

	_386_PM_o32
	push si

	_386_PM_a32
	es lodsb
	rol byte [bp + ?wantreplace], 1
	jnc .noreplace
	mov al, byte [bp + ?want]
.noreplace:
	or al, byte [bp + ?wantplus]
	mov ah, byte [bp + ?wantminus]
	not ah
	and al, ah
	_386_PM_a32
	stosb

reloc	mov dx, msg.updated
internaldatarelocation
	extcallcall putsz

	_386_PM_o32
	pop si
@@:

	mov di, 1			; di = 1
	cmp byte [bp + ?mode], 255
	jne @F
	mov byte [bp + ?offset], 0
	inc di				; di = 2
@@:

.looplimit:
	push di
reloc	mov word [bp + ?initial_msg], msg.linebreaktab
internaldatarelocation
reloc	mov word [bp + ?separator_msg], msg.empty
internaldatarelocation
reloc	mov word [bp + ?final_msg], msg.empty
internaldatarelocation

	_386_PM_o32
	es lodsb

	push es
	 push ss
	 pop es
	mov byte [bp + ?value], al

	mov bx, word [bp + ?offset]
	add bx, bx
reloc	mov dx, [word bx + unitnames]
internaldatarelocation
	extcallcall putsz

reloc	mov di, msg.query.value
internaldatarelocation
	extcallcall hexbyte
reloc	mov dx, msg.query
internaldatarelocation
	extcallcall putsz

	xor cx, cx
.loopvalue:
	mov dx, 1
	shl dx, cl
	test al, dl
	jz .nextvalue
	xchg ax, dx
reloc	mov di, msg.queryflag.value
internaldatarelocation
	extcallcall hexbyte
	xchg ax, dx

	mov bx, cx
	add bx, bx
reloc	mov dx, [word bx + flagnames]
internaldatarelocation
	test dx, dx
	jnz @F
reloc	mov dx, msg.flagname_unknown
internaldatarelocation
@@:
	push dx
	mov dx, word [bp + ?initial_msg]
	extcallcall putsz
	mov dx, word [bp + ?separator_msg]
	extcallcall putsz
reloc	mov dx, msg.queryflag
internaldatarelocation
	extcallcall putsz
	pop dx
	extcallcall putsz

reloc	mov word [bp + ?initial_msg], msg.empty
internaldatarelocation
reloc	mov word [bp + ?separator_msg], msg.linebreaktab
internaldatarelocation
reloc	mov word [bp + ?final_msg], msg.empty
internaldatarelocation

.nextvalue:
	inc cx
	cmp cl, 8
	jb .loopvalue

	mov dx, word [bp + ?final_msg]
	extcallcall putsz
reloc	mov dx, msg.linebreak
internaldatarelocation
	extcallcall putsz

	pop es
	pop di

	inc byte [bp + ?offset]
	dec di
	jnz .looplimit

.done:
	lleave
	retn


extcallcall error

onlinehelp:
reloc	mov dx, msg.onlinehelp
internaldatarelocation
	extcallcall putsz
reloc	mov si, flagnames
internaldatarelocation
	mov cx, 8
	mov dx, 1
.loop:
	lodsw
	test ax, ax
	jz .next
	xchg ax, dx
reloc	mov di, msg.onlinenumber.patch
internaldatarelocation
	extcallcall hexbyte
	push dx
reloc	mov dx, msg.onlinenumber
internaldatarelocation
	extcallcall putsz
	pop dx
	extcallcall putsz
reloc	mov dx, msg.linebreak
internaldatarelocation
	extcallcall putsz
	xchg dx, ax
.next:
	add dx, dx
	loop .loop
	retn

	eldcall_dump_callcall ELDCALL_CALLCALL_LIST

endinstalled equ ($ + CODEFIXUP + 15) & ~15


	align 2, db 0				; align on word boundary
		; Table of patches that are to be set NOP if not running on a 386.
writepatchtable patch_no386_table, PATCH_NO386_TABLE
%undef PATCH_NO386_TABLE

	align 2, db 0
		; Table of patches that are to be set NOP if running on a 386.
writepatchtable patch_386_table, PATCH_386_TABLE
%undef PATCH_386_TABLE


start:
	push si
reloc	mov dx, code
internalcoderelocation
reloc	testopt [relocateddata], has386
linkdatarelocation internalflags, -3
	jz @F
reloc	mov si, patch_386_table		; table of patches to set for 386+
internalcoderelocation
%if __patch_386_table_method == 1
	mov cx, patch_386_table_size_w
	call .patch1
%else
	call .patch2
%endif
	jmp .patch_code1_end

@@:
reloc	mov si, patch_no386_table	; table of patches to set for 16-bit CPU
internalcoderelocation
%if __patch_no386_table_method == 1
	mov cx, patch_no386_table_size_w
	call .patch1
%else
	call .patch2
%endif
	jmp .patch_code1_end

		; Complicated table patch code.
%if __patch_no386_table_method == 2 || __patch_386_table_method == 2
.patch2:
reloc	mov di, code_start		; initialise offset
internalcoderelocation
	xor ax, ax			; initialise ah
.looppatch2:
	cs lodsb
	add di, ax			; skip number of bytes to skip
	cmp al, 255			; really repositioning?
	jne .l2patch			; no -->
	xchg ax, di			; (to preserve ah)
	cs lodsw			; ax = new address
	add ax, dx
	xchg ax, di			; di = new address
.l2patch:
	cs lodsb
	mov cx, ax			; cx = number of bytes to patch
	jcxz .patchesdone		; end of table -->
	mov al, 90h			; patch to NOP
	rep stosb			; patch as many bytes as specified
	jmp short .looppatch2
%endif

		; Simple table patch code.
%if __patch_no386_table_method == 1 || __patch_386_table_method == 1
.patch1:
	jcxz .patchesdone
.looppatch1:
	cs lodsw			; load address of patch
	add ax, dx
	xchg bx, ax			; (set bx = ax, CHG ax)
	mov byte [es:bx], 90h		; patch
	loop .looppatch1
%endif
.patchesdone:
	retn

.patch_code1_end:
	pop si

	mov bx, es
	 push ss
	 pop es
	call skipcomma
	dec si
reloc	mov dx, relocateddata
linkdatarelocation msg.install
	call isstring?
	je install
reloc	mov dx, msg.keyword_help
internaldatarelocation
	call isstring?
	je help
	call run
@@:
	call uninstall_oneshot
	xor ax, ax
	retf

help:
	lodsb
	call chkeol
reloc	mov dx, msg.help
internaldatarelocation
	call putsz
	jmp @B


uninstall_oneshot:
reloc	testopt [ss:relocateddata], 1
linkdatarelocation options7, -3
	jnz @F

reloc	mov ax, word [cs:code + eldiEndCode]
internalcoderelocation
reloc	sub ax, word [cs:code + eldiStartCode]
internalcoderelocation
reloc	sub word [relocateddata], ax
linkdatarelocation extseg_used

reloc	mov ax, word [cs:code + eldiEndData]
internalcoderelocation
reloc	sub ax, word [cs:code + eldiStartData]
internalcoderelocation
reloc	sub word [relocateddata], ax
linkdatarelocation extdata_used
@@:
	retn


DATAOFFSET equ CODEOFFSET + code_size
	addsection DATA, follows=CODE vstart=_ELD_DATA_VSTART
%define DATAFIXUP - datastart + 0
datastart:
PUT_ELD_DATETIME

	align 2, db 0
unitnames:
reloc	dw msg.unitname_diskette
internaldatarelocation
reloc	dw msg.unitname_harddisk
internaldatarelocation

	align 2, db 0
flagnames:
reloc	dw msg.flagname_chs
internaldatarelocation
reloc	dw msg.flagname_lba
internaldatarelocation
reloc	dw msg.flagname_no_geometry
internaldatarelocation
reloc	dw msg.flagname_no_multi
internaldatarelocation
	dw 0
	dw 0
reloc	dw msg.flagname_no_recheck
internaldatarelocation
reloc	dw msg.flagname_apply_ldp
internaldatarelocation

	align 2, db 0
pattern:
.:	mov dl, byte [bp + 40h]
	mov ax, 0
.patchword: equ $ - 2
	test dl, dl
	jns @F
	xchg al, ah
@@:
.size: equ $ - .
%if .size & 1
 %error Unexpected odd size
%endif

table:
reloc	dw msg.keyword_diskette
internaldatarelocation
	db 0
reloc	dw msg.keyword_floppy
internaldatarelocation
	db 0
reloc	dw msg.keyword_harddisk
internaldatarelocation
	db 1
reloc	dw msg.keyword_hdd
internaldatarelocation
	db 1
reloc	dw msg.keyword_fixeddisk
internaldatarelocation
	db 1
	dw 0		; end of table

msg:
.unitname_diskette:	asciz "Diskette"
.unitname_harddisk:	asciz "Hard disk"
.linebreaktab:		db 13,10,9
.empty:			asciz
.query:			db " query patch = "
.query.value:		asciz "--h"
.flagname_unknown:	asciz "Unknown"
.queryflag:
.queryflag.value:	asciz "--h: "
.flagname_chs:		asciz "Force CHS"
.flagname_lba:		asciz "Force LBA"
.flagname_no_geometry:	asciz "No query geometry"
.flagname_no_multi:	asciz "Force single sector reads"
.flagname_no_recheck:	asciz "Do not re-check (TestWrit)"
.flagname_apply_ldp:	asciz "Apply to LDP (lDebug)"
.invalidkeyword:	asciz "Error: Invalid unit name: "
.invalidchoice:		asciz "Error: Invalid query patch choice",13,10
.keyword_diskette:	asciz "DISKETTE"
.keyword_floppy:	asciz "FLOPPY"
.keyword_harddisk:	asciz "HARDDISK"
.keyword_hdd:		asciz "HDD"
.keyword_fixeddisk:	asciz "FIXEDDISK"
.keyword_range:		asciz "RANGE"
.keyword_show:		asciz "SHOW"
.patchqry:		asciz "PATCHQRY"
.notfound:		asciz "Error: Query patch site not found",13,10
.updated:		asciz "Query patch updated",13,10
.onlinehelp:		db "Usage: patchqry [DISKETTE|HARDDISK] [number]",13,10
			db 13,10
			db "Supported query patch flags:"
.linebreak:		db 13,10
			asciz
.onlinenumber:		db " "
.onlinenumber.patch:	asciz "--h: "
.dump:			db "offset="
.dump.offset:		db "--h mode="
.dump.mode:		db "--h wantplus="
.dump.wantplus:		db "--h wantminus="
.dump.wantminus:	db "--h want="
.dump.want:		db "--h wantreplace="
.dump.wantreplace:	db "--h",13,10
			asciz
.uninstall_done:	db "PATCHQRY uninstalled."
%if _ELD_RECLAIM_HINT
			db " (Don't forget to use reclaim.eld)"
%endif
			asciz 13,10
.uninstall_error:	asciz "PATCHQRY unable to uninstall!",13,10

uinit_data: equ $
.installed:		asciz "PATCHQRY installed.",13,10
.keyword_help:		asciz "HELP"
.help:		db "This ELD can be installed residently or used transiently.",13,10
		db 13,10
		db "Usage: patchqry [DISKETTE|HARDDISK] [number]",13,10
		db 13,10
		db "Supported query patch flags:",13,10
		db " 01h: ","Force CHS",13,10
		db " 02h: ","Force LBA",13,10
		db " 04h: ","No query geometry",13,10
		db " 08h: ","Force single sector reads",13,10
		db " 40h: ","Do not re-check (TestWrit)",13,10
		db " 80h: ","Apply to LDP (lDebug)",13,10
		asciz

	align 16, db 0
init_data_end:
data_size equ $ - datastart
transient_data_size equ data_size

	absolute uinit_data

	alignb 16
uinit_data_end:
resident_data_end:
resident_data_size equ resident_data_end - datastart

%if uinit_data_end >= init_data_end
 total_data_size equ $ - datastart
%else
 total_data_size equ init_data_end - datastart
%endif
%assign _DATA_SIZE total_data_size


	usesection CODE

install:
	lodsb
	extcall chkeol

	houdini
	mov es, bx		; => ext seg (writable)

	mov ax, endresident - endinstalled
reloc	sub word [es:code + eldiEndCode], ax
internalcoderelocation		; adjust size
reloc	sub word [relocateddata], ax
linkdatarelocation extseg_used	; adjust size

%if (transient_data_size - resident_data_size) > 0
	mov ax, transient_data_size - resident_data_size
reloc	sub word [es:code + eldiEndData], ax
internalcoderelocation		; adjust size
reloc	sub word [relocateddata], ax
linkdatarelocation extdata_used	; adjust size
%endif

reloc	mov bx, word [relocateddata]
linkdatarelocation ext_command_handler
				; -> prior
reloc	mov di, command		; -> our handler
internalcoderelocation
	test bx, bx		; installing as first ?
	jz .only_first		; yes, simple --> (leave as extcall cmd3_not_ext)
	scasw			; skip entrypoint jmp strict short
	mov al, 0E9h		; = jmp near opcode
	stosb			; store
	xchg ax, bx		; ax -> next handler
	sub ax, di
	dec ax
	dec ax			; ax = ax - (di + 2)
	stosw			; store our downlink as rel16 displacement

.only_first:
reloc	setopt [es:code + eldiFlags], eldifResident
internalcoderelocation -3	; mark block as resident
reloc2	mov word [relocateddata], command
linkdatarelocation ext_command_handler, -4
internalcoderelocation		; -> our entrypoint

reloc	testopt [relocateddata], 4
linkdatarelocation options7, -3
	jnz @F
reloc	mov dx, msg.installed
internaldatarelocation
	call putsz
@@:
	xor ax, ax
	retf


%include "eldlink.asm"

	align 16
code_size equ $ - code
