;BOOTA2.68K	FEB-25-89
;Apex Bootstrap for the Amiga 2000 and 500 (use BOOTA.68K for the Amiga
; 1000).
;Written by Loren Blaney
;
;REVISION HISTORY:
;FEB-25-89, Original, based on BOOTA.68K, JUN-30-88.
;
;NOTES:
;This code resides in the first four blocks (1K) of the boot disk. The
; Amiga Kickstart boot reads the first 1K from the disk, verifies that
; it says "DOS", and then jumps to its execution entry point. This
; program then reads RESCOD.SYS from the disk, kills AmigaDOS, and then
; moves RESCOD.SYS into its proper places in memory and starts it.
; RESCOD.SYS, in turn, reads in SYSTEM.SYS (APEX.XPL) and starts it.
;
;This boot code is installed onto a newly formatted disk as follows:
;
; LOAD BOOTA2
;	CHANGE DEFAULTS (Y/N)? N
;	(Press RETURN to execute the checksum calculation)
;
; (Make sure unit is not in a sub-directory)
; WRITE
;	UNIT? 0
;	BLOCK? 0
;	BUFFER? $8000			(= BODY)
;	SIZE (BLOCKS)? 4
;
;
;    DISK BLOCK		CONTENTS
;	0-3		BOOTA2 (clobbers extended directory)
;	4-8		unused (extended backup directory)
;	9-12		directory
;	13-16		backup directory
;	17-96		RESCOD.SYS
;	97-3519		file space
;
;
;DATA STRUCTURES:
;
;  IOStdReq:
;  0	Message:0	Node:	0	*lnSucc
;  4		4		4	*lnPred
;  8		8		8	lnType
;  9		9		9	lnPri
;  10		10		10	*lnName		"APEX."
;  
;  14		14	*mnReplyPort	pointer to MsgPort
;  18		18	mnLength
;  
;  20	*ioDevice
;  24	*ioUnit
;  28	ioCommand		Clear/Change No./Read
;  30	ioFlags
;  31	ioError
;  32	ioActual		No. of bytes actually read
;  36	ioLength		No. of bytes to read
;  40	ioData			Pointer to buffer to read into
;  44	ioOffset		No. of bytes to start of data on disk
;  
;  msgPort:			Used for replies from trackdisk.device
;  0	Node:	0	*lnSucc
;  4		4	*lnPred
;  8		8	lnType
;  9		9	lnPri
;  10		10	*lnName		"APEX."
;  
;  14	mpFlags		Flags in message port
;  15	mpSigBit	Signal from AllocSignal
;  16	*mpSigTask	Pointer to the current task, from FindTask
;  
;  20	List:	0   mlHead	Points to mpTail
;  24		4   mlTail	Zero
;  28		8   mlTailPred	Points to mlHead
;
;----------------------------------------------------------------------

;MEMTOP	EQU	$100000		;Highest memory address +1
MEMTOP	EQU	$80000		;Highest memory address +1 *** DEBUG ***
VSTART	EQU	$0400		;Start location for RESCOD
VRENTR	EQU	$7B4		;Apex re-entry vector
RAM	EQU	$40000		;Absolute RAM location for AmigaDOS to
				; load RESCOD.SYS into
RESSIZE	EQU	$5000+$200	;Total number of bytes in RESCOD.SYS
				; including two half-sectors on each end
				; (This must be a multiple of 512)
IOStdReq EQU	RAM+RESSIZE	;Offset into RAM to I/O request block
msgPort	EQU	IOStdReq+48	;Offset to the reply message port

;Offsets into IOStdReq:
ioCommand	EQU	28
ioLength	EQU	36
ioData		EQU	40
ioOffset	EQU	44

ExecBase	EQU	4	;Jump table for ROM-based exec routines
;Offsets into jump table for selected exec routines:
DoIO		EQU	-$1C8
OpenDevice	EQU	-$1BC
AllocSignal	EQU	-$14A
FindTask	EQU	-$126
AllocAbs	EQU	-$CC
SuperState	EQU	-$96

CIAA	EQU	$BFE001		;Base address of 8520-A chip
;Offsets to CIA registers:
PRA	EQU	$0		;Peripheral Data Register A
DDRA	EQU	$200		;Data Direction Register A

CHIPREG	EQU	$DFF000		;Base address of chip registers
;Offsets to chip registers:
DMACON	EQU	$96		;DMA control
INTENA	EQU	$9A		;Interrupt enable bits
INTREQ	EQU	$9C		;Interrupt request bits
BPLCON0	EQU	$100		;Bit plane control register 0
BPL1DAT	EQU	$110		;Bit plane 1 data register
COLOR00	EQU	$180		;Color register 00

;----------------------------------------------------------------------
;Kickstart loads this program (BOOTA2.68K) at an unknown address
; therefore this code must be relocatable.
;
	ORG	$0400		;The LOADer jumps here
	JMP	DOCKSUM.L

BODY	EQU	$8000		;An arbitrary location
	ORG	BODY

;Kickstart requires the following header information:
	ASCII	"DOS"		;ASCII identification of the disk
	DC.B	0
CKSUM	DC.L	0		;Checksum of the "boot block" (1st 1K)
	DC.L	880		;Pointer to "root block" (unused)

;Kickstart jumps to this location:
START	BRA.S	BT00
	ASCII	"Apex, V1.8, Copyright (c) Feb-25-89 "
	ASCII	"Computer Applications"
	DC.B	0

;----------------------------------------------------------------------
;This routine calculates and sets the checksum for this program.
;
DOCKSUM	LEA	BODY.L,A0	;Point to beginning of this program
	LEA	4(A0),A1	;Point A1 to checksum entry
	CLR.L	(A1)		;Initialize checksum
	MOVE.W	#$400/4-1,D1	;Set loop counter for number of longs
	MOVEQ	#$00,D0		;Initialize accumulator
CS10	ADD.L	(A0)+,D0	;Add long word
	BCC.S	CS20
	ADDQ.L	#1,D0		;End arround carry
CS20	DBF	D1,CS10		;Next long word
	NOT.L	D0		;Ones complement of checksum
	MOVE.L	D0,(A1)		;Save result
	JMP	VRENTR		;Re-enter Apex (reload it if necessary)

;----------------------------------------------------------------------
;Allocate memory for RESCOD.SYS:
BT00	MOVE.L	#RESSIZE+$100,D0 ;Bytes to allocate (+IOStdReq +msgPort)
	LEA	RAM.L,A1	;Absolute address to allocate
	MOVEA.L	ExecBase,A6
	JSR	AllocAbs(A6)	;Call exec routine to allocate memory
	TST.L	D0		;Error?
	BNE.S	BT10		;Branch if not
	MOVE.L	#$BADC0DE1,D0	;Return error code to Kickstart
	RTS			;Guru error $30000001, BADC0DE1

BT10	MOVE.W	#256/4-1,D0	;Zero IOStdReq block
	LEA	IOStdReq.L,A0
BT15	CLR.L	(A0)+
	DBF	D0,BT15

;Set up reply message port:
	LEA	msgPort.L,A5	;Point A5 to base of message port
	MOVE.L	APXNAME-@-2(PC),10(A5)	;Set lnName in node structure

	SUBA.L	A1,A1		;Name = null
	JSR	FindTask(A6)	;Find current task FindTask(A1=0)
	MOVE.L	D0,16(A5)

	LEA	20(A5),A0	;Set mlHead to mlTail
	MOVE.L	A0,(A0)
	ADDQ.L	#4,(A0)
	MOVE.L	A0,8(A0)	;Set mlTailPred to mlHead

	MOVEQ	#-1,D0
	JSR	AllocSig(A6)	;AllocSig(D0=-1)
	MOVE.B	D0,15(A5)
	BPL.S	BT20		;Branch if no error
	RTS			;Return error code for the Guru

APXNAME	ASCII	"APEX."
	DC.B	0

;Open disk drive:
;Set iORequest = start of allocated memory
BT20	LEA	IOStdReq.L,A1	;iORequest: Pointer to I/O request
				; block to be initialized
	MOVE.L	#msgPort,14(A1)	;Set pointer to reply message port
	MOVE.L	APXNAME-@-2(PC),10(A1)	;Set lnName in node

	LEA	TDNAME-@-2(PC),A0	;devName: Requested device name
	MOVEQ	#0,D0		;unitNumber: Unit number on device (DF0)
	MOVEQ	#0,D1		;Flags: additional info (if any)
	JSR	OpenDevice(A6)
	TST.L	D0		;Error?
	BEQ.S	BT30		;Branch if no error
	RTS			;Return with error code

TDNAME	ASCII	"trackdisk.device"
	DC.W	0		;Terminator

;Read in RESCOD.SYS:
BT30	LEA	IOStdReq.L,A1	;Pass pointer to I/O request block
	MOVE.W	#$0002,ioCommand(A1)	;Set command to read
	MOVE.L	#RESSIZE,ioLength(A1)	;Number of bytes to read
	MOVE.L	#RAM,ioData(A1)	;Pointer to data buffer
	MOVE.L	#16/2*512,ioOffset(A1)	;Offset on disk to RESCOD.SYS
					; (must be a multiple of 512)
	JSR	DoIO(A6)		;Read disk blocks
	TST.L	D0			;Error?
	BEQ.S	BT40			;Branch if not
	RTS				;Return with error code

;Kill AmigaDOS (Hurray!!!):
BT40	JSR	SuperState(A6)	;Go to supervisor mode
	ORI	#$0700,SR	;Disable interrupts
	LEA	MEMTOP.L,SP	;Set the stack to top of memory

	LEA	CIAA.L,A6	;Initialize CIA chips
	MOVE.B	#$03,DDRA(A6)	;Set bits 0 & 1 as outputs
	MOVE.B	#$02,PRA(A6)	;Overlay = 0 (off), LED = dim

	LEA	CHIPREG.L,A6
	MOVE.W	#$7FFF,D0	;Disable all bits
	MOVE.W	D0,INTENA(A6)	;Clear all interrupt enable bits
	MOVE.W	D0,INTREQ(A6)	;Clear all interrupt requests
	MOVE.W	D0,DMACON(A6)	;Disable all DMA channels
	MOVE.W	#$0200,BPLCON0(A6)	;No bit planes, color enabled
	MOVE.W	#$0000,BPL1DAT(A6)	;Blank display
	MOVE.W	#$0024,COLOR00(A6)	;Set background color

;Move low part of RESCOD into its correct location:
	LEA	$100+RAM.L,A6	;Set "from" address
	LEA	$00000000,A5	;Set "to" address
	MOVE.W	#16*8,D0	;Move 16 blocks ($0000 up to $1000)
	BSR.S	MOVBLK		;Go do it

;Move high part of RESCOD into its correct location:
	LEA	$1100+RAM.L,A6	;Set "from" address
	LEA	MEMTOP-$4000.L,A5	;Set "to" address
	MOVE.W	#63*8+4,D0	;Move 63.5 blocks (-$4000 up to -$0080)
	BSR.S	MOVBLK		;Go do it

;Initialize the rest of memory to zero:
	MOVEQ	#0,D0
	LEA	$1000,A6	;Start at the end of the low part
BT50	MOVE.L	D0,(A6)+	;WARNING: amount must be a multiple of 4
	CMPA.L	#MEMTOP-$4000,A6	;Finish at the beginning of the
	BGE.S	BT50			; high part

	JMP	VSTART		;Enter RESCOD

;-----------------------------------------------------------------------
;Move D0*32 bytes from A6 to A5.
; Most registers are destroyed.
; Note unusual entry point.
;
MOV10	MOVEM.L	(A6)+,A4/D1-D7	;Read 32 bytes at A6
	MOVEM.L	A4/D1-D7,(A5)	;Write 32 bytes at A5
	ADDA.L	#32,A5		;(Post incrementing is not allowed)
MOVBLK	DBF	D0,MOV10	;Loop until done
	RTS


MAX	EQU	BODY +$400	;Maximum load location +1 (1K)
	DCB.B	MAX-@, 0	;Fill the rest of boot block with zeros

	END

	RTS


MAX	EQU	BODY +$400	;Maximum load location +1 (1K)
	DCB.B	MAX-@, 0	;Fill the rest of boot block with zero