	INCLUDE	"FileIO.i"
	INCLUDE	"IFF.i"

	;CAPE Directives
	OBJFILE	"rad:ANIMInfo.o"
	OPTIMON
	SMALLOBJ
	ADDSYM

			SECTION	CopyLibCode,CODE

	;from SmallStart.o
	XREF	_DOSBase,_SysBase,_BUFFER

	;from functions.o
	XREF	asprintf,multiply

	;from amiga.lib or small.lib
	XREF	_LVOOpenLibrary,_LVOCloseLibrary,_LVOOpenWindow,_LVOCloseWindow
	XREF	_LVOAllocMem,_LVOFreeMem
	XREF	_LVOGetMsg,_LVOReplyMsg,_LVOWait,_LVOWaitPort
	XREF	_LVOMove,_LVOText,_LVOSetAPen,_LVORectFill
	XREF	_LVOOpen,_LVORead,_LVOWrite,_LVOClose,_LVODelay
	XREF	_LVOLock,_LVOUnLock,_LVOExamine
	XREF	_LVOClearPointer

MODE_OLDFILE equ 1005
MODE_NEWFILE equ 1006
LIB_VERSION  equ 33

	XDEF	print_line
print_line:
		movem.l	a2/a4,-(sp)
		movea.l	a0,a4
		movea.l	RastPort,a2
		moveq		#5,d0
		moveq		#26,d1			;allow for window title bar
		lea		yPos,a1
		add.w		(a1),d1			;get y position to print at
		addq.w	#8,(a1)			;increment 1 line down for next time
		movea.l	a2,a1				;our window's RastPort
		movea.l	_GfxBase,a6
		jsr		_LVOMove(a6)
		movea.l	a4,a0
len	move.b	(a4)+,d0
		bne.s		len
		subq.l	#1,a4
		move.l	a4,d0
		sub.l		a0,d0				;length of string
		movea.l	a2,a1
		movem.l	(sp)+,a2/a4
		jmp		_LVOText(a6)

print_and_delay:
		bsr.s		print_line
		;fall through to delay

delay_msg:
	;---Leave the msg displayed for a while
		moveq		#100,d1
		movea.l	_DOSBase,a6
		jsr		_LVODelay(a6)
	;---clear msg
		moveq		#5,d0
		moveq		#26-8,d1
		add.w		yPos,d1
		movea.l	RastPort,a2
		movea.l	a2,a1
		movea.l	_GfxBase,a6
		jsr		_LVOMove(a6)
		moveq		#36,d0
		lea		Spaces,a0
		movea.l	a2,a1
		jmp		_LVOText(a6)

	XDEF	clear_window
clear_window:
		movem.l	d2/d3/a2/a6,-(sp)
		movea.l	_GfxBase,a6
		moveq		#0,d0
		movea.l	RastPort,a1
		movea.l	a1,a2
		jsr		_LVOSetAPen(a6)
		moveq		#4,d0
		moveq		#15,d1
		move.w	#636,d2
		moveq		#80,d3
		movea.l	a2,a1
		jsr		_LVORectFill(a6)
		moveq		#1,d0
		movea.l	a2,a1
		jsr		_LVOSetAPen(a6)
		movem.l	(sp)+,d2/d3/a2/a6
		rts

   XDEF _main
_main:
;---Open Gfx Library
		movea.l	_SysBase,a6
		moveq		#LIB_VERSION,d0
		lea		GfxName,a1
		jsr		_LVOOpenLibrary(a6)
		move.l	d0,_GfxBase
		bne.s		xxx
		rts
;---Open Intuition
xxx	moveq		#LIB_VERSION,d0
		lea		IntuitionName,a1
		jsr		_LVOOpenLibrary(a6)
		move.l	d0,_IntuitionBase
		beq		clG
;---Open the main window
		lea		newWindow,a0
		move.l	a6,-(sp)
		movea.l	d0,a6
		jsr		_LVOOpenWindow(a6)
		move.l	(sp)+,a6
		move.l	d0,WindowPtr
		beq		clI
		movea.l	d0,a0
		move.l	50(a0),RastPort
;---Open the dissidents FileIO (requester) library
		moveq		#0,d0					;any version (for now)
		lea		RequesterName,a1
		movea.l	_SysBase,a6
		jsr		_LVOOpenLibrary(a6)
		move.l	d0,_RequesterBase
		bne.s		gotRQ
		lea		CantFindFileIO,a0
		bsr		print_and_delay
		bra		clW
;---Get the FileIO Structure
gotRQ	movea.l	d0,a6
		jsr		_LVOGetFileIO(a6)
		move.l	d0,FileIO
		bne		gotIO
		lea		IOerR,a0
		bsr		print_and_delay
		bra		clF
	;---Set up certain options in the FileIO
gotIO	movea.l	d0,a0
		Bset.b	#INFO_SUPPRESS,1(a0)   ;INFO_SUPPRESS ON
	;--Set up the XY co-ordinates of where the requester will open
	; If we used DoFileIOWindow(), we wouldn't need to set co-ordinates.
		moveq		#6,d0
		move.w	d0,FILEIO_X(a0)  ;x position
		moveq		#11,d0
		move.w	d0,FILEIO_Y(a0)  ;y position
	;---Mandatory setup: The drawmodes and buffer
		move.l	#_BUFFER,FILEIO_BUFFER(a0)
		moveq		#2,d0
		move.b	d0,FILEIO_DRAWMODE(a0)
		move.b	d0,FILEIO_PENA(a0)
	;---Open the dissidents ilbm.library
		moveq		#0,d0				;any version (for now)
		lea		ILBMName,a1
		movea.l	_SysBase,a6
		jsr		_LVOOpenLibrary(a6)
		move.l	d0,_ILBMBase
		bne.s		E3
		lea		CantFindIlbm,a0
		bsr		print_and_delay
		bra		delFile
;********************** ANIMInfo IDCMP LOOP ******************************
	;---Create a mask of the Window's UserPort's mp_Sigbit (to wait on)
E3		movea.l	WindowPtr,a3
		movea.l	86(a3),a0
		move.b	15(a0),d0
		moveq		#0,d7
		Bset.l	d0,d7
	;---Get the next message queued at our UserPort
E4		movea.l	86(a3),a0
		movea.l	_SysBase,a6
		jsr		_LVOGetMsg(a6)
		move.l	d0,d1
		bne.s		E7
	;---If no more msgs, check if we are ready to exit the program
E5		Btst.b	#0,Quit
		beq		clILBM
	;---Wait for a message sent to our Window (from Intuition)===
E6		move.l	d7,d0
;		movea.l	_SysBase,a6
		jsr		_LVOWait(a6)
		bra.s		E4
	;---Copy all the info we want from the IntuiMessage
E7		movea.l	d0,a1
		lea		20(a1),a0	;get the address of the first field to copy.
		move.l	(a0)+,d6		;Copy the Class field to d6
		move.w	(a0)+,d5		;Copy the Code field to d5
		move.w	(a0)+,d4		;Copy the qualifier field to d4
		movea.l	(a0)+,a2		;Copy the IAddress field to a2
		move.w	(a0)+,d3		;Copy MouseX position to d3
		move.w	(a0)+,d2		;Copy MouseY position to d2
	;---Now reply to the message so Intuition can dispose of it
E8		;Address of the message is in a1.
		jsr		_LVOReplyMsg(a6)
	;---What type of msg? Handle it.
		Bclr.l	#3,d6		;MOUSEBUTTONS
		bne.s		BUT
		Bclr.l	#9,d6		;CLOSEWINDOW
		beq.s		E4
	;=========CLOSEWINDOW============
		Bclr.b	#0,Quit
		bra.s		E4
	;=========MOUSEBUTTONS===========
	;---Make sure that it's an UP select if MOUSEBUTTONS
BUT	subi.b	#$68,d5
		beq.s		E4				;ignore down
		clr.w		yPos			;reset to top of window
		bsr		clear_window
	;---Allow the user to choose the file, and then examine it
		bsr.s		show_info
		bra.s		E4
;*************************** Exit Routine *****************************
	;---Close the ilbm lib
clILBM	movea.l	_ILBMBase,a1
			movea.l	_SysBase,a6
			jsr		_LVOCloseLibrary(a6)
	;---Release the FileIO
delFile	movea.l	FileIO,a1
			movea.l	_RequesterBase,a6
			jsr		_LVOReleaseFileIO(a6)
	;---Close the requester lib
clF		movea.l	_RequesterBase,a1
			movea.l	_SysBase,a6
			jsr		_LVOCloseLibrary(a6)
	;---Close the window
clW		movea.l	WindowPtr,a0
			movea.l	_IntuitionBase,a6
			jsr		_LVOCloseWindow(a6)
	;---Close the Intuition Lib
clI		movea.l	_SysBase,a6
			movea.l	_IntuitionBase,a1
			jsr		_LVOCloseLibrary(a6)
	;---Close the graphics lib
clG		movea.l	_GfxBase,a1
			jmp		_LVOCloseLibrary(a6)  ;returns to startup code

;==========================================================================
;show_info(window)
;				a3

	XDEF	show_info
show_info:
		movem.l	d2/d3/d4/d5/a4,-(sp)
	;---DoFileIO(FileIO, window)
		movea.l	a3,a1
		movea.l	FileIO,a0
		movea.l	_RequesterBase,a6
		jsr		_LVODoFileIO(a6)
		move.l	d0,d1
		beq		L92		;Error in Filename selection (shouldn't happen, but...)
		addq.l	#1,d0
		beq		L92		;If -1, user must have selected CANCEL
		;Buffer address in d1
	;---Check FileSize
		movea.l	FileIO,a0
		move.l	FILEIO_FILESIZE(a0),d0
		beq		L92		;must be a dir or disk that was chosen
	;---Get a lock on the full pathname
		moveq		#-2,d2
		;Buffer address in d1
		movea.l	_DOSBase,a6
		jsr		_LVOLock(a6)
		move.l	d0,d5
		beq		L92
	;---Open the File for Reading
		moveq		#0,d2
		move.w	#MODE_OLDFILE,d2
		lea		_BUFFER,a0
		move.l	a0,d1
		jsr		_LVOOpen(a6)
		move.l	d0,d4
		beq		L92
	;---Set the WAIT mouse pointer
		movea.l	_RequesterBase,a6
		movea.l	a3,a0
		jsr		_LVOSetWaitPointer(a6)
	;---Examine the File (ExamineFORM is our installed custom FORMhandler)
		;---IFFP = LoadILBM(file, Vectors, ILBMFrame)
		lea		Vectors,a0
		movea.l	_ILBMBase,a6
		lea		ILBMFrame,a1
		Bclr.b	#ANIMFLAG,iUserFlags(a1)
		moveq		#-1,d0
		move.l	d0,NumOfFrames  ;initially, -1
		move.l	d4,d1
		jsr		_LVOLoadILBM(a6)
	;---Did we find an ILBM or ANIM? If so, LoadILBM() returned IFF_DONE
		move.l	d0,d1
		addq.l	#2,d1
		bne.s		erriff
	;---Print out the number of frames if an ANIM
		lea		ItsILBM,a0
		Btst.b	#ANIMFLAG,ILBMFrame+iUserFlags
		beq.s		pfnum
		move.l	NumOfFrames,-(sp)
		addq.l	#1,(sp)
		lea		_BUFFER,a0
		lea		FramePrint,a1
		jsr		asprintf
		addq.l	#4,sp
		bra.s		pfnum
	;---Display the returned IFFP code
erriff:
		jsr		_LVOGetIFFPMsg(a6)
		movea.l	d0,a0
pfnum	bsr		print_line
	;---Restore mouse pointer
		movea.l	a3,a0
		movea.l	_IntuitionBase,a6
		jsr		_LVOClearPointer(a6)
	;---Close File, Free lock
		move.l	d4,d1
		movea.l	_DOSBase,a6
		jsr		_LVOClose(a6)
		move.l	d5,d1
		jsr		_LVOUnLock(a6)
L92	movem.l	(sp)+,d2/d3/d4/d5/a4
		rts

;=========================================================================
;This is the custom FORMhandler we installed in the Vectors Structure
;passed to LoadILBM(). The lib routine LoadILBM() will call this routine
;for every FORM it encounters in the opened file with the following
;registers as follows:
;
; IFFP = ExamineFORM(ID, Context, Vectors, ILBMFrame, PROPList)
;  d0						d0		a0			a2			a3				a4
;
; Our routine is going to check for ANIMs or ILBMs, (ignoring all other 
; FORMs), and print out info about the ILBM (or first Frame of the ANIM
; and total # of Frames).

	XDEF	ExamineFORM
ExamineFORM:
		movem.l  d2/a2/a5/a6,-(sp)
		movea.l  _ILBMBase,a6
	;---Put the Context in a convenient register
		movea.l  a0,a5
	;---if ID = ANIM, set ANIM flag and do anim parse
		cmpi.l	#ID_ANIM,d0
		beq.s		animf
	;---if ID = ILBM (this will be an ANIM frame if we're inside of an ANIM)
		cmpi.l	#ID_ILBM,d0
		bne.s		nonif
	;---If an ILBM, increment NumOfFrames
		addq.l	#1,NumOfFrames
	;---If we haven't displayed the info on an ILBM yet, do so. Otherwise,
	;   just exit.
		bne.s		Aout	;returning an ID, or IFF_OKAY continues to next group
		bra.s		ilBm 
animf	Bset.b	#ANIMFLAG,iUserFlags(a3)
;**********Open a non-ILBM FORM and recursively scan it for ILBMs.********
;The initial 'ANIM' header chunk executes here.
	;---While IFFP = IFF_OKAY, do GetF1ChunkHdr(Context)
nonif	movea.l	a5,a0
		jsr		_LVOGetF1ChunkHdr(a6)
		move.l	d0,d1
		bpl.s		nonif
	;---If IFFP = END_MARK, then return IFF_OKAY (to continue scanning file)
	;   unless this was an ANIM. For ANIM, return IFF_DONE instead of IFF_OKAY
	;   (because we hit END_MARK, so we got to the end of the FORM without error)
		addq.l	#1,d1
		bne.s		Aout
		Btst.b	#ANIMFLAG,iUserFlags(a3)
		bne.s		aok
		moveq		#IFF_OKAY,d0
Aout	movem.l	(sp)+,d2/a2/a5/a6
		rts
aok	moveq		#IFF_DONE,d0
		bra.s		Aout
;*******************Load a Frame (ILBM)********************************
	;---See if there is an ILBM PROP in PROPList
ilBm	movea.l	a4,a1
		;ILBM ID in d0
		jsr		_LVOSearchPROP(a6)
		beq.s		nAck
	;---copy PROP ILBMFrame to our master ILBMFrame
		;data (frame) part of ILBMPropFrame in d0
      movea.l  a3,a1
		jsr		_LVOCopyILBMProp(a6)
	;---Get the next chunk ID and process it
nAck	movea.l	a5,a0
		jsr		_LVOGetFChunkHdr(a6)
		move.l	d0,d2
		bmi		L334			;IFFP error
		cmpi.l	#'ANHD',d2
		beq		Anhdh
		cmpi.l	#'BMHD',d2
		beq		Bmhdh
		cmpi.l	#'CAMG',d2
		beq		Camgh
		cmpi.l	#'CMAP',d2
		beq		Cmaph
		cmpi.l	#'BODY',d2
		bne.s		nAck
	;=========case ID_BODY: (assume this is the last chunk in the ILBM)
	; Here we print out all of the info we collected in the ILBMFrame.
	;---Print out info in BMHD
		Bclr.b	#BMHDFLAG,iFlags(a3)
		beq		CLER       ;first frame must have a BMHD
		lea		iBMHD(a3),a2
		moveq		#0,d1
		moveq		#0,d0
		move.w	BMHD_pageH(a2),d1
		move.l	d1,-(sp)
		;---d2 = pageHeight or h, whichever is larger
		move.w	BMHD_h(a2),d0
		move.l	d0,-(sp)
		cmp.w		d0,d1
		bcc.s		larh
		move.w	d0,d1
larh	move.w	d1,d2
		moveq		#0,d0
		move.b	BMHD_nPlanes(a2),d0
		move.l	d0,-(sp)
		mulu.w	d0,d2      ;planeS = nPlanes * pageHeight
		move.w	BMHD_pageW(a2),d1
		move.l	d1,-(sp)
		move.w	(a2),d0    ;w
		move.l	d0,-(sp)
		;---d0 = pageWidth or w, whichever is larger
		cmp.w		d0,d1
		bcc.s		larw
		move.w	d0,d1
		;---RasterSize = planeS * RowBytes(pageWidth)
larw	moveq		#15,d0
		add.w		d1,d0
		lsr.w		#3,d0
		Bclr.l	#0,d0
		move.l	d2,d1
		jsr		multiply
		move.l	d0,-(sp)
		lea		BMHDinfo,a1
		lea		_BUFFER,a0
		jsr		asprintf
		lea		24(sp),sp
		bsr		print_line
	;---Print out more BMHD info
		moveq		#0,d0
		move.b	BMHD_yAspect(a2),d0
		move.l	d0,-(sp)
		move.b	BMHD_xAspect(a2),d0
		move.l	d0,-(sp)
		move.b	BMHD_compress(a2),d0
		move.l	d0,-(sp)
		move.b	BMHD_masking(a2),d0
		move.l	d0,-(sp)
		move.w	BMHD_color(a2),d0
		move.l	d0,-(sp)
		move.w	BMHD_y(a2),d0
		move.l	d0,-(sp)
		move.w	BMHD_x(a2),d0
		move.l	d0,-(sp)
		lea		BMHDinfo2,a1
		lea		_BUFFER,a0
		jsr		asprintf
		lea		28(sp),sp
		bsr		print_line
	;---Print CAMG viewmodes, or "None"
pCamg	lea		None,a0
		lea		ViewModePrint,a1
		Btst.b	#CAMGFLAG,iFlags(a3)
		beq.s		Ncamg
		lea		INTERLACE,a0
		move.l	iViewModes(a3),d1
		btst.l	#2,d1
		bne.s		Ncamg
		lea		HAM,a0
		btst.l	#7,d1
		bne.s		Ncamg
		lea		HIRES,a0
		btst.l	#15,d0
		bne.s		Ncamg
		lea		DUAL,a0
		btst.l	#10,d0
		bne.s		Ncamg
		lea		LORES,a0
Ncamg	move.l	a0,-(sp)
		lea		_BUFFER,a0
		jsr		asprintf
		addq.l	#4,sp
		bsr		print_line
	;---Print number of colors in table
		moveq		#0,d0
		move.b	iNumColors(a3),d0
		move.l	d0,-(sp)
		lea		NCPrint,a1
		lea		_BUFFER,a0
		jsr		asprintf
		addq.l	#4,sp
		bsr		print_line
	;---If an ANHD, print out the opmode
		Bclr.b	#ANHDFLAG,iFlags(a3)
		beq.s		nopm
		moveq		#0,d0
		move.b	ANHDchunk,d0
		move.l	d0,-(sp)
		lea		OpMode,a1
		lea		_BUFFER,a0
		jsr		asprintf
		addq.l	#4,sp
		bsr		print_line
	;---IFFP = IFF_OKAY (to continue the load) if an ANIM. If an ILBM outside
	;   of an ANIM (by itself), then return IFF_DONE.
nopm	moveq		#IFF_OKAY,d0
		Btst.b	#ANIMFLAG,iUserFlags(a3)
		bne.s		L321
		moveq		#IFF_DONE,d0
		bra.s		L321
CLER	moveq		#BAD_FORM,d0
		bra.s		L321
	;===============case ID_BMHD:
   ;---Set BMHDFLAG, and read chunk
Bmhdh	Bset.b	#BMHDFLAG,iFlags(a3)
		moveq		#sizeofBMHD,d0
		lea		iBMHD(a3),a1
readChunk:
		movea.l	a5,a0
		jsr		_LVOIFFReadBytes(a6)
IFfp	move.l	d0,d2
	;---while IFFP >= IFF_OKAY, (loop if valid ID of ignored chunk, or a
	;   subroutine returned IFF_OKAY (no errors))
L334	move.l	d2,d0
		bpl		nAck
L321	movem.l	(sp)+,d2/a2/a5/a6
		rts
	;=============case ID_ANHD:
	;---store data in global ANHD, and set ANHDflag
Anhdh	Bset.b	#ANHDFLAG,iUserFlags
	;---Read in ANHD chunk
		lea		ANHDchunk,a1
		moveq		#sizeofANHD,d0
		bra.s		readChunk
 ;=============case ID_CAMG:
Camgh	jsr		_LVOHandleCAMG(a6)
		bra.s		readChunk
 ;=================case ID_CMAP:
Cmaph	lea		iNumColors(a3),a1
		moveq		#maxColorReg,d0
		move.b	d0,(a1)
		move.l	a5,d0
		lea		iColorTable(a3),a0
		;NumColors address in a1
		jsr		_LVOGetCMAP(a6)
		bra		IFfp

	;SECTION IFFdata,DATA	;some assemblers may need this un-commented

	XDEF Vectors	;the initialized Vectors structure with custom FORMhandler
Vectors:
	dc.l	0
	dc.l	ExamineFORM
	dc.l	0
	dc.l	0

	XDEF	NumOfFrames
NumOfFrames dc.l 0

	XDEF	yPos
yPos dc.w 0

	XDEF	ANHDchunk
ANHDchunk ds.b 40

	XDEF	ILBMFrame
ILBMFrame ds.b sizeofILBMFrame

	XDEF	newWindow
newWindow:
	dc.w   0,0
	dc.w   640,200
	dc.b   0,1
	;IDCMP = MOUSEBUTTONS|CLOSEWINDOW
	dc.l   $208
;WindowFlags = WINDOWSIZE|WINDOWDRAG|WINDOWDEPTH|SMART_REFRESH|ACTIVATE
	dc.l   $100F
	dc.l   0
	dc.l   0
	dc.l   WINTITLE
	dc.l   0
	dc.l   0
	dc.w   306,145
	dc.w   640,200
	dc.w   1

TextAttr:			;Topaz 8 is a ROM font so doesn't need to be opened
	dc.l	FONTNAME
	dc.w	8			;TOPAZ_EIGHTY
	dc.b	0,0

	XDEF	_GfxBase,_IntuitionBase,_RequesterBase,WindowPtr,RastPort,_ILBMBase
	XDEF	FileIO,RequesterName,ILBMName
_GfxBase			dc.l  0
_IntuitionBase	dc.l  0
_RequesterBase	dc.l  0
_ILBMBase		dc.l  0
WindowPtr		dc.l  0
RastPort			dc.l  0
FileIO			dc.l  0
Spaces			dc.b  '                                     ',0
FONTNAME			dc.b  'topaz.font',0

IOerR				dc.b  'Cannot get a FileIO structure.',0
GfxName			dc.b  'graphics.library',0
IntuitionName	dc.b  'intuition.library',0
CantFindFileIO	dc.b  'Cannot find the '
RequesterName	dc.b	'requester.library',0
CantFindIlbm	dc.b  'Cannot find the '
ILBMName			dc.b	'ilbm.library',0

WINTITLE			dc.b  'ANIMInfo ® 1989  dissidents',0
Quit				dc.b  1
FramePrint		dc.b  'Number of Frames = %-11lu',0
ItsILBM			dc.b  'This is an ILBM file.          ',0
BMHDinfo			dc.b  'Raster=%-7lu  w=%-4lu  pageW=%-4lu  Planes=%-2lu  h=%-4lu'
					dc.b  '  pageH=%-4lu',0
BMHDinfo2		dc.b  'XY=(%-5lu,%-5lu)  TransColor=%-5lu  Masking=%1lu  '
					dc.b  'Compression=%1lu   Aspect=%2lu/%-2lu',0
ViewModePrint	dc.b  'ViewModes=%-16s',0
DUAL				dc.b  'Dual Playfield',0
HAM				dc.b  'Ham',0
INTERLACE		dc.b  'InterLace',0
HIRES				dc.b  'Hi-Res',0
LORES				dc.b  'Lo-Res',0
NCPrint			dc.b  'Number of Colors = %-4lu',0
None				dc.b  'Not Specified',0
OpMode			dc.b  'ANHD opmode = %-3lu',0
