
; Public Domain

%include "lmacros3.mac"

%include "eld.mac"
%include "eldcall.mac"
%include "elddata.mac"
%include "amis.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 "Install N extension for B: placeholder."


	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 "FDBPLACE"
at eldiListing,		asciz _ELD_LISTING
	iend

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

install:
	mov ah, 08h
	push bx
	xor dl, dl
	int 13h
	cmp dl, 2
	pop es
	jb @F
reloc	mov dx, msg.noneed
internaldatarelocation
	mov ax, 0E71h
.specificerror:
	extcallcall setrc
	extcallcall putsz
	xor ax, ax
	retf

@@:
reloc	mov byte [es:resident_real_amount], dl
internalcoderelocation

	mov bx, resident_size_p
	extcall loader_prepare_resident
	jc .specificerror

	mov es, dx
	mov di, resident.image - resident
	 push cs
	 pop ds
reloc	mov si, resident.image
internalcoderelocation
	mov cx, resident_size_w - words(resident.image - resident)
	rep movsw		; place resident

	xor bx, bx
	mov ds, bx		; => IVT
	mov bl, 13h * 4		; ds:bx -> interrupt vector
	cli
	push ds
	lds di, [bx]		; ds:di = vector
	mov word [es:i13.next + 0 - resident], di
	mov word [es:i13.next + 2 - resident], ds
				; save prior vector
	pop ds
	mov word [bx], i13 - resident
	mov word [bx + 2], es	; change vector to our handler
	sti

	mov ax, 40h
	mov ds, ax
	mov ax, [10h]
	test al, 1
	jz .2
	cmp al, 0100_0000b
	jae @F
.2:
	or al, 1
	and al, ~ 1100_0000b
	or al, 0100_0000b
	mov [10h], ax		; adjust int 11h equipment word
@@:

	 push ss
	 pop ds
	 push ss
	 pop es
reloc	testopt [relocateddata], 4
linkdatarelocation options7, -3
	jnz @F
reloc	mov dx, msg.installed
internaldatarelocation
	extcallcall putsz
@@:
	xor ax, ax
	retf

help:
	lodsb
	extcallcall chkeol
reloc	mov dx, msg.help
internaldatarelocation
	extcallcall 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


	align 16, nop
resident:
	times 16 db 0		; for NEXT image ident
.image:
signature:
.ven:	fill 8,32,db "ecm"		; vendor
.prod:	fill 8,32,db "FDBPLACE"		; product
.deac:	asciz "Drive B: placeholder"

resident_real_amount:
	db 0

iispentry i13
	test dl, dl
	js .chain
	cmp ah, 08h
	je .func08
	cmp dl, 2
	jae .chain
	cmp dl, byte [cs:resident_real_amount - resident]
	jae .dispatch
.chain:
	jmp far [cs:.next - resident]

.func08:
	cmp dl, 2
	jae @F
	cmp dl, byte [cs:resident_real_amount - resident]
	jae .func08_placeholder
@@:
	stc
	 pushf
	 push cs
	call .chain
	jc .ret_CF
	cmp dl, 2
	jae .ret_NC
	mov dl, 2
.ret_NC:
	clc
.ret_CF:
	push bp
	mov bp, sp
	rcr byte [bp + 6], 1	; flip
	rol byte [bp + 6], 1	; flop
	pop bp
	iret

.func08_placeholder:
	mov dx, 2 + (1 << 8)	; 2 drives, max head = 1 (2 heads)
	xor ax, ax		; 0
	mov bl, 1		; 360 KiB drive
	mov cx, 9 + (39 << 8)	; max sector = 9 (9 sectors as it is 1-based),
				;  max cylinder = 39 (40 cylinders)
	xor di, di
	mov es, di
	jmp .ret_NC

.dispatch:
	cmp ah, 15h
	je .func15
	cmp ah, 01h
	jb .func00
	je .func01
	cmp ah, 03h
	jb .func02
	je .func03
	cmp ah, 05h
	jb .func04
	je .func05
.func_invalid:
	mov ah, 01h
.set_error_and_ret:
	call .set_error
	jmp .ret_CF

.set_error:
	push ds
	push ax
	mov ax, 40h
	mov ds, ax
	pop ax
	mov byte [41h], ah
	pop ds
	stc
	retn

.func15:
	mov ah, 01h		; diskette without changeline support
	jmp .ret_NC

.func00:
	 pushf
	 push cs
	call .chain
	jmp .ret_CF

.func01:
	push ds
	push ax
	mov ax, 40h
	mov ds, ax		; => BDA
	pop ax
	mov al, byte [41h]	; get status
	mov ah, al		; ah == al
	pop ds
	cmp al, 1		; CY if status == 0
	cmc			; NC if status == 0
	jmp .ret_CF

.func02:		; CHS read
.func03:		; CHS write
.func04:		; CHS verify
	mov al, 0		; 0 sectors done

.func05:		; CHS format
	mov ah, 80h		; timeout / drive not ready
	jmp .set_error_and_ret

	align 16, nop
	endarea resident


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

msg:
.linebreak:		db 13,10
.empty:			asciz

uinit_data: equ $
.installed:		asciz "FDBPLACE installed.",13,10
.keyword_help:		asciz "HELP"
.help:		db "This ELD installs an N extension for a drive B: placeholder.",13,10
		db "This ELD can only be used by the lDOS pre-boot loader.",13,10
		db 13,10
		db "Run with INSTALL keyword to install.",13,10
		asciz
.noneed:
	asciz "No need for FDBPLACE N extension, already have >= 2 diskette drives!",13,10

	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

%include "eldlink.asm"

	align 16
code_size equ $ - code
