**********************************************************************
	Section	DIP,Code
**********************************************************************

	Include	System.gs
	Include	Macros.i

**********************************************************************

;TaskPriority	Equ	0
NOWBCD
	Include	Start.i

**********************************************************************

	Dc.B	'$VER: Disk Imaging Program (DIP) V1.0 by Shamus Husheer',0
	Even

READ	EQU	0
WRITE	EQU	1

NUMCYLS	EQU	80
CYLSIZE	EQU	512*11*2

**********************************************************************

Main:
	Lea.L	VBase,A5
	Clr.B	-1(A0,D0.L)
	Move.L	A0,ArgsPtr-VBase(A5)

	Lea.L	MessagePort-VBase(A5),A0
	Move.B	#4,LN_TYPE(A0)
	Lea.L	MP_MSGLIST+LH_TAIL(A0),A1
	Move.L	A1,-4(A1)
	Subq.L	#4,A1
	Move.L	A1,MP_MSGLIST+LH_TAILPRED(A0)

	Sub.L	A1,A1
	EXEC	FindTask
	Move.L	D0,MP_SIGTASK+MessagePort-VBase(A5)

	Moveq.L	#-1,D0
	EXEC	AllocSignal
	Move.B	D0,MP_SIGBIT+MessagePort-VBase(A5)
	Bmi	.exit

	Lea.L	IORequest-VBase(A5),A1
	Move.B	#5,LN_TYPE(A1)
	Move.L	A0,MN_REPLYPORT(A1)
	Move.W	#IOSTD_SIZE,MN_LENGTH(A1)

	Lea.L	DOSLibName(PC),A1
	Moveq.L	#0,D0
	EXEC	OpenLibrary
	Move.L	D0,_DOSBase
	Beq	.freesig

	DOS	Output
	Move.L	D0,OutputHD-VBase(A5)

	Move.L	D0,D1
	Lea.L	IntroStr(PC),A0
	Move.L	A0,D2
	Move.L	#IntroStrLen,D3
	DOS	Write

	Bsr	ParseArgs
	Tst.L	D0
	Bne	.badargs

	Move.L	DevName-VBase(A5),A0
	Bsr	GetDevName
	Tst.L	D0
	Beq	.nodev

	Move.L	D0,A0
	Move.L	DevUnit-VBase(A5),D0
	Move.L	DevFlags-VBase(A5),D1
	Lea.L	IORequest-VBase(A5),A1
	EXEC	OpenDevice
	Tst.L	D0
	Bne	.nodevopen

	Move.L	#CYLSIZE,D0
	Move.L	#MEMF_CHIP|MEMF_CLEAR,D1
	EXEC	AllocMem
	Move.L	D0,Buffer-VBase(A5)
	Beq	.nomem

	Tst.B	Operation-VBase(A5)
	Beq.S	.read01
	Move.L	#MODE_OLDFILE,D2
	Bra.S	.motoron
.read01
	Move.L	#MODE_NEWFILE,D2
.motoron
	Move.L	FileName-VBase(A5),D1
	DOS	Open
	Move.L	D0,FileHD-VBase(A5)
	Beq	.nofile

	Move.W	#TD_MOTOR,IO_COMMAND+IORequest-VBase(A5)
	Move.L	#1,IO_LENGTH+IORequest-VBase(A5)
	Lea.L	IORequest-VBase(A5),A1
	EXEC	DoIO

	Tst.B	Operation-VBase(A5)
	Beq.S	.read02
	Bsr	DoWrites
	Bra.S	.motoroff
.read02
	Bsr	DoReads
.motoroff

	Move.L	D0,D7

	Move.W	#TD_MOTOR,IO_COMMAND+IORequest-VBase(A5)
	Move.L	#0,IO_LENGTH+IORequest-VBase(A5)
	Lea.L	IORequest-VBase(A5),A1
	EXEC	DoIO

	Move.L	OutputHD-VBase(A5),D1
	Tst.L	D7
	Beq.S	.noerrors
	Lea.L	ErrorsStr(PC),A0
	Move.L	A0,D2
	Move.L	#ErrorsStrLen,D3
	Bra.S	.dofinal
.noerrors
	Lea.L	NoErrorsStr(PC),A0
	Move.L	A0,D2
	Move.L	#NoErrorsStrLen,D3
.dofinal
	DOS	Write

.closefile
	Move.L	FileHD-VBase(A5),D1
	DOS	Close
.freemem
	Move.L	Buffer-VBase(A5),A1
	Move.L	#CYLSIZE,D0
	EXEC	FreeMem
.closedev
	Lea.L	IORequest-VBase(A5),A1
	EXEC	CloseDevice
.closedos
	Move.L	_DOSBase(PC),A1
	EXEC	CloseLibrary
.freesig
	Moveq	#0,D0
	Move.B	MessagePort+MP_SIGBIT-VBase(A5),D0
	EXEC	FreeSignal
.exit
	Moveq.L	#0,D0
	Rts

.badargs
	Move.L	OutputHD-VBase(A5),D1
	Lea.L	ArgStr(PC),A0
	Move.L	A0,D2
	Move.L	#ArgStrLen,D3
	DOS	Write
	Bra.S	.closedos

.nodev
	Move.L	OutputHD-VBase(A5),D1
	Lea.L	NoDevStr(PC),A0
	Move.L	A0,D2
	Move.L	#NoDevStrLen,D3
	DOS	Write
	Bra.S	.closedos

.nodevopen
	Move.L	OutputHD-VBase(A5),D1
	Lea.L	NoDevOpenStr(PC),A0
	Move.L	A0,D2
	Move.L	#NoDevOpenStrLen,D3
	DOS	Write
	Bra.S	.closedos

.nomem
	Move.L	OutputHD-VBase(A5),D1
	Lea.L	NoMemStr(PC),A0
	Move.L	A0,D2
	Move.L	#NoMemStrLen,D3
	DOS	Write
	Bra	.closedev

.nofile
	Move.L	OutputHD-VBase(A5),D1
	Lea.L	NoFileStr(PC),A0
	Move.L	A0,D2
	Move.L	#NoFileStrLen,D3
	DOS	Write
	Bra	.freemem

************************

ParseArgs:
	Move.L	ArgsPtr-VBase(A5),A0
.find1starg
	Move.B	(A0)+,D0
	Tst.B	D0
	Beq.S	.badargs
	Cmp.B	#' ',D0
	Bne.S	.find1starg
	Lea.L	-2(A0),A1
	Cmp.B	#':',(A1)
	Bne.S	.write
	Clr.W	(A1)+
	Move.L	ArgsPtr-VBase(A5),DevName-VBase(A5)
	Move.L	A1,FileName-VBase(A5)
	Move.B	#READ,Operation-VBase(A5)
	Bra.S	.doneargs
.write
	Clr.B	1(A1)
	Move.L	ArgsPtr-VBase(A5),FileName-VBase(A5)
	Move.L	A0,DevName-VBase(A5)
	Move.B	#WRITE,Operation-VBase(A5)
.find2ndarg
	Cmp.B	#':',(A0)
	Beq.S	.found
	Tst.B	(A0)+
	Bne.S	.find2ndarg
	Bra.S	.badargs
.found
	Clr.W	(A0)
.doneargs
	Moveq.L	#0,D0
	Rts
.badargs
	Moveq.L	#-1,D0
	Rts


GetDevName:		;In:  A0 - Dev Name (eg FF0) Out: D0 = aptr Device
	Move.L	A0,A2
	Moveq.L	#-1,D1
.lenloop
	Cmp.B	#'a',(A0)
	Blo.S	.noand
	Cmp.B	#'z',(A0)
	Bhi.S	.noand
	And.B	#$DF,(A0)
.noand
	Tst.B	(A0)+
	DBeq	D1,.lenloop
	Neg.L	D1
	Subq.L	#1,D1
	Beq.S	.notfound
	Move.L	_DOSBase(PC),A0
	EXEC	Forbid
	Move.L	34(A0),A0
	Move.L	24(A0),D0
	Lsl.L	#2,D0
	Move.L	D0,A0
	Addq.L	#4,A0
.loop
	Move.L	(A0),D0
	Beq.S	.notfound
	Lsl.L	#2,D0
	Move.L	D0,A0
	Tst.L	dol_Type(A0)
	Bne.S	.loop
	Move.L	dol_Name(A0),D0
	Lsl.L	#2,D0
	Move.L	D0,A1
	Cmp.B	(A1)+,D1
	Bne.S	.loop
	Move.L	D1,D0
	Subq.L	#1,D0
	Move.L	A2,A3
.cmploop
	Cmp.B	(A1)+,(A3)+
	Bne.S	.loop
	DBra	D0,.cmploop
	Move.L	dol_Startup(A0),D0
	Beq.S	.loop
	Lsl.L	#2,D0
	Move.L	D0,A1
	Move.L	4(A1),D0
	Beq.S	.loop
	Move.L	(A1),DevUnit-VBase(A5)
	Move.L	12(A1),DevFlags-VBase(A5)
	Lsl.L	#2,D0
	Addq.L	#1,D0
	Move.L	D0,DeviceName-VBase(A5)
	Bra.S	.permit
.notfound
	Moveq.L	#0,D0
.permit
	EXEC	Permit
	Rts

DoReads:
	Moveq.L	#-1,D7
.readloop
	Addq.L	#1,D7
	Cmp.L	#NUMCYLS,D7
	Bhs.S	.finished
	Move.L	#ReadingStr,OpType-VBase(A5)
	Move.L	D7,UpToCyl-VBase(A5)
	Bsr	PrintProgress
	Move.L	D7,D0
	Mulu	#44,D0
	Lsl.L	#8,D0
	Move.L	D0,IO_OFFSET+IORequest-VBase(A5)
	Move.W	#CMD_READ,IO_COMMAND+IORequest-VBase(A5)
	Move.L	#CYLSIZE,IO_LENGTH+IORequest-VBase(A5)
	Move.L	Buffer-VBase(A5),IO_DATA+IORequest-VBase(A5)
	Lea.L	IORequest-VBase(A5),A1
	EXEC	DoIO
	Moveq.L	#0,D0
	Move.B	IO_ERROR+IORequest-VBase(A5),D0
	Bne.S	.error
	Move.L	FileHD-VBase(A5),D1
	Move.L	Buffer-VBase(A5),D2
	Move.L	#CYLSIZE,D3
	DOS	Write
	Cmp.L	#CYLSIZE,D1
	Beq.S	.readloop
.error
	Moveq.L	#-1,D0
	Rts
.finished
	Moveq.L	#0,D0
	Rts

DoWrites:
	Moveq.L	#-1,D7
.writeloop
	Addq.L	#1,D7
	Cmp.L	#NUMCYLS,D7
	Bhs.S	.finished
	Move.L	#WritingStr,OpType-VBase(A5)
	Move.L	D7,UpToCyl-VBase(A5)
	Bsr.S	PrintProgress
	Move.L	FileHD-VBase(A5),D1
	Move.L	Buffer-VBase(A5),D2
	Move.L	#CYLSIZE,D3
	DOS	Read
	Cmp.L	#CYLSIZE,D1
	Bne.S	.error
	Move.L	D7,D0
	Mulu	#44,D0
	Lsl.L	#8,D0
	Move.L	D0,IO_OFFSET+IORequest-VBase(A5)
	Move.W	#CMD_WRITE,IO_COMMAND+IORequest-VBase(A5)
	Move.L	#CYLSIZE,IO_LENGTH+IORequest-VBase(A5)
	Move.L	Buffer-VBase(A5),IO_DATA+IORequest-VBase(A5)
	Lea.L	IORequest-VBase(A5),A1
	EXEC	DoIO
	Moveq.L	#0,D0
	Move.B	IO_ERROR+IORequest-VBase(A5),D0
	Beq.S	.writeloop
.error
	Moveq.L	#-1,D0
	Rts
.finished
	Moveq.L	#0,D0
	Rts

PrintProgress:
	Lea.L	ProgressStr(PC),A0
	Lea.L	OpType-VBase(A5),A1
	Lea.L	.stuffchar(PC),A2
	Lea.L	TextBuffer-VBase(A5),A3
	EXEC	RawDoFmt

	Move.L	OutputHD-VBase(A5),D1
	Lea.L	TextBuffer-VBase(A5),A0
	Move.L	A0,D2
	Moveq.L	#-1,D3
.lenloop
	Tst.B	(A3)+
	DBeq	D3,.lenloop
	Not.L	D3
	DOS	Write
	Rts

.stuffchar
	Move.B	D0,(A3)+
	Rts

*******

IntroStr:
	Dc.B	'Disk Imaging Program V1.0 by Shamus Husheer',10
IntroStrLen	Equ	*-IntroStr

ArgStr:
	Dc.B	'Command Line Parameters INCORRECT.  Try:',10
	Dc.B	'DIP <source> <dest>',10
	Dc.B	'Where, for reading, <source> is some device (eg DF0:) and <dest> is a file,',10
	Dc.B	'or for writing <source> is a file, and <dest> is a device.',10
ArgStrLen	Equ	*-ArgStr

NoDevStr:
	Dc.B	'Unable to locate the device you have requested.',10
NoDevStrLen	Equ	*-NoDevStr

NoDevOpenStr:
	Dc.B	'The device you have requested failed allocation.',10
NoDevOpenStrLen	Equ	*-NoDevOpenStr

NoMemStr:
	Dc.B	'Unable to allocate 11KB of memory for track buffer.',10
NoMemStrLen	Equ	*-NoMemStr

NoFileStr:
	Dc.B	'Unable to open your requested file.',10
NoFileStrLen	Equ	*-NoFileStr

ErrorsStr:
	Dc.B	13,'There were errors in the operation.',10
ErrorsStrLen	Equ	*-ErrorsStr

NoErrorsStr:
	Dc.B	13,'No errors were encountered.',10
NoErrorsStrLen	Equ	*-NoErrorsStr

ProgressStr:
	Dc.B	13,'%s cyl %ld of 79',0

ReadingStr:
	Dc.B	'Reading',0
WritingStr:
	Dc.B	'Writing',0

DOSLibName:
	DOSNAME

	EVEN

_DOSBase
	Dc.L	0		;Frequently used, so PC relative.

*******

	Section	Variables,BSS

VBase:

ArgsPtr:
	Ds.L	1

OutputHD:
	Ds.L	1

DevName:
	Ds.L	1
DeviceName:
	Ds.L	1
DevUnit:
	Ds.L	1
DevFlags:
	Ds.L	1

Buffer:
	Ds.L	1

FileName:
	Ds.L	1
FileHD:
	Ds.L	1

OpType:			;Do not separate
	Ds.L	1
UpToCyl:		;Do not separate
	Ds.L	1

TextBuffer:
	Ds.B	32

MessagePort:
	Ds.B	MP_SIZE

IORequest:
	Ds.B	IOSTD_SIZE

Operation:
	Ds.B	1
