	TITLE 'DOUBLE DENSITY MYDOS3 SYSTEM DISK BUILDER'
;
;  Copyright 1984, Charles Marslett, Wordmark Systems
;
;  Permission is granted by the author for any use whatsoever of this
;    code, so long as this notice remains in the source code, and so
;    long as the source to this routine, however modified or unmodified,
;    is made available for a nominal cost.
;
;
;  Some important absolute addresses
;
CIOV	=	$E456	;CIO ENTRY VECTOR
;
MENUP	=	$02E0	;THE RUN ENTRY POINT OF "MDUP.OBJ"
;
ORIGIN	=	$4800	;GOTTA BE BIG ENOUGH TO NOT HIT EITHER COPY OF MYDOS
;
ZCTR	=	$FA	;A GENERAL PURPOSE COUNTER
BPTR	=	$FC	;A GENERAL PURPOSE POINTER
ZPTR	=	$FE	;AND ANOTHER GENERAL PURPOSE POINTER
;
;  Define the fields of IOCB $10 that I use
;
	ORG	$0351
	DS	1
ICMD	DS	1
	DS	1
IBUF	DS	4
ILEN	DS	2
IAUX1	DS	1
IAUX2	DS	1
;
; The BUILD program itself -- loads MDOS.OBJ and MDUP.OBJ into memory above
;   itself, then relocates the code down over the previous version of MYDOS
;   that we are running with and starts it up.  This is how we create a new
;   version of MYDOS.
;
	ORG	ORIGIN
;
START	LDX	#LOW[SIGNON]
	LDY	#HIGH[SIGNON]	;LOG ONTO THE SCREEN
	JSR	DMSG
;
	LDA	#$C0
	STA	BPTR+1		;POINT BPTR AT $C000
	LDY	#0
	STY	BPTR
	LDA	#$FF
	STA	SAVC
	LDX	#$10
CLRC	STA	(BPTR),Y
	INY
	BNE	CLRC
	INC	BPTR+1
	DEX
	BNE	CLRC
;
	LDA	#HIGH[BUFFER]
	STA	BPTR+1		;POINT BPTR AT "BUFFER"
	LDA	#LOW[BUFFER]
	STA	BPTR
	LDX	#$20
	LDA	#0
MVLP1	STA	(BPTR),Y	;FILL THE 8K BUFFER WITH $00 BYTES
	INY
	BNE	MVLP1
	INC	BPTR+1
	DEX
	BNE	MVLP1
;
; COPY NEW DOS CODE FROM FILE "MDOS.OBJ"
;
	LDX	#LOW[MSG01]
	LDY	#HIGH[MSG01]
	JSR	DMSG		;ANNOUNCE WE ARE READING "D:MDOS.OBJ"
	LDY	#LOW[DOSFIL]
	LDA	#HIGH[DOSFIL]
	JSR	LOADBF		;LOAD CONTENTS OF "MDOS.OBJ"
;
; COPY NEW DOS AND DUP CODE FROM FILE "MDUP.OBJ"
;
	LDX	#LOW[MSG02]
	LDY	#HIGH[MSG02]
	JSR	DMSG		;ANNOUNCE WE ARE READING "D:MDUP.OBJ"
	LDY	#LOW[DUPFIL]
	LDA	#HIGH[DUPFIL]
	JSR	LOADBF		;LOAD CONTENTS OF "MDUP.OBJ"
;
; MOVE BUFFER DOWN TO LOW MEMORY
;
	LDX	#LOW[MSG03]
	LDY	#HIGH[MSG03]
	JSR	DMSG		;ANNOUNCE WE ARE RELOCATING DOS AND DUP CODE
	LDA	#$07
	STA	ZPTR+1
	LDA	#$00
	STA	ZPTR		;SET DESTINATION POINTER TO $0700
	LDA	#HIGH[BUFFER]
	STA	BPTR+1
	LDA	#LOW[BUFFER]
	STA	BPTR		;SET SOURCE POINTER TO "BUFFER"
;
	LDY	#0
MVLP2	LDA	(BPTR),Y
	STA	(ZPTR),Y	;COPY 256 BYTES AT A TIME UNTIL WE
	INY			;ARE ABOUT TO OVERWRITE BUILD ITSELF
	BNE	MVLP2		;(THIS IS TOO MUCH, I HOPE, BUT IT WORKS)
	INC	BPTR+1
	INC	ZPTR+1
	LDA	ZPTR+1
	CMP	#HIGH[START]
	BNE	MVLP2
;
; REINITIALIZE THE SYSTEM
;
	LDX	#LOW[MSG04]
	LDY	#HIGH[MSG04]
	JSR	WFSTR		;ANNOUNCE STARTUP AND WAIT FOR A KEY
;
	JSR	DOSINI		;REINITIALIZE THE NEW MYDOS
;
	LDX	#0
	LDA	#3
	STA	ICMD-16
	LDA	#$2C
	STA	IAUX1-16
	LDA	#LOW[EC]
	STA	IBUF-16
	LDA	#HIGH[EC]
	STA	IBUF+1-16
	JSR	CIOV		;REOPEN THE KEYBOARD/SCREEN "E:" DEVICE
;
	LDX	#LOW[MSG05]
	LDY	#HIGH[MSG05]
	JSR	WFSTR		;ANNOUNCE WE ARE READY TO RUN THE NEW MYDOS
;
	JMP	(MENUP)		;ENTER BACK AT MENU (USE "H" TO SAVE NEW DOS)
;
;
; LOAD CONTENTS OF OBJECT FILE INTO BUFFER
;
LOADBF	STY	IBUF
	STA	IBUF+1
	LDA	#$FF
	STA	MINAD
	STA	MINAD+1		;SET LOW ADDRESS TO $FFFF
	LDA	#3
	STA	ICMD
	LDA	#4
	STA	IAUX1
	LDA	#0
	STA	MAXAD		;SET HIGH ADDRESS TO $0000
	STA	MAXAD+1
	STA	IAUX2
	LDX	#$10
	JSR	CIOV		;OPEN D:MDOS.OBJ OR D:MDUP.OBJ
	BPL	GOTFIL
	LDX	#LOW[NOFIL]
	LDY	#HIGH[NOFIL]
	JSR	DMSG		;REPORT IT IF WE CANNOT OPEN THE FILE
	JMP	($000A)
;
GOTFIL	LDA	#7		;ELSE,
	STA	ICMD		;CHANGE COMMAND TO READ
	LDA	#LOW[BUFAD]
	STA	IBUF
	LDA	#HIGH[BUFAD]	;BUFFER ADDRESS TO THAT OF LOCAL BUF.
	STA	IBUF+1
	LDA	#2
	STA	ILEN
	LDA	#0
	STA	ILEN+1		;LENGTH TO 2 BYTES
	LDX	#$10
	JSR	CIOV		;READ HEADER
	BMI	INVHDR		;IF ERROR, REPORT IT
	LDA	BUFAD
	AND	BUFAD+1
	CMP	#$FF		;ELSE, VALID HEADER?
	BPL	RDNXTB
INVHDR	LDX	#LOW[NOHDR]
	LDY	#HIGH[NOHDR]
	JSR	DMSG		;IF NOT, REPORT THAT ERROR
	JMP	($000A)
;
RDNXTB	LDA	#LOW[BUFAD]	;READ THE NEXT WORD PAIR (START & END ADDR)
	STA	IBUF
	LDA	#HIGH[BUFAD]
	STA	IBUF+1
	LDA	#4
	STA	ILEN		;SET LENGTH TO 4 BYTES
	LDA	#0
	STA	ILEN+1
	LDX	#$10
	JSR	CIOV		;READ START/END ADDRESSES
	BPL	RDDATA		;IF NO ERROR, LOAD THE DATA
	CPY	#$88		;ELSE, IS IT EOF?
	BNE	ABORT		;IF NOT EOF, REPORT THE ERROR
	JMP	MOVER		;IF EOF, WE HAVE LOADED IT ALL, RETURN NORMALLY
;
RDDATA	LDA	BUFAD+2
	LDY	BUFAD+3
	CPY	MAXAD+1
	BCC	NOTMAX		;IF THIS BLOCK SETS A NEW HIGH ADDRESS LOADED
	BNE	NEWMAX
	CMP	MAXAD
	BCC	NOTMAX
NEWMAX	STY	MAXAD+1		;UPDATE THE HIGH WATER MARK
	STA	MAXAD
NOTMAX	SEC
	SBC	BUFAD
	STA	ZCTR
	TYA
	SBC	BUFAD+1
	STA	ZCTR+1
	INC	ZCTR
	BNE	LENOK
	INC	ZCTR+1
LENOK	JSR	DEBUG1
	LDY	BUFAD+1
	LDA	BUFAD
	CPY	MINAD+1		;AND IF IT SETS A NEW LOW ADDRESS LOADED
	BCC	NEWMIN
	BNE	NOTMIN
	CMP	MINAD
	BCS	NOTMIN		;UPDATE THE LOW WATER MARK
NEWMIN	CPY	#$03
	BCC	NOTMIN
	STY	MINAD+1
	STA	MINAD
NOTMIN	CPY	#$07
	BCC	DONTMV
	CPY	#$C0		;SKIP THE INDIRECT BUFFER AND MOVE
	BCS	DONTMV		;IF THE ADDR <0700 OR >BFFF
	ADC	#LOW[BUFFER-$700]
	PHA
	TYA
	ADC	#HIGH[BUFFER-$700]
	TAY
	PLA
DONTMV	STA	BPTR
	STY	BPTR+1
	JSR	DEBUG2
	LDA	#0
	STA	ILEN
	STA	ILEN+1		;READ ONE BYTE AT A TIME
GETNB	LDX	#$10
	JSR	CIOV
	BPL	STBYTE		;AND IF NO ERROR, STORE IT
ABORT	LDX	#LOW[ABORTED]
	LDY	#HIGH[ABORTED]
	JSR	DMSG		;REAL I/O ERROR
	JMP	($000A)		;EXIT TO DOS
;
STBYTE	LDY	BPTR
	BNE	STBY0
	LDY	BPTR+1		;TEST FOR BUFFER POINTER BEING STILL VALID
	CPY	#$C0
	BNE	STBY0
	STA	SAVC
	BEQ	STBY3
STBY0	LDY	#0
	STA	(BPTR),Y	;ALL OK, STORE THE BYTE JUST READ
STBY3	INC	BPTR
	BNE	STBT1
	INC	BPTR+1
STBT1	LDA	ZCTR
	BNE	STBT2		;INCREMENT THE MEMORY POINTER
	DEC	ZCTR+1
STBT2	DEC	ZCTR
	LDA	ZCTR
	ORA	ZCTR+1		;DECREMENT THE BYTE COUNTER
	BNE	GETNB		;IF STILL IN THE BLOCK, READ THE NEXT BYTE
	JMP	RDNXTB		;ELSE, EXAMINE THE NEXT BLOCK
;
MOVER	LDA	#12		;DONE WITH THE LOAD,
	STA	ICMD
	LDX	#$10
	JSR	CIOV		;CLOSE LOAD FILE
	JSR	PSTR
	DB	'(',0
	LDA	MINAD+1
	JSR	PHEX		;REPORT THE LOW AND HIGH WATER MARKS
	LDA	MINAD
	JSR	PHEX
	JSR	PSTR
	DB	'-',0
	LDA	MAXAD+1
	JSR	PHEX
	LDA	MAXAD
	JSR	PHEX
	LDX	#LOW[LOADED]
	LDY	#HIGH[LOADED]
	JSR	DMSG
	RTS			;AND RETURN TO THE MAIN LINE CODE
;
;	PROGRAM FILE (NEW FMS)
;
DOSFIL	DB	'D:MDOS.OBJ',$9B
;
;	PROGRAM FILE (NEW UTILITY PROGRAM)
;
DUPFIL	DB	'D:MDUP.OBJ',$9B
;
;	CONSOLE KEYBOARD/DISPLAY
;
EC	DB	'E:',$9B
;
; DISPLAY A MESSAGE AND WAIT FOR "START"
;
WFSTR	JSR	DMSG		;NESTED CALL TO DISPLAY THE MESSAGE
	LDA	#8
	STA	$D01F
WFSTRT	LDA	$D01F		;READ CONSOLE SWITCHES
	AND	#1
	BNE	WFSTRT		;WAIT UNTIL START IS DEPRESSED
	RTS
;
; DISPLAY A MESSAGE TO THE OPERATOR
;
DMSG	STX	ZPTR
	STY	ZPTR+1
	LDA	#0
	STA	ZCTR
MSGLP	LDY	ZCTR
	LDA	(ZPTR),Y
	BEQ	DXIT
	JSR	BYTOUT
	INC	ZCTR
	BNE	MSGLP
;
DXIT	RTS
;
CODE	DB	'0123456789ABCDEF'
;
;  DISPLAY A 4 DIGIT HEX NUMBER ON THE SCREEN
;
PHEX	PHA
	LSR	A
	LSR	A
	LSR	A
	LSR	A
	TAX
	LDA	CODE,X
	JSR	BYTOUT
	PLA
	AND	#$0F
	TAX
	LDA	CODE,X
;
BYTOUT	LDX	#11
	STX	ICMD-$10
	LDX	#0
	STX	ILEN-$10
	STX	ILEN-$10+1
	JSR	CIOV
	RTS
;
PSTR	PLA
	STA	ZPTR
	PLA
	STA	ZPTR+1
PLOOP	INC	ZPTR
	BNE	POUT
	INC	ZPTR+1
POUT	LDX	#0
	LDA	(ZPTR,X)
	BEQ	PEXIT
	JSR	BYTOUT
	JMP	PLOOP
;
PEXIT	LDA	ZPTR+1
	PHA
	LDA	ZPTR
	PHA
	RTS
;
;  REPORT THE HIGH AND LOW BUFFER LIMITS
;
DEBUG1	JSR	PSTR
	DB	'(',0
	LDA	BUFAD+1
	JSR	PHEX
	LDA	BUFAD
	JSR	PHEX
	JSR	PSTR
	DB	'-',0
	LDA	BUFAD+3
	JSR	PHEX
	LDA	BUFAD+2
	JSR	PHEX
	RTS
;
DEBUG2	JSR	PSTR
	DB	')'
	DB	$1E,$1E,$1E,$1E,$1E
	DB	$1E,$1E,$1E,$1E,$1E
	DB	$1E,0
	RTS
;
;  ROUTINE TO REINITIALIZE DOS 2.0
;
DOSINI	LDA	$704
	STA	$00C
	LDA	$704+1
	STA	$00C+1
	JMP	($00C)		;==REINITIALIZE ENTIRE DOS/DUP
;
;  MESSAGES TO OPERATOR
;
SIGNON	DC	$9B,$9B,'  '
	DC	'M','Y','D','O','S','3',' ','d','o','u','b','l','e'
	DC	' ','d','e','n','s','i','t','y'
	DC	' ','A','T','A','R','I',' ','O','S',' ',$9B
	DB	' '
	DC	' ',' ',' ',' ',' ',' ','s','y','s','t','e','m'
	DC	' ','d','i','s','k',' ','b','u','i','l','d','e','r'
	DC	' ',' ',' ',' ',' ',' ',' ',$9B,$9B
	DB	0
;
MSG01	DB	'LOADING MDOS.OBJ',0
MSG02	DB	'LOADING MDUP.OBJ',0
LOADED	DB	$1E,$1E,$1E,$1E,$1E
	DB	$1E,$1E,$1E,$1E,$1E
	DB	$1E,$1E,$1E,$1E,$1E
	DB	$1E,$1E,$1E,$1E,$1E
	DB	$1E,$1E,'ED',$FE,$9B,0
MSG03	DB	'Moving DOS/DUP into place',$9B,0
MSG04	DB	'PRESS '
	DC	'S','T','A','R','T'
	DB	' TO INITIALIZE NEW DOS',$9B,0
MSG05	DB	'PRESS '
	DC	'S','T','A','R','T'
	DB	' TO ENTER NEW DOS.',$9B,0
;
NOFIL	DB	'Cannot open Object File',$9B,0
NOHDR	DB	'Invalid Header in Object File',$9B,0
ABORTED	DB	'I/O Error, load aborted',$9B,0
;
;  BUFFER FOR PATCHING A RUNNING DOS
;
MAXAD	DS	2
MINAD	DS	2
SAVC	DS	1
BUFAD	DS	6	;FOR ADDRESSES
BUFFER	DS	START-$0700
;
; EXECUTION FORCED, LOAD RUN ADDRESS
;
;	ORG	$02E0
;	DW	START		;run address
;
	END	START
