		TTL		Maze
*
*******************************************************************************
*									      *
*	Maze								      *
*									      *
*	Copyright (c) 1989 by Michael Sinz    MKSoft Development	      *
*									      *
*	AmigaDOS EXEC release 1.2 or greater...				      *
*									      *
*******************************************************************************
*									      *
*	Reading legal mush can turn your bain into guacamole!		      *
*									      *
*		So here is some of that legal mush:			      *
*									      *
* Permission is hereby granted to distribute this program's source	      *
* executable, and documentation for non-comercial purposes, so long as the    *
* copyright notices are not removed from the sources, executable or	      *
* documentation.  This program may not be distributed for a profit without    *
* the express written consent of the author Michael Sinz.		      *
*									      *
* This program is not in the public domain.				      *
*									      *
* Fred Fish is expressly granted permission to distribute this program's      *
* source and executable as part of the "Fred Fish freely redistributable      *
* Amiga software library."						      *
*									      *
* Permission is expressly granted for this program and it's source to be      *
* distributed as part of the Amicus Amiga software disks, and the	      *
* First Amiga User Group's Hot Mix disks.				      *
*									      *
*******************************************************************************
*									      *
*	This program is not very usefull on its own, but it is an interesting *
*	680x0 problem.  I have tried to make use of the registers as best     *
*	as possible.  The speed of the generation of the maze is, it seems,   *
*	limited by graphics.library and not the CPU.  I am running this on    *
*	a 2620 and a base Amiga and see very little difference in speed...    *
*									      *
*	The code is FULLY re-entrant and can be made resident.		      *
*									      *
*	I hope you enjoy the code...					      *
*									      *
*******************************************************************************
*									      *
* Options for assembling Maze.asm...  (Defines...)			      *
*									      *
*	Xmax/Ymax	- Set the size of the window...			      *
*	DOUBLE		- Uses the DOUBLE-LOOP reset random number...	      *
*	EASYMAZE	- Uses the old maze-making method...		      *
*	PRINT		- Add the code needed to print the maze...	      *
*									      *
*******************************************************************************
*									      *
*	To assemble, I used the assembler that comes with MANX C68K	      *
*									      *
*	It should assemble without any problems on most 680x0 assemblers      *
*									      *
*	Note to persons trying to assemble on other assemblers:		      *
*	I have a habbit for using bcc.s (bra.s, etc) for ALL jumps.	      *
*	This may be a problem in some assemblers/with certain options.	      *
*	Sorry...  (Bad habbits are hard to break...  ;-(  )		      *
*									      *
*******************************************************************************
*
* The following INCLUDE files are needed to make this program assemble.
* They come with the Amiga Macro-Assembler Package.
*
	NOMLIST					; No macro expansion list
	NOCLIST					; No conditional list
	NOLIST					; No need to list these
	INCLUDE	"EXEC/Types.i"
	INCLUDE	"EXEC/Libraries.i"
	INCLUDE	"EXEC/Ables.i"
	INCLUDE	"EXEC/Memory.i"
	INCLUDE	"EXEC/IO.i"
	INCLUDE	"EXEC/Nodes.i"
	INCLUDE	"EXEC/Lists.i"
	INCLUDE	"Devices/Printer.i"
	INCLUDE	"Graphics/GfxBase.i"
	INCLUDE	"Graphics/RastPort.i"
	INCLUDE	"Intuition/IntuitionBase.i"
	INCLUDE	"Intuition/Intuition.i"
	INCLUDE	"Libraries/DOSextens.i"
	LIST					; Ok, lets start the listing
*
*******************************************************************************
*
* This is the only fixed address in the system...
*
		xref	_AbsExecBase
*
*******************************************************************************
*
* Some macros that make calling the system routines easier...
*
CALLSYS		MACRO
		xref	_LVO\1		; Set the external reference
		CALLLIB	_LVO\1		; Call the EXEC definied macro
		ENDM
*
*******************************************************************************
*
* Offsets from the stack that contain the following...
*
my_Left		equ	0		; Left 0
my_Top		equ	2		; Top 0
my_Right	equ	4		; Right MAX
my_Bottom	equ	6		; Left MAX
intuitionBASE	equ	8		; Where IntuitionBase is stored...
*
*******************************************************************************
*
* These are the sizes in X and Y of the 'Block' that is used...
* X_Size/Y_Size should be ODD and less than 8...
*
X_Size		equ	5		; Size in X
Y_Size		equ	3		; Size in Y
*
X_Size_Mod	equ	(X_Size-1)/2
Y_Size_Mod	equ	(Y_Size-1)/2
*
*******************************************************************************
*
* These define the size of the window...  If not defined by assembler
* parameter, these values are used...
*
	IFD Xmax
XMax		equ	Xmax		; Use the parameter from the user...
	ELSE
XMax		equ	509		; X size for window...
	ENDC
*
	IFD Ymax
YMax		equ	Ymax		; Use the parameter from the user...
	ELSE
YMax		equ	171		; Y size for window...
	ENDC
*
*******************************************************************************
*
BACKpen		equ	3		; Pen for the background colour...
*
*******************************************************************************
*
* Bits for the different directions...
*
LEFT_Bit	equ	0
RIGHT_Bit	equ	1
UP_Bit		equ	2
DOWN_Bit	equ	3
*
*******************************************************************************
*									      *
* Register usage through this program...				      *
*									      *
*	a0	- Scrap							      *
*	a1	- Scrap							      *
*	a2	- GFX Base saved...					      *
*	a3	- RastPort...						      *
*	a4	- Window pointer...					      *
*	a5	- EXEC Base saved...					      *
*	a6	- Library Base Register...				      *
*	a7	- Stack...  (What else?)				      *
*									      *
*	d0	- Scrap							      *
*	d1	- Scrap							      *
*	d2	- Random Number seed...					      *
*	d3	- Bit Pattern of possible moves...			      *
*	d4	- Current X						      *
*	d5	- Current Y						      *
*	d6	- Intuition Base (and ....)				      *
*	d7	- Zero...						      *
*									      *
*******************************************************************************
*
* Now, for the start of the code...
*
Maze:		move.l	_AbsExecBase,a6		; Get the EXEC library base
		move.l	a6,a5			; Save it...
		clr.l	d7			; Clear d7...
*
		move.l	d7,a1		; Clear a1
		CALLSYS	FindTask	; Get our task pointer...
		move.l	d0,a4		; Now, move it to a4 for addressing use
		lea	pr_MsgPort(a4),a3
		tst.l	pr_CLI(a4)	; Check if this is a CLI task...
		bne.s	QuickCLI	; If so, skip the next section
*
*******************************************************************************
*
* This section deals with starting from the WorkBench...
* It is just here for completeness...
*
QuickWorkBench:	move.l	a3,a0		; Get message port
		CALLSYS	WaitPort	; Wait for the WorkBench message...
		move.l	a3,a0		; ...it's here, so let's get it
		CALLSYS	GetMsg		; off the message port...
		bra.s	QuickCont	; ...and go to the continue routine
*
*******************************************************************************
*
* The routine was started from the CLI  (prefered)
* Let's store a NULL pointer so that there is no WB message...
*
QuickCLI:	move.l	d7,d0		; No reply message...
*
*******************************************************************************
*
* Continue with the Quick initialization
*
QuickCont:	move.l	d0,-(sp)	; Save the message pointer...
*
*******************************************************************************
*
* Ok, we are now ready to do some real work...
*
		lea	intuitionName(pc),a1	; Get LIB name...
		move.l	d7,d0			; ANY version, I guess...
		CALLSYS	OpenLibrary		; Open it...
		move.l	d0,d6			; Quick way to check it...
		beq.s	abortNoIntuit		; No intuition, we abort...
		lea	graphicsName(pc),a1	; Get LIB name...
		move.l	d7,d0			; Any version...
		CALLSYS	OpenLibrary		; Open it...
		move.l	d0,a2			; Save it...
		move.l	a2,d0			; And check...
		beq.s	abortNoGfx		; Abort if we can't get it...
*
*******************************************************************************
*
* Now, open a window...
*
		lea	NewWindowStuff(pc),a0	; Point to the NewWindow...
		move.l	d6,a6			; Set IntuitionBase...
		CALLSYS	OpenWindow		; Open it...
		move.l	d0,a4			; Save the pointer...
		move.l	a4,d0			; Check it...
		beq.s	abortNoWindow		; No window, so abort...
		move.l	wd_RPort(a4),a3		; Get rastport...
		move.l	d6,-(sp)		; Save the intuition pointer
*
*******************************************************************************
*
* Ok, now we fill the screen with the block pen...
*
		move.l	a2,a6			; We will be doing Gfx stuff...
		moveq.l	#BACKpen,d0		; Pen number...
		move.l	a3,a1			; Get RPort...
		CALLSYS	SetAPen			; Set the pen...
		move.w	wd_Height(a4),d3	; Window Y size...
		move.w	wd_Width(a4),d2		; Window X size...
		move.b	wd_BorderBottom(a4),d0	; the bottom border...
		ext.w	d0			; Extend it to a word...
		sub.w	d0,d3			; subtract it from d3...
		move.b	wd_BorderRight(a4),d0	; the right border...
		ext.w	d0			; Extend it...
		sub.w	d0,d2			; Subtrack it from d2...
		move.b	wd_BorderTop(a4),d1	; Get top border...
		ext.w	d1			; Extend it...
		move.b	wd_BorderLeft(a4),d0	; Get left border...
		ext.w	d0			; Extend it...
		subq.l	#1,d2			; We need to adjust a bit...
		subq.l	#1,d3
		movem.w	d0-d3,-(sp)		; Save these values...
		move.l	a3,a1			; Make sure we have RPort...
		CALLSYS	RectFill		; Fill it...
		move.l	a3,a1			; (It may have trashed it...)
		move.l	d7,d0			; Set pen to 0...
		CALLSYS	SetAPen			; (We will erase the bad areas)
*
*******************************************************************************
*
* The window is now pained and ready to rock...  We just need to do a few
* adjustments on the limits...
*
		movem.w	(sp)+,d0-d3		; Get the limits...
		addq.l	#X_Size,d0		; Adjust inwards...
		subq.l	#X_Size,d2
		addq.l	#Y_Size,d1
		subq.l	#Y_Size,d3
		movem.w	d0-d3,-(sp)		; Save them again...
		move.l	d0,d4			; Get the initial X
		move.l	d1,d5			;    and Y
		bsr	PutBlock		; And put it down...
*
*******************************************************************************
*
* Ok, now we start the maze loop.  This should be interesting...
*
MazeLoop:	move.l	d7,d6			; Clear the DONE flag...
		move.w	my_Left(sp),d4		; Get the starting X
MazeLoop1:	move.w	my_Top(sp),d5		; Get the starting Y
*
* Check this spot for more work...
*
MazeLoop2:	move.w	d4,d0			; Get X
		move.w	d5,d1			;    and Y
		move.l	a3,a1			; RPort...
		CALLSYS	ReadPixel		; Check what it is...
		tst.b	d0			; If it is
		beq.s	FoundSpot		;   0 - Possible continue...
		moveq	#1,d6			; Empty means we come again...
*
* Move to next spot...
*
MazeNext:	addq.l	#Y_Size,d5		; Go to next point...
		addq.l	#Y_Size,d5		;	(Y+ 2*Y_Size)
		cmp.w	my_Bottom(sp),d5	; Check if we went too far...
		bcs.s	MazeLoop2		; Try again...
		addq.l	#X_Size,d4		; Go to next column
		addq.l	#X_Size,d4		;	(X+ 2*X_Size)
		cmp.w	my_Right(sp),d4		; Check it...
		bcs.s	MazeLoop1		; Ok, so we continue...
		tst.l	d6			; Check our flag...
		bne.s	MazeLoop		; If not zero, go again...
		bra.s	WaitForClose		; All, done, wait for user...
*
*******************************************************************************
*
* Ok, we are at a possible spot.  Let's check it out...
*
FoundSpot:	move.l	d7,d3			; Clear bit pattern...
*
* Check to the left...
*
CheckLeft:	move.l	d5,d1			; Get Y...
		move.l	d4,d0			; Get X...
		subq.l	#X_Size,d0		; Adjust to the left...
		subq.l	#X_Size,d0
		cmp.w	my_Left(sp),d0		; Check if out of bounds...
		blt.s	CheckRight		; If no good, skip...
		move.l	a3,a1			; Get RPort...
		CALLSYS	ReadPixel		; Get the pixel...
		tst.b	d0			; Check it...
		beq.s	CheckRight		; Skip to next check...
		bset	#LEFT_Bit,d3		; Set the bit...
*
* Check to the right...
*
CheckRight:	move.l	d5,d1			; Get Y...
		move.l	d4,d0			; Get X...
		addq.l	#X_Size,d0		; Adjust to the right...
		addq.l	#X_Size,d0
		cmp.w	my_Right(sp),d0		; Check if out of bounds...
		bgt.s	CheckUp			; If no good, skip...
		move.l	a3,a1			; Get RPort...
		CALLSYS	ReadPixel		; Get the pixel...
		tst.b	d0			; Check it...
		beq.s	CheckUp			; Skip to next check...
		bset	#RIGHT_Bit,d3		; Set the bit...
*
* Check up...
*
CheckUp:	move.l	d4,d0			; Get X...
		move.l	d5,d1			; Get Y...
		subq.l	#Y_Size,d1		; Adjust to the left...
		subq.l	#Y_Size,d1
		cmp.w	my_Top(sp),d1		; Check if out of bounds...
		blt.s	CheckDown		; If no good, skip...
		move.l	a3,a1			; Get RPort...
		CALLSYS	ReadPixel		; Get the pixel...
		tst.b	d0			; Check it...
		beq.s	CheckDown		; Skip to next check...
		bset	#UP_Bit,d3		; Set the bit...
*
* Check Down...
*
CheckDown:	move.l	d4,d0			; Get X...
		move.l	d5,d1			; Get Y...
		addq.l	#Y_Size,d1		; Adjust to the left...
		addq.l	#Y_Size,d1
		cmp.w	my_Bottom(sp),d1	; Check if out of bounds...
		bgt.s	CheckDone		; If no good, skip...
		move.l	a3,a1			; Get RPort...
		CALLSYS	ReadPixel		; Get the pixel...
		tst.b	d0			; Check it...
		beq.s	CheckDone		; Skip to next end of check...
		bset	#DOWN_Bit,d3		; Set the bit...
*
* Ok, we checked every-which-way, and now to see if any worked...
*
CheckDone:	tst.l	d3			; Check if any bits were set...
		beq.s	MazeNext		; No match, on to the next...
		moveq.l	#1,d6			; Set Not-Done flag...
*
* So, there is a possible direction.  Let's see if we can find it...
*
TryToFind:	bsr.s	Random			; Get a random number...
		and.l	d3,d0			; Mask with the directions...
	IFD DOUBLE
		bne.s	TryToFind1		; There is a match...
		bsr.s	Random			; Try again...
		and.l	d3,d0			; Mask it...
	ENDC
	IFD EASYMAZE
		beq.s	TryToFind		; Look again...
	ELSE
		beq.s	MazeNext		; If no match, Next...
	ENDC
TryToFind1:	btst	#UP_Bit,d0		; Check if UP...
		bne.s	Do_UP			; Do the up...
		btst	#LEFT_Bit,d0		; Check if LEFT...
		bne.s	Do_LEFT			; Do the left...
		btst	#RIGHT_Bit,d0		; Check if RIGHT...
		bne.s	Do_RIGHT		; Do the right...
*
* We fall into this...  Do the DOWN...
*
Do_DOWN:	addq.l	#Y_Size,d5		; Move down...
		bsr.s	PutBlock		; Put the block...
		addq.l	#Y_Size,d5		;   down to the next spot...
		bsr.s	PutBlock		; Put the block...
		bra.s	FoundSpot		; Go do another...
*
* Do the RIGHT...
*
Do_RIGHT:	addq.l	#X_Size,d4		; Move over...
		bsr.s	PutBlock		; Put the block...
		addq.l	#X_Size,d4		;   over to the next spot...
		bsr.s	PutBlock		; Put the block...
		bra.s	FoundSpot		; Go do another...
*
* Do the UP...
*
Do_UP:		subq.l	#Y_Size,d5		; Move up...
		bsr.s	PutBlock		; Put the block...
		subq.l	#Y_Size,d5		;   up to the next spot...
		bsr.s	PutBlock		; Put the block...
		bra.s	FoundSpot		; Go do another...
*
* Do the LEFT...
*
Do_LEFT:	subq.l	#X_Size,d4		; Move over...
		bsr.s	PutBlock		; Put the block...
		subq.l	#X_Size,d4		;   over to the next spot...
		bsr.s	PutBlock		; Put the block...
		bra.s	FoundSpot		; Go do another...
*
*******************************************************************************
*
* Wait for the user to press the Close gadget...
*
WaitForClose:	lea	DoneTitle(pc),a0	; Get the address...
		move.l	a0,wd_Title(a4)		; Set the title...
		move.l	intuitionBASE(sp),a6	; Get IntuitionBase...
		move.l	a4,a0			; Get window address...
		CALLSYS	RefreshWindowFrame	; Refresh it...
WaitForClose1:	move.l	a5,a6			; Get EXEC base...
		move.l	wd_UserPort(a4),a0	; Get message port...
		CALLSYS	WaitPort		; Wait for it...
		move.l	wd_UserPort(a4),a0
		CALLSYS	GetMsg			; Get the message
		move.l	d0,a1			; Pointer
		move.l	im_Class(a1),d2		; Get the message type...
		CALLSYS	ReplyMsg		; Reply the message...
		cmpi.l	#CLOSEWINDOW,d2		; Check if it is correct...
		bne.s	WaitForClose1		; Wait for the close...
*
*******************************************************************************
*
	IFD PRINT
		movem.w	(sp)+,d0-d3		; Get the limits...
		addq.l	#X_Size,d2		; Adjust outwards for printing
		subq.l	#X_Size,d0		;  we need the border around
		addq.l	#Y_Size,d3		;  the maze grid...
		subq.l	#Y_Size,d1
		movem.w	d0-d3,-(sp)		; Save them again...
		move.l	intuitionBASE(sp),d6	; Get IntuitionBase...
		bsr.s	AskPrinting		; Check if user wants to print
	ENDC
*
*******************************************************************************
*
* The standard exit routines...
* Close anything that we have opened...
*
NormalExit:	movem.l	(sp)+,d0-d1/d6	; Restore space & intuition pointer...
		move.l	a4,a0		; Get window pointer...
		move.l	d6,a6		; Make sure intuitionbase...
		CALLSYS	CloseWindow	; Close the window...
abortNoWindow:	move.l	a5,a6		; Get EXECbase back...
		move.l	a2,a1		; Get GfxBase...
		CALLSYS	CloseLibrary	; Close it...
abortNoGfx:	move.l	d6,a1		; Get IntuitionBase...
		CALLSYS	CloseLibrary	; Close it...
abortNoIntuit:	move.l	(sp)+,d0	; Get that message back
		beq.s	abortNoWB	; If none, we are done
		move.l	d0,a1		; Get the pointer ready
		FORBID			; manual says we must forbid...
		CALLSYS	ReplyMsg	; ...when returning WB message
abortNoWB:	rts			; RTS out of this task...
*
*******************************************************************************
*
* Random number generator...  It uses the two EXECbase values Idle/DispCount
* It will return a number in d0 that SHOULD be RELATIVELY random...  The
* initial value of d0 is used as an extra seed...
*
Random:		add.l	IdleCount(a5),d0	; Get the idle count...
		add.l	DispCount(a5),d0	; Pull the rest in...
		eor.l	d2,d0			; Add in the seed...
		swap	d2			; Flip the bytes...
		add.l	d0,d2			; Change the seed...
		rts				; Return...
*
*******************************************************************************
*
* Draws my 5x5 block at Current X/Y ...
*
PutBlock:	movem.l	d2/d3,-(sp)		; Save what we mess with...
		move.l	d4,d0			; Get x...
		subq.l	#X_Size_Mod,d0		; Drop by 2...
		move.l	d4,d2			; And the other side...
		addq.l	#X_Size_Mod,d2		; Up by 2...
		move.l	d5,d1			; Get y...
		subq.l	#Y_Size_Mod,d1		; Drop by 2...
		move.l	d5,d3			; And the other side...
		addq.l	#Y_Size_Mod,d3		; Up by 2...
		move.l	a3,a1			; Get RPort...
		CALLSYS	RectFill		; Draw the block...
		movem.l	(sp)+,d2/d3		; Restore it...
		rts				; and return...
*
*******************************************************************************
*									      *
* Register usage through the print section...				      *
*									      *
*	a0	- Scrap							      *
*	a1	- Scrap							      *
*	a2	- Positive IntuiText...					      *
*	a3	- Negative IntuiText...					      *
*	a4	- PrinterIO union...					      *
*	a5	- EXEC Base saved...					      *
*	a6	- Library Base Register...				      *
*	a7	- Stack...  (What else?)				      *
*									      *
*	d0	- Scrap							      *
*	d1	- Scrap							      *
*	d2	- IntuiText size...					      *
*	d3	- Scrap (Memory type during IntuiText allocations...)	      *
*	d4	- Body IntuiText...					      *
*	d5	- RastPort...						      *
*	d6	- Intuition Base (and ....)				      *
*	d7	- Zero...						      *
*									      *
*******************************************************************************
*
* Ask the user if s/he wishes to print the maze...
*
PrintOffset	equ	16	; Number of bytes stack moves
*				  due to bsr and the saving of a2/a3/a4...
AskXsize	equ	162	; AutoRequest X size...
AskYsize	equ	45	; AutoRequest Y size...
WindowOffset	equ	8	; Window pointer on stack...
*
	IFD PRINT
AskPrinting:	movem.l	a2-a4,-(sp)		; Save these...
		move.l	a3,d5			; Save RastPort pointer...
		move.l	a5,a6			; Get EXECbase...
		move.l	#it_SIZEOF,d2		; Size of IntuiText...
		move.l	#MEMF_PUBLIC!MEMF_CLEAR,d3
*
* Now start getting the IntuiText structures...
*
		move.l	d2,d0			; Get Size...
		move.l	d3,d1			; Get memory type...
		CALLSYS	AllocMem
		move.l	d0,d4			; Save BodyText...
		beq.s	NoBodyText		; If none, exit...
		move.l	d2,d0			; Get Size...
		move.l	d3,d1			; Get memory type...
		CALLSYS	AllocMem
		move.l	d0,a2			; Save PositiveText...
		move.l	a2,d0			; Check it...
		beq.s	NoPositiveText		; If none, exit...
		move.l	d2,d0			; Get Size...
		move.l	d3,d1			; Get memory type...
		CALLSYS	AllocMem
		move.l	d0,a3			; Save NegativeText...
		move.l	a3,d0			; Check it...
		beq.s	NoNegativeText		; If none, exit...
*
* Now, set up the structures...
*
		move.l	d4,a1			; Put it somewhere we can use
*
		moveq.l	#2,d0			; Get it_FrontPen...
		move.b	d0,it_FrontPen(a1)	; Save in BodyText...
		move.b	d0,it_FrontPen(a2)	; Save in PositiveText...
		move.b	d0,it_FrontPen(a3)	; Save in NegativeText...
*
		moveq.l	#3,d0			; Get it_BackPen...
		move.b	d0,it_BackPen(a1)	; Save in BodyText...
		move.b	d0,it_BackPen(a2)	; Save in PositiveText...
		move.b	d0,it_BackPen(a3)	; Save in NegativeText...
*
		moveq.l	#RP_JAM1,d0		; Get it_DrawMode...
		move.b	d0,it_DrawMode(a1)	; Save in BodyText...
		move.b	d0,it_DrawMode(a2)	; Save in PositiveText...
		move.b	d0,it_DrawMode(a3)	; Save in NegativeText...
*
		moveq.l	#6,d0			; Get LeftEdge...
		move.w	d0,it_LeftEdge(a1)	; Save in BodyText...
		move.w	d0,it_LeftEdge(a2)	; Save in PositiveText...
		move.w	d0,it_LeftEdge(a3)	; Save in NegativeText...
*
		moveq.l	#3,d0			; Get TopEdge...
		move.w	d0,it_TopEdge(a1)	; Save in BodyText...
		move.w	d0,it_TopEdge(a2)	; Save in PositiveText...
		move.w	d0,it_TopEdge(a3)	; Save in NegativeText...
*
		lea	Text_Attr(pc),a0	; Get address of font...
		move.l	a0,it_ITextFont(a1)	; Save in BodyText...
		move.l	a0,it_ITextFont(a2)	; Save in PositiveText...
		move.l	a0,it_ITextFont(a3)	; Save in NegativeText...
*
		lea	AskMessage(pc),a0	; Get address of Body...
		move.l	a0,it_IText(a1)		; Save in BodyText...
		lea	OkMessage(pc),a0	; Get address of Positive...
		move.l	a0,it_IText(a2)		; Save in PositiveText...
		lea	NoMessage(pc),a0	; Get address of Negative...
		move.l	a0,it_IText(a3)		; Save in NegativeText...
*
AskTheUser:	move.l	WindowOffset(sp),a0	; Get window...
		move.l	d7,d0			; Clear Positive Flags...
		move.l	d7,d1			; Clear Negative Flags...
		move.l	d2,-(sp)		; Save IntuiText Size...
		move.l	#AskXsize,d2		; Get X-size...
		move.l	#AskYsize,d3		; Get Y-size...
		move.l	d6,a6			; Get intuitionBASE...
		CallSYS	AutoRequest		; Ask the user...
		move.l	a5,a6			; Restore ExecBase...
		move.l	(sp)+,d2		; Restore...
		tst.l	d0			; Check the result...
		beq.s	NoPrint			; If FALSE, no-print...
*
*******************************************************************************
*
* Ok, we must print now.
*
		move.l	#iodrpr_SIZEOF,d0	; Size of IODRPReq...
		move.l	#MEMF_PUBLIC!MEMF_CLEAR,d1
		CallSYS	AllocMem		; Get memory...
		move.l	d0,a4			; Get pointer...
		move.l	a4,d0			; Check it...
		beq.s	ExitPrint		; Can't get IODRPReq...
*
		move.l	d7,a1			; Clear a1...
		CallSYS	FindTask		; Get our task...
		move.l	d0,a1			; Move it into a1...
		lea	pr_MsgPort(a1),a1	; Point to message port...
		move.l	a1,MN_REPLYPORT(a4)	; Save the reply port...
		move.l	#iodrpr_SIZEOF-MN_SIZE,MN_LENGTH(a4)	; Save size...
*
		lea	PrinterName(pc),a0	; Get name of printer
		move.l	d7,d0			; Clear unit number...
		move.l	d7,d1			; Clear flags...
		move.l	a4,a1			; Get pointer to PrinterIO
		CallSYS	OpenDevice		; Open printer.device...
		tst.l	d0			; Check for error...
		bne.s	PrinterError		; Can't open printer...
*
		lea	ColourMap(pc),a0	: Pointer to colour map...
		move.l	a0,io_ColorMap(a4)	; Store it...
		move.l	d5,io_RastPort(a4)	; Pointer to RastPort...
*		move.l	#V_HIRES,io_Modes(a4)	; Set mode to HiRes...
*
* This sets the x/y start/end of the RastPort to dump...
*
		move.w	PrintOffset+my_Left(sp),d0
		move.w	d0,io_SrcX(a4)		; Start of rectangle-X
		move.w	PrintOffset+my_Right(sp),d1
		sub.w	d0,d1
		move.w	d1,io_SrcWidth(a4)	; Size of rectangle-X
*
		move.w	PrintOffset+my_Top(sp),d0
		move.w	d0,io_SrcY(a4)		; Start of rectangle-Y
		move.w	PrintOffset+my_Bottom(sp),d1
		sub.w	d0,d1
		move.w	d1,io_SrcHeight(a4)	; Size of rectangle-Y
*
* Set the special to FULL size
*
		move.w	#SPECIAL_FULLCOLS!SPECIAL_FULLROWS,io_Special(a4)
*
* And, finally, the DumpRPort command...
*
		move.w	#PRD_DUMPRPORT,IO_COMMAND(a4)	; Printer command...
*
		move.l	a4,a1			; Get PrinterIO....
		CallSYS	DoIO			; Send the command...
		move.l	a4,a1			; Get PrinterIO...
		CallSYS	CloseDevice		; Close it...
PrinterError:	move.l	a4,a1			; Pointer to PrinterIO
		move.l	#iodrpr_SIZEOF,d0	; Size of PrinterIO...
		CallSYS	FreeMem			; Release the memory...
ExitPrint:	move.l	d4,a1			; Get body text again...
		bra.s	AskTheUser		; Ask again...
*
*******************************************************************************
*
* Exit the print routine, freeing all memory that we have...
*
NoPrint:	move.l	a3,a1			; Get address
		move.l	d2,d0			; Get Size
		CallSYS	FreeMem
NoNegativeText:	move.l	a2,a1			; Get address
		move.l	d2,d0			; Get Size
		CallSYS	FreeMem
NoPositiveText:	move.l	d4,a1			; Get address
		move.l	d2,d0			; Get Size
		CallSYS	FreeMem
NoBodyText:	movem.l	(sp)+,a2-a4		; Restore them again...
		rts
	ENDC
*
*******************************************************************************
*
* The data section...
*
NewWindowStuff	dc.w	0,11,XMax,YMax	; The window pos/size
		dc.b	2,1		; Window pens...
		dc.l	CLOSEWINDOW	; IDCMP setting...
		dc.l	WINDOWCLOSE!WINDOWDEPTH!WINDOWDRAG	; Smart refresh
		dc.l	0,0		; No gadgets/checkmark
		dc.l	TheTitle	; The title of the window...
		dc.l	0,0		; No screen/bitmap...
		dc.w	0,0,0,0		; No sizing stuff...
		dc.w	WBENCHSCREEN	; The window's screen...
*
DoneTitle:	dc.b	'Done!  '
TheTitle:	dc.b	'MKSoft MAZE Maker',0
intuitionName	dc.b	'intuition.library',0
graphicsName	dc.b	'graphics.library',0
*
*******************************************************************************
*
* This is the data section if PRINT is defined...
*
	IFD PRINT
		ds.l	0		; Make sure we long-align...
*
* This colour map is used for the DumpRPort call to make the maze walls
* black and all else white...
*
ColourMap:	dc.b	0
		dc.b	0
		dc.w	4		; Number of entries
		dc.l	ColourTable	; Pointer...
ColourTable:	dc.w	$0FFF		; White for colours 0 to 2...
		dc.w	$0FFF
		dc.w	$0FFF
		dc.w	$0000		; Black for colour 3...
*
Text_Attr:	dc.l	FontName	; Name of the font...
		dc.w	8		; Y-Size of font...
		dc.b	0		; No style flags...
		dc.b	0		; No flags...
FontName:	dc.b	'topaz.font',0
*
AskMessage:	dc.b	'Print this maze?',0
OkMessage:	dc.b	'Yes',0
NoMessage:	dc.b	'No',0
*
PrinterName:	dc.b	'printer.device',0
	ENDC
*
*******************************************************************************
*
* And, with that we come to the end of another full-length feature staring
* that wonderful MC680x0 and the Amiga system.  Join us again next time
* for more Wonderful World of Amiga...  Until then, keep boinging...
*
		end
