; maildb/asm - kjw/bqsd - version 2.00 - 01/83
;
; revised 02/24/83 - kjw
;
	SUBTTL	'<maildb/asm - REPACK module>'
;
;	system data usage
;
;	+7,8,9		- current logical record # read
;	+10,11,12	- current physical record # read
;	+13		- data offset in I/O buffer
;	+14,15,16	- unused
;	+17,18,19	- unused
;	+20,21,22	- last record #
;	+23		- I/O buffer offset last record
;	+24,25,26	- physical sector
;
RECOVER	SET	5,(IY+0)	;set recovery mode
	JR	PACREC		;go common
;
REPACK	LD	HL,MSGB1	;'repacking'
	CALL	GETDRV		;get drive from user
	JP	C,MENU		;go on BREAK
;
	CALL	LOCFCB		;locate FCB block
	BIT	7,(IX+0)	;file open?
	JR	Z,REPACK	;go if NOT open!
	RES	5,(IY+0)	;set REPACK mode
;
PACREC	CALL	INITCNT		;clear counters
	LD	(IY+1),0	;clear buffer flags
;
	BIT	5,(IY+0)	;repack or recover?
	JR	NZ,RECIT	;go if recover
	LD	HL,MSGB1A	;'repacking'
	CALL	DISPLAY
	CALL	PACK1		;repack 1 drive
	JR	Z,RECEND	;go if OK
	CALL	BERROR		;display error
	JP	MENU		;back to menu!
;
;	recovery mode, check drives requested
;
RECIT	LD	BC,DRIVES<8+0	;B=counter, C=drive
RECLP	PUSH	BC		;save BC
	LD	A,C		;get drive #
	CALL	LOCFCB		;locate the FCB
	LD	HL,MSGB2	;'recovering'
	CALL	DISPLAY		;display message
	BIT	7,(IX+0)	;drive open?
	JR	Z,RECNX		;nope, go!
	BIT	5,(IX+0)	;recovery issued?
	JR	Z,RECNX		;go if not indicated
	CALL	REC1		;count this record
	RES	5,(IX+0)	;set done!
	JR	Z,RECNX		;go if no error
	CALL	BERROR		;display error message
;
RECNX	POP	BC		;restore
	INC	C		;bump drive #
	DJNZ	RECLP		;go for 8 drives
;
RECEND	BIT	5,(IY+0)	;recover?
	RES	5,(IY+0)	;set done!
	JP	NZ,EXIT		;go if yes
;
;	display pack specifics
;
	LD	DE,MSGBXB	;'records removed'
	LD	B,(IY+35)	;get counter B
	LD	H,(IY+36)
	LD	L,(IY+37)
	CALL	BINASC		;binary => ascii
	LD	HL,MSGBX	;'completed'
	CALL	DISPLAY		;display message
	CALL	INKEY		;wait for a key
	LD	A,(IY+35)	;get # deleted
	OR	(IY+36)
	OR	(IY+37)		;anything?
	JP	NZ,MENU		;go if not
	LD	A,'$'		;get old sort flag
OLDPACK	EQU	$-1
	BIT	6,A		;was file sorted before?
	JP	Z,MENU		;go if not!
	SET	6,(IX+0)	;reset sorted bit
	JP	MENU		;back to local menu
;
;	recovery mode on drive (IX)
;
REC1	LD	B,0		;set current record #
	LD	H,B
	LD	L,B		;BHL = 0
;
REC1LP	LD	(IY+7),B	;set current record
	LD	(IY+8),H
	LD	(IY+9),L
;
	CALL	STROBE		;strobe keyboard
	CP	BREAK		;break key?
	JP	Z,ABORT		;yes, abort operation!
;
	CALL	GETPACK		;get a record
	JR	Z,RECNEX	;no error, go!
	CP	1CH		;end of file?
	JR	Z,REC1END	;yes, done!
	CP	1DH		;beyond file?
	RET	NZ		;go on error!
;
;	completed, set count and repack data
;
REC1END	LD	B,(IY+7)	;get current rec #
	LD	H,(IY+8)
	LD	L,(IY+9)
	CALL	DECBHL		;backspace one record
	LD	(IX+7),B	;set as # records avail
	LD	(IX+8),H
	LD	(IX+9),L
	LD	(IX+10),B	;set as # records used
	LD	(IX+11),H
	LD	(IX+12),L
	JR	PACK1		;repack this drive!
;
RECNEX	LD	B,(IY+7)	;get current record #
	LD	H,(IY+8)
	LD	L,(IY+9)
	CALL	INCBHL		;increment rec #
	JR	REC1LP		;go next record
;
;	repack/recover single file
;
PACK1	LD	A,(IX+10)	;check for any records
	OR	(IX+11)
	OR	(IX+12)
	RET	Z		;none!
	LD	A,(IX+0)	;get old sort flag
	LD	(OLDPACK),A	;save it
	RES	6,(IX+0)	;set NOT sorted
	LD	B,0		;set record # to 0
	LD	H,B
	LD	L,B		;BHL = 000000H
;
PACK1LP	LD	(IY+7),B	;update record #
	LD	(IY+8),H
	LD	(IY+9),L	;current record #
	LD	C,(IX+10)	;get total # records
	LD	D,(IX+11)
	LD	E,(IX+12)
	CALL	CMPBHL		;BHL = CDE ?
	RET	Z		;yes, done!
	CALL	GETPACK		;read record @ BHL
	RET	NZ		;go on error
	LD	A,(HL)		;get first byte
	INC	A		;FF dead record?
	JR	Z,PACK1B	;yes, pack the record
;
	LD	B,(IY+7)	;get record #
	LD	H,(IY+8)
	LD	L,(IY+9)
	CALL	INCBHL		;BHL = BHL +1
	JR	PACK1LP		;go next record
;
PACK1B	LD	L,(IX+17)	;get I/O buff address
	LD	H,(IX+18)	;HL = buffer
	LD	DE,BUFFER	;put it here
	LD	BC,100H		;sector length
	LDIR			;save it
	LD	A,(IY+13)	;get data offset
	LD	(PACKOFF),A	;save offset
;
PACK1G	LD	B,(IX+10)	;get total records
	LD	H,(IX+11)
	LD	L,(IX+12)
	CALL	DECBHL		;last record #
	LD	C,(IY+7)	;get current rec #
	LD	D,(IY+8)
	LD	E,(IY+9)
	CALL	CMPBHL		;last rec = current rec?
	JR	NZ,PACK1D	;go!
	LD	(IX+10),B	;update
	LD	(IX+11),H
	LD	(IX+12),L
	CALL	ADDCNTB		;bump dead counter
	XOR	A		;return Z
	RET			;done!
;
PACK1D	CALL	GETPACK		;read the record
	RET	NZ		;go if error!
	LD	A,(HL)		;get flag byte
	INC	A		;dead FF?
	PUSH	AF		;save NZ flag
;
PACK1E	LD	B,(IX+10)	;get total # records
	LD	H,(IX+11)
	LD	L,(IX+12)
	CALL	DECBHL		;less this record
	LD	(IX+10),B	;update
	LD	(IX+11),H
	LD	(IX+12),L
	CALL	ADDCNTB		;bump dead counter
	POP	AF		;get flags back
	JR	Z,PACK1G	;go if dead record
;
PACK1F	LD	L,(IX+17)	;get I/O buffer
	LD	H,(IX+18)	;HL => buffer
	LD	E,(IY+13)	;get data offset
	LD	D,0		;DE = offset
	ADD	HL,DE		;HL => source record
	EX	DE,HL		;DE => source
	LD	HL,BUFFER	;stored buffer
	LD	C,'$'		;fetch offset
PACKOFF	EQU	$-1
	LD	B,0		;BC = offset
	ADD	HL,BC		;HL => dest
	EX	DE,HL		;HL => source, DE => dest
	LD	BC,128		;record length
	LDIR			;move to I/O buffer
	LD	E,(IX+17)	;get I/O buff address
	LD	D,(IX+18)
	LD	HL,BUFFER	;stored buffer
	LD	BC,100H		;sector length
	LDIR			;move to I/O buffer
	LD	B,(IY+7)	;get current record
	LD	H,(IY+8)
	LD	L,(IY+9)
	CALL	COMPSEC		;compute
	LD	C,(IX+4)	;get start rec #
	LD	D,(IX+5)
	LD	E,(IX+6)
	CALL	ADDIT		;BHL = record #
	LD	(IY+10),B	;update pointer
	LD	(IY+11),H
	LD	(IY+12),L
	RES	7,(IY+1)	;reset current record
	LD	BC,SYSTEM+10	;point to rec #
	LD	E,(IX+15)	;get FCB address
	LD	D,(IX+16)
;
	POSN$			;position to record
	RET	NZ		;go if error
	WRITE$			;write the record
	RET	NZ		;go if error
;
	LD	B,(IY+7)	;get current rec #
	LD	H,(IY+8)
	LD	L,(IY+9)
	JP	PACK1LP		;go next record
;
;**
;
BERROR	CALL	ERROR		;display error message
	LD	HL,MSGB4	;'key to continue'
	CALL	DISPLAY		;display prompt
	CALL	INKEY		;wait for a key
	OR	-1		;return NZ
	RET			;done!
;
PAKREC	CALL	COMPSEC		;compute sector #
	LD	(IY+23),A	;save offset
	LD	C,(IX+4)	;get record offset
	LD	D,(IX+5)
	LD	E,(IX+6)
	CALL	ADDIT		;add CDE => BHL
	LD	(IY+24),B	;save phys sector #
	LD	(IY+25),H
	LD	(IY+26),L
	RES	7,(IY+1)	;set NO record in memory
	LD	E,(IX+15)	;get FCB pointer
	LD	D,(IX+16)
	LD	BC,SYSTEM+24	;point to rec #
;
	POSN$			;position to record
	RET	NZ		;go if error
	READ$			;read the sector
	RET	NZ		;go if error
;
	LD	L,(IX+17)	;get FCB pointer
	LD	H,(IX+18)
	LD	C,(IY+23)	;get data offset
	LD	B,0		;BC = offset
	ADD	HL,BC		;HL => record
	XOR	A		;return Z
	RET			;done
;
GETPACK	CALL	COMPSEC		;compute sector #
	LD	(IY+13),A	;save byte offset
	LD	C,(IX+4)	;get start record data
	LD	D,(IX+5)
	LD	E,(IX+6)
	CALL	ADDIT		;add CDE => BHL
	BIT	7,(IY+1)	;sector in buffer?
	RES	7,(IY+1)	;set NO rec in buffer
	JR	Z,GETPAC1	;go if not!
	LD	C,(IY+10)	;get current sector
	LD	D,(IY+11)
	LD	E,(IY+12)
	CALL	CMPBHL		;record current?
	JR	Z,GETPAC2	;yes, go!
;
GETPAC1	LD	(IY+10),B	;save phys record
	LD	(IY+11),H
	LD	(IY+12),L
	LD	E,(IX+15)	;get FCB pointer
	LD	D,(IX+16)
	LD	BC,SYSTEM+10	;point to rec #
;
	POSN$			;position to record
	RET	NZ		;go if error
	READ$			;read the record
	RET	NZ		;go if error
;
GETPAC2	SET	7,(IY+1)	;set sector IN memory
	LD	L,(IX+17)	;get buff pointer
	LD	H,(IX+18)
	LD	C,(IY+13)	;get offset
	LD	B,0		;BC = offset
	ADD	HL,BC		;HL => record
	XOR	A		;return Z
	RET			;done
;
;##
;
MSGB1	DEFB	SETCUR
	DEFB	12,00
	DEFB	EOF
	DEFM	'Repacking Deleted Data Files'
	DEFB	ETX
;
MSGB1A	DEFB	SETCUR
	DEFB	14,00
	DEFB	EOF
	DEFM	'Repacking - '
	DEFB	ETX
;
MSGB2	DEFB	SETCUR
	DEFB	12,00
	DEFB	EOF
	DEFB	CR
	DEFM	'Recovering Data - '
	DEFB	ETX
;
MSGBX	DEFB	SETCUR
	DEFB	12,00
	DEFB	EOF
	DEFB	CR
MSGBXB	DEFM	'xxxxxxxx Records Deleted, (KEY):'
	DEFB	ETX
;
MSGB4	DEFB	SETCUR
	DEFB	15,00
	DEFB	EOF
	DEFM	'(KEY) to continue:'
	DEFB	ETX
;
