;*** Also needs O/S 2 style CLI Args interpretation to add more parameters

;*** VerticalScroller FILE/A,LOOP/S,PAPER/N,PEN/N,SPEED/S

;		FILE - The name of a text file to be used as scroll text.
;		LOOP - If this switch is specified the scroller will loop around
;              to the start when the end of the text file is reached.
;              (default is to exit at end of text)
;      PAPER - This command allows you to specify a paper colour, in
;              decimal, you can use EVAL to calculate it's number.
;              (EG: EVAL 0x0rgb, where r,g + b are 0-F)
;        PEN - This command allows you to specify a pen colour.
;      SPEED - Speed of scroller, 0 is fastest, any other number specifies
;              how many VBLs are skipped between each scroll.


;Possible additions in future are..
;
;    HIRES/S - Open a hi-res screen (default lowres)
;    LACED/S - Open an interlaced screen (default non-laced)
;
;    SPEED/N - Speed of scroller


			SECTION		program,CODE

Start:	
		;Open dos library
			Move.l	4.w,a6
			Lea		DosName,a1
			Jsr		_LVOOldOpenLibrary(a6)
			Move.l	d0,DosLib

		;Check the dos library version (does anyone still have K1.3 ?!)
			Move.l	d0,a0
			CMP.W	#37,LIB_VERSION(a0)
			BLO		OldKick

		;Call Read Args to pre-parse the command line
			Move.l	DosLib,a6
			Move.l	#Template,d1
			Move.l	#Array,d2
			Moveq.l	#0,d3
			Jsr		_LVOReadArgs(a6)
			Move.l	d0,RdArgs

		;If Args were invalid print syntax message and quit
			Beq		ArgsError
		
		;Try to get a lock on the file to be displayed.
			Move.l	DosLib,a6
			Move.l	Array,d1
			Moveq.l	#ACCESS_READ,d2
			Jsr		_LVOLock(a6)
			
		;Was it successful ?
			Tst.l	d0
			Beq		FileNotFound

		;Remember the lock for later
			Move.l	d0,-(a7)

		;Examine the file
			Move.l	DosLib,a6
			Move.l	d0,d1
			Move.l	#Buffer,d2
			Jsr		_LVOExamine(a6)
			
		;Remove the lock from the file
			Move.l	(a7)+,d1
			Move.l	DosLib,a6
			Jsr		_LVOUnLock(a6)
			
		;Check that what we have a lock on isn't a directory
			Move.l	Buffer+4,d0
			Tst.l	d0
			Bmi		IsAFile
			Bra		FileNotFound	
		
		;Calc how much memory is needed for the file.
IsAFile:	Move.l	Buffer+124,d0
			Addq.l	#2,d0
			Move.l	d0,MemSize
				
		;Try to allocate memory to load file into
			Move.l	4.w,a6
			Move.l	MemSize,d0
			Moveq.l	#MEMF_PUBLIC,d1
			Jsr		_LVOAllocMem(a6)
			
		;Check for "Out of Memory" error.
			Tst.l	d0
			Beq		OutOfMemory
			
		;Remember where out memory is (Quite important!)
			Move.l	d0,MemPtr
			
		;Now try to open the actual file for reading
			Move.l	DosLib,a6
			Move.l	Array,d1
			Move.l	#MODE_OLDFILE,d2
			Jsr		_LVOOpen(a6)
			
		;Was this successful.
			Tst.l	d0
			Beq		FileNotOpened
			
		;Remember file handle for later
			Move.l	d0,-(a7)
			
		;Read the file into the allocated memory
			Move.l	d0,d1
			Move.l	MemPtr,d2
			Move.l	MemSize,d3
			Subq.l	#2,d3
			Jsr		_LVORead(a6)
			
		;Close the file
			Move.l	DosLib,a6
			Move.l	(a7)+,d1
			Jsr		_LVOClose(a6)
			
		
		;Put two NULL bytes at end of the memory area to mark EOF
			Move.l	MemPtr,a0
			Add.l	MemSize,a0
			Move.b	#0,-1(a0)
			Move.b	#0,-2(a0)
			
		;Check the file ended with a chr$(10)
			Cmp.b	#10,-3(a0)
			Beq		MarkedOkay
			Move.b	#10,-2(a0)
		
		;Set the text pointer to the start of our file in memory.	
MarkedOkay:	Move.l	MemPtr,d0
			Move.l	d0,String_Ptr
			
		;Check if there was a PEN parameter
			Move.l	Array+4,d0
			Tst.l	d0
			Beq		NoPen
		
		;Get the parameter
			Move.l	d0,a0
			Move.l	(a0),d0
			Move.w	d0,Pen	

		;Check if there was a PAPER parameter
NoPen:		Move.l	Array+8,d0
			Tst.l	d0
			Beq		NoPaper			
	
		;Get the parameter
			Move.l	d0,a0
			Move.l	(a0),d0
			Move.w	d0,Paper
	
		;Check if the HIRES switch was given.
NoPaper:	Tst.l	Array+16
			Beq		NoHires

		;It was so change set up to Hires mode
			Move.w	#V_HIRES,mode
			Move.l	#80,Width

		;Check if there was a speed parameter
NoHires:	Move.l	Array+20,d0
			Tst.l	d0
			Beq		NoSpeed
			
		;Get the parameter
			Move.l	d0,a0
			Move.l	(a0),d0
			Move.l	d0,Speed
			
		;Open Graphics Library	
NoSpeed:	Move.l	4.w,a6
			Lea	GfxName,a1
			Jsr	_LVOOldOpenLibrary(a6)
			Move.l	d0,GfxLib

		;Open Intuition Library
			Lea	IntName,a1
			Jsr	_LVOOldOpenLibrary(a6)
			Move.l	d0,IntLib

		;Open New Screen
			Move.l	IntLib,a6
			Lea	NewScr,a0
			Jsr	_LVOOpenScreen(A6)
			Move.l	d0,ScreenBase
			Beq		NoScreen

		;Get RastPort
			Add.l	#84,D0
			Move.l	D0,RastPrt

		;Get ViewPort
			Move.l	ScreenBase,d0
			Add.l	#44,d0
			Move.l	d0,ViewPrt
			
		;Set the paper colour
			Move.l	GfxLib,a6
			Move.l	ViewPrt,a0
			Move.w	Paper,d0
			Move.b	d0,d3
			And.l	#$F,d3
			Lsr.w	#4,d0
			Move.b	d0,d2
			And.l	#$f,d2
			Lsr.w	#4,d0
			Move.b	d0,d1
			And.l	#$f,d1
			Moveq.l	#0,d0
			Jsr		_LVOSetRGB4(a6)
		
		;Set the pen colour
			Move.l	GfxLib,a6
			Move.l	ViewPrt,a0
			Move.w	Pen,d0
			Move.b	d0,d3
			And.l	#$F,d3
			Lsr.w	#4,d0
			Move.b	d0,d2
			And.l	#$f,d2
			Lsr.w	#4,d0
			Move.b	d0,d1
			And.l	#$f,d1
			Moveq.l	#1,d0
			Jsr		_LVOSetRGB4(a6)

		;Clear the screen
			Move.l	GfxLib,a6	
			Move.l	RastPrt,a1
			Clr.l	d0
			Jsr		_LVOSetRast(a6)
		
		;Turn off task switching (only way we can stop jerking)
			Move.l	4.w,a6
			Jsr		_LVOForbid(a6)

		;Switch of the Mouse Pointer (It's frozen with Forbid() anyway!)
			Move.w	#$20,$dff096

		;Wait for Copper to scan top of screen
WaitLoop:	Move.l	$dff004,d5
			And.l	#$0001ff00,d5
			Cmp.l	#$00001000,d5
			Bne.s	WaitLoop

		;Is frame count Zero ?
			Tst.l	Frames
			Bne		SkipFrame

		;Yes, so reset frame count and call scroller.
			Move.l	Speed,d0
			Move.l	d0,Frames
			Jsr		Scroller

		;Has the scroller asked us to quit ?
			Tst.b	Quit_Flag
			Beq		Finish
			Bra		CheckMouse
			
		;Decrease the frame counter
SkipFrame:	Move.l	Frames,d0
			Subq.l	#1,d0
			Move.l	d0,Frames
			
		;Wait for copper to scan line 16 (we may still be on the
		;timing scan-line on faster machines!)
WaitLoop2:	Move.l	$dff004,d5
			And.l	#$0001ff00,d5
			Cmp.l	#$00003000,d5
			Bne.s	WaitLoop2

		;If user isn't pressing the mouse button then do it again.
CheckMouse:	Btst	#6,$BFE001
			Bne.s	WaitLoop


		;Turn task switching back on
Finish:		Move.l	4.w,a6
			JSR		_LVOEnable(a6)

		;Close the Screen
			Move.l	IntLib,a6
			Move.l	ScreenBase,a0
			Jsr		_LVOCloseScreen(A6)

NoScreen:
		;Close the gfx library
			Move.l	4.w,a6
			Move.l	GfxLib,a1
			Jsr		_LVOCloseLibrary(a6)
			
		;Close the intuition library
			Move.l	4.w,a6
			Move.l	IntLib,a1
			Jsr		_LVOCloseLibrary(a6)

		;Free back the memory
Exit_FNO:	Move.l	4.w,a6
			Move.l	MemPtr,a1
			Move.l	MemSize,d0
			Jsr		_LVOFreeMem(a6)

		;Free the RdArgs structure
Exit_FNF:	Move.l	DosLib,a6
			Move.l	RdArgs,d1
			Jsr		_LVOFreeArgs(a6)

		;Close the dos library
OldKick:	Move.l	4.w,a6
			Move.l	DosLib,a1
			Jsr		_LVOCloseLibrary(a6)

			Clr.l	d0
			Rts

		;Print the command syntax for user.
ArgsError:	Move.l	DosLib,a6
			Move.l	#SyntaxText,d1
			Jsr		_LVOPutStr(a6)
			
			Bra.s		OldKick


		;Print error because no file could be locked.
FileNotFound:	Move.l	DosLib,a6
				Move.l	#NoFileText,d1
				Jsr		_LVOPutStr(a6)
				
				Bra.s	Exit_FNF

		;Print error because no memory for file.
OutOfMemory:	Move.l	DosLib,a6
				Move.l	#NoMemText,d1
				Jsr		_LVOPutStr(a6)
				
				Bra.s	Exit_FNF

		;Print error because no file could be opened.
FileNotOpened:	Move.l	DosLib,a6
				Move.l	#NoFileText,d1
				Jsr		_LVOPutStr(a6)
				
				Bra.s	Exit_FNO



		;Now comes our actual scroll routine, calling this will scroll
		;the screen by one pixel.

Scroller:

		;Scroll the display up one line.
			Move.l	GfxLib,a6
			Move.l	RastPrt,a1
			Clr.l	d0						;dx
			Moveq.l	#1,d1					;dy
			Clr.l	d2						;min x
			Clr.l	D3						;min y
			Move.l	#640,d4					;max x
			Move.l	#250,d5					;max y
			Jsr		_LVOScrollRaster(a6)

		;Does a new line of text need to be printed ?
			Subq.w	#1,LineCount
			Beq	NewLine

		;If not then we've finished.
			Rts

		;A new line of text needs printing.
		
NewLine:		

		;Restart line counter (Font is 8 rows high.)
				Move.w	#8,LineCount

		;Get the pointer to next string of text. (in both a0 and a1)
			Move.l	String_Ptr,a0
			Move.l	a0,a1

		;Check that line isn't blank
			Cmp.b	#10,(A1)		
			Beq		EndOfLine
		
		;Count the length of the text using d0
			Clr.l	D0
Count_Loop:	Cmp.b	#10,(A1)
			Beq	Count_End
			Addq.l	#1,A1
			Addq.l	#1,D0		
			Bra.s	Count_Loop

		;If the text is longer than 40/80 chars then truncate it.
Count_End:	Move.l	Width,d1
			Cmp.l	d1,d0
			Bmi		DontTrunk
			Move.l	d1,d0

		;Store the new string pointer (points at the EOL char)
DontTrunk:	Move.l	a1,String_Ptr

		;Store the text pointers
			Movem.l	D0/A0,-(A7)

		;Calculate X-Position (ScreenWidth-TextLength)*4
			Exg	D0,D1
			Move.l	Width,D0	
			Sub.l	D1,D0
			Lsl.l	#2,D0

		;Position Pen for printing Text
			Move.l	GfxLib,A6
			Move.l	RastPrt,A1
			Move.l	#248,D1		;y
			Jsr		_LVOMove(a6)

		;Restore the text pointers
			Movem.l	(A7)+,D0/A0

		;Now Print the text.
			Move.l	RastPrt,a1
			Jsr		_LVOText(a6)

		;Now advance pointer past the EOL char
EndOfLine:		Addq.l	#1,String_Ptr

		;Has the end of the text been reached (NULL byte)
				Move.l	String_Ptr,a0
				Tst.b	(a0)
				Bne		Not_Text_End

		;Is the Loop flag set ?
				Tst.l	Array+12
				Beq		NoLoopFlag

		;Yes, so set the text pointer back to the start
				Move.l	MemPtr,d0
				Move.l	d0,String_Ptr
				Rts

		;Tell main loop that we've finished and it's time to quit.				
NoLoopFlag		Move.b	#0,Quit_Flag

Not_Text_End:	Rts

 SECTION data,DATA

NewScr:		dc.w	0,0,640,256		;x-min,y-min,width,height
			dc.w	1			;depth 1 bitplane
			dc.b	0,1			;detailpen,blockpen
mode:		dc.w	0,15			;viewmodes,type=customscreen
			dc.l	textattr,0		;textattr,title=none
			dc.l	0,0			;gadgets,bitmap

textattr:	dc.l	fontname		;Fontname
			dc.w	8			;fontsize
			dc.b	0			;Style=normal
			dc.b	1			;flags=romfont

Speed:		dc.l	3
Frames:		dc.l	0
Width:		dc.l	40
LineCount:	dc.w	1
GfxLib:		dc.l	0
IntLib:		dc.l	0
DosLib:		dc.l	0
RdArgs:		dc.l	0
RastPrt:	dc.l	0
ViewPrt:	dc.l	0
ScreenBase:	dc.l	0
MemSize:	dc.l	0
MemPtr:		dc.l	0
String_Ptr:	dc.l	0
Pen:		dc.w	$F0F
Paper:		dc.w	0

Array:		dc.l	0,0,0,0,0,0
Template:	dc.b	"FILE/A,PEN/N/K,PAPER/N/K,LOOP/S,HIRES/S,SPEED/N/K",0
IntName:	dc.b	"intuition.library",0
GfxName:	dc.b	"graphics.library",0
DosName:	dc.b	"dos.library",0
fontname:	dc.b	"topaz.font",0
Quit_Flag:	dc.b	$ff

SyntaxText:	dc.b	"VerticalScroller V1.0       ©1999 Mike Archer",10
			dc.b	10
			dc.b	"  Syntax: VerticalScroller <file>",10
			dc.b	0

NoFileText:	dc.b	"ERROR: Could not open file.",10,0

NoMemText:	dc.b	"ERROR: Not enough memory.",10,0


					SECTION		storage,BSS
					
Buffer:			ds.b		260

