******************************************************************************
*                                                                            *
*  uShow.asm - The Mantis Really-Really-Small-Micro Show command (ver 1.1)   *
*                                                                            *
*  Programmed by Darrin Massena, Mantis Development.                         *
*  No Rights Reserved - Hey everybody, it's FREE!                            *
*                                                                            *
*  To make uShow using the Aztec 'C' assembler:                              *
*    1) as uShow.asm                                                         *
*    2) ln -o uShow uShow.o -lc32                                            *
*                                                                            *
*  To make uShow using the MetaCompost assembler:                            *
*    1) Rewrite first few lines to get a suitable index into the data hunk.  *
*    2) Fix other odd incompatibilities.                                     *
*    3) Wait forever for assembling.                                         *
*    4) Wait forever to linking.                                             *
*    5) Give up and go buy Aztec 'C'.                                        *
*    6) Use instructions above.                                              *
*                                                                            *
*  WARNING!  This code has been HIGHLY optimized for size.  Beware of code   *
*  that seems unnecessary or incorrect, as it is probably part of a nasty    *
*  hack to save a few bytes somewhere.  Be especially delicate when altering *
*  register usage.  Do not change the contents of ANY register without first *
*  examining the repercussions of the change on the rest of the program.     *
*  Tread lightly around the global vars and structures, almost all of them   *
*  have more than one use.                                                   *
*                                                                            *
*  Revision history :                                                        *
*  ------------------                                                        *
*  04/25/87 (DWM)  Started writing uShow.                                    *
*  04/26/87 (DWM)  Completed writing uShow.                                  *
*  04/27/87 (DWM)  Fixed a couple of bugs.                                   *
*  05/01/87 (DWM)  Fixed masked images bug.                                  *
*                                                                            *
******************************************************************************

			include	"exec/types.i"
			include	"intuition/intuition.i"
			include	"libraries/dosextens.i"
			include	"libraries/dos.i"

call		MACRO						;macro to call system routines
			jsr	_LVO\1(a6)
			ENDM

* ===========================================================================
* IFF BitMap header structure (BMHD)
	STRUCTURE BitMapHeader,0
		UWORD bmhd_w
		UWORD bmhd_h
		WORD	bmhd_x
		WORD	bmhd_y
		UBYTE	bmhd_nPlanes
		UBYTE	bmhd_masking
		UBYTE	bmhd_compression
		UBYTE	bmhd_pad1
		UWORD	bmhd_transparentColor
		UBYTE	bmhd_xAspect
		UBYTE	bmhd_yAspect
		WORD	bmhd_pageWidth
		WORD	bmhd_pageHeight
	LABEL	bmhd_SIZEOF

* ===========================================================================
			DSEG
SysBase	equ		4

bmhd		equ		-bmhd_SIZEOF
cmap		equ		bmhd-(32*2)

* ===========================================================================
			CSEG
* Define these as public and they'll be pulled from C32.lib.
			public	_LVOOpenLibrary,_LVOCloseLibrary,_LVOAllocMem,_LVOFreeMem
			public	_LVOOpenWindow,_LVOCloseWindow,_LVOOpenScreen,_LVOCloseScreen
			public	_LVOOpen,_LVORead,_LVOWrite,_LVOSeek,_LVOClose,_LVOLoadRGB4
			public	_LVOWait

* ===========================================================================
			public	uShow
uShow
*			movea.l	#dummyVar+32766,a4	;special stuff to get my relative A4
			dc.w		%0010100001111100
			dc.l		dummyVar+32766

			link		a5,#cmap					;grab space on stack for cmap/bmhd
			move.l	a0,a2						;save copy
			subq.w	#1,d0						;dec to drop \n
			move.w	d0,d2						;save copy
			beq		Quit9						;no args, quit

* Initialize all necessary structures, open necessary libraries, etc.
* If any initializations fail, we'll just abort
			move.l	SysBase,a6
			lea.l		szGfx,a1
			moveq		#0,d0
			call		OpenLibrary
			move.l	d0,GfxBase

			lea.l		szDos,a1
			moveq		#0,d0
			call		OpenLibrary				;open dos.library
			move.l	d0,DosBase

			lea.l		szIntuition,a1
			moveq		#0,d0
			call		OpenLibrary				;open intuition.library
			move.l	d0,IBase

* The Manx Shell seems to add a space to the end of the cli args somehow...
			move.b	-1(a2,d2.w),d0			;get char before \n
			cmp.b		#' ',d0					;is it a space?
			bne		1$							; no, clear \n
			subq.w	#1,d2						; yes, clear it
1$
			clr.b		(a2,d2.w)				;null terminate filename
			move.l	a2,d1						;d1 = szFileName
			move.l	#MODE_OLDFILE,d2		;d2 = access mode
			move.l	DosBase,a6
			call		Open						;open picture file
			tst.l		d0							;did it open?
			beq		Quit						; no, forget about error msgs for now
			move.l	d0,pfhPic				;save ptr to file handle

			lea.l		chunkBuff,a0			;a0 = ptr to read buffer
			moveq		#12,d3					;d3 = # of bytes to read from file
			jsr		Read						;read 'em in

			cmp.l		#'FORM',chunkType		;is it an IFF FORM?
			bne		Quit						; no, quit
			cmp.l		#'ILBM',chunkSubType	;is it an ILBM?
			bne		Quit						; no, quit

ReadILBM											;read in the ILBM
			lea.l		chunkBuff,a0
			moveq		#8,d3
			jsr		Read						;read in a chunk (type/len pair)

CkBMHD
			move.l	chunkType,d0			; yes, get type
			cmp.l		#'BMHD',d0				;is it a BitMap header?
			bne		CkCMAP					; no
			lea.l		bmhd(a5),a0				;a0 = ptr to read buffer
			moveq		#bmhd_SIZEOF,d3		;# of bytes to read
			jsr		Read
			bra		ReadILBM					;get next piece of data
CkCMAP
			cmp.l		#'CMAP',d0				;is it a color map?
			bne		CkCAMG					; no
			move.l	chunkLen,d4				;# of colors to read * 3
			divu		#3,d4						;divide by 3 to get color count
			move.w	d4,ccoMap				;save count of colors in map
			subq		#1,d4
			lea.l		cmap(a5),a3				;a3 = ptr to cmap buffer
			moveq		#3,d3						;# of bytes to read
1$
			lea.l		chunkLen+1,a0
			jsr		Read
			move.w	chunkLen,d1
			lsl.w		#4,d1
			or.b		chunkLen+2,d1
			lsl.w		#4,d1
			or.b		chunkLen+3,d1
			lsr.w		#4,d1
			move.w	d1,(a3)+
			dbra		d4,1$

			addq.b	#1,fGotCMAP				;set found CMAP flag
			bra		ReadILBM					;get next piece of data

CkCAMG
			cmp.l		#'CAMG',d0				;how about special Amiga ViewModes?
			bne		CkBODY					; no, check for body
			lea.l		chunkSubType,a0		;a0 = ptr to camg buffer
			moveq		#4,d3						;# of bytes to read
			jsr		Read
			move.w	chunkSubType+2,ns_ViewModes+nscrPic
			bra		ReadILBM					;get next piece of data

CkBODY
			cmp.l		#'BODY',d0				;is it the ILBM body?
			beq		Continue					; yes, try to do something with it
TossIt
			move.l	pfhPic,d1				;throw unusable data away by
			move.l	chunkLen,d2				; simply seeking past it.
			moveq		#OFFSET_CURRENT,d3
			move.l	DosBase,a6
			call		Seek
			bra		ReadILBM

* If we've gotten here, we have a BMHD and we're prepared to read the BODY
Continue
			move.l	chunkLen,d7				;save length of body
			lea.l		bmhd(a5),a3				;use values from BMHD to initialize
			lea.l		nscrPic,a0				; our new screen structure
			move.w	bmhd_w(a3),ns_Width(a0)
			move.w	bmhd_h(a3),ns_Height(a0)
			move.b	bmhd_nPlanes(a3),ns_Depth+1(a0)

			cmp.w		#500,bmhd_w(a3)
			ble		11$
			or.w		#V_HIRES,ns_ViewModes(a0)
11$
			cmp.w		#300,bmhd_h(a3)
			ble		12$
			or.w		#V_LACE,ns_ViewModes(a0)
12$
			move.b	bmhd_compression(a3),d3
			cmp.b		#2,d3						;do I know this kind of compression?
			bge		Quit						; no, give up

* Open screen to display the picture on.
			move.l	IBase,a6
			call		OpenScreen
			tst.l		d0
			beq		Quit						;error while opening, abort
			move.l	d0,pscrPic				;save pointer to my picture screen

* Open a backdrop window so we can use its message port for communication.
			lea.l		nwinPic,a0
			move.l	d0,nw_Screen(a0)		;point new window to this screen
			call		OpenWindow
			tst.l		d0							;everything opened ok?
			beq		Quit						; no, quit
			move.l	d0,pwinPic				; yes, save window pointer

			tst.b		fGotCMAP					;did we get a colormap?
			beq		1$							; no
			move.l	pscrPic,a0				; yes, let's jam those colors in ther
			lea.l		sc_ViewPort(a0),a0
			lea.l		cmap(a5),a1
			move.w	ccoMap,d0
			move.l	GfxBase,a6
			call		LoadRGB4
1$
			move.l	d7,d0
			moveq		#0,d1
			move.l	SysBase,a6
			call		AllocMem
			tst.l		d0
			beq		Quit						;couldn't get buffer memory
			move.l	d0,prgbPicBuff			;save pointer to picture buffer
			move.l	d0,a0
			move.l	d7,d3
			jsr		Read						;read the rest of the body into buffer

Decomp
			move.l	pscrPic,a2
			lea.l		sc_BitMap+bm_Planes(a2),a6	;a6 = ptr to screen's 1st plane

			cmp.b		#1,bmhd_masking(a3)	;does this image have a mask?
			bne		10$						; no
			moveq		#0,d0						; yes
			move.b	bmhd_nPlanes(a3),d0	;get planes count
			lsl.w		#2,d0						;convert to planeptr array index
			move.l	#$FE0000,(a6,d0.w)	;set mask planeptr = ROMs (hehheh)
			addq.b	#1,bmhd_nPlanes(a3)	;increment planes count
10$

			lea.l		sc_BitMap+bm_BytesPerRow(a2),a2
			move.w	(a2),d6					;d6 = bytes per row
			move.l	prgbPicBuff,a0			;a0 = ptr to body data buffer
			move.w	bmhd_h(a3),d4			;d4 = # of rows in image
			subq.w	#1,d4
			moveq		#0,d3						;d3 = offset within plane
1$
			moveq		#0,d5
			move.b	bmhd_nPlanes(a3),d5	;d5 = # of planes in image
			move.l	a6,a2						;reset plane array pointer
2$
			dbra		d5,3$						;loop through each plane
			add.w		d6,d3						;move offset down one line
			dbra		d4,1$						;loop through all lines
			bra		ShowDone
3$
			move.l	(a2)+,a1
			add.w		d3,a1
35$
			move.w	d6,d2						;d2 = bytes per row
			tst.b		bmhd_compression(a3)	;data compressed?
			bne		50$						; yes
			subq		#1,d2						; no, setup copy loop
4$
			move.b	(a0)+,(a1)+				;move each byte
			dbra		d2,4$						;loop for entire row
			bra		2$							;this row done, next?
50$
			tst.w		d2							;is this line done?
			beq		2$							; yes, setup for next
			moveq		#0,d1
51$
			move.b	(a0)+,d1					;get token from source
			bmi		53$						; handle repeat-run

			sub.w		d1,d2						;sub from bytes per row
			subq.w	#1,d2						; and one more
52$
			move.b	(a0)+,(a1)+
			dbra		d1,52$
			bra		50$
53$
			cmp.b		#128,d1					;NULL? Is anyone that stupid?
			beq		50$						; yes, someone is...
			neg.b		d1
			sub.w		d1,d2						;sub from bytes per row
			subq.w	#1,d2						; and one more
			move.b	(a0)+,d0
54$
			move.b	d0,(a1)+
			dbra		d1,54$
			bra		50$

ShowDone
			move.l	d7,d0
			move.l	prgbPicBuff,a1
			move.l	SysBase,a6
			call		FreeMem					;free our load buffer

			move.l	pwinPic,a0
			move.l	wd_UserPort(a0),a0
			moveq		#0,d1
			move.b	MP_SIGBIT(a0),d1
			moveq		#1,d0
			lsl.l		d1,d0
			call		Wait
			
* It's time to quit, close everything and say good-night.
Quit
			move.l	IBase,a6					;get intuition base
			move.l	pwinPic,d0				;is our window open?
			beq		1$							; no
			move.l	d0,a0						; yes, close it
			call		CloseWindow
1$
			move.l	pscrPic,d0				;is our screen open?
			beq		2$							; no
			move.l	d0,a0						; yes, close it
			call		CloseScreen
2$
			move.l	pfhPic,d1				;is the pic file still open?
			beq		3$							; no, it's closed
			move.l	DosBase,a6
			call		Close						;close that puppy
3$
			move.l	GfxBase,a1				;close the graphics.library
			move.l	SysBase,a6
			call		CloseLibrary

			move.l	IBase,a1					;close the intuition.library
			call		CloseLibrary

			move.l	DosBase,a1				;close the dos.library
			call		CloseLibrary
Quit9
			unlk		a5
			rts

* ===========================================================================
* d0.l: len = Read(a0: prgbBuff, d3.l: len) 
Read
			move.l	pfhPic,d1				;a nasty assumption, but saves space
			move.l	a0,d2						;move buff ptr to d2
			move.l	DosBase,a6
			call		Read						;read the data in
			cmp.l		d0,d3						;did we get it all
			bne		Quit						; no, quit
			rts									; yes, just return

* ===========================================================================
				DSEG
* These vars are derived using the Mantis naming conventions.  A brief summary
* follows:
*
* p - indicates a pointer
* n - 'new' structure
* win,scr,fh - abbreviations for window, screen and filehandle structures
* co - color 0x0RGB data type
* sz - null terminated string
* rg - range of values (array)
* b,w,l - byte, word, long data types
*
* Quiz: What does prgpfhOpen stand for?
* .selif nepO fo sretnioP eldnaHeliF fo eGnaR a ot retnioP a :resnA

dummyVar									;dummy, used to create my A4
* The following group of vars was created by a trained professional.
*                     DO NOT try this at home.

szMe			dc.b	"   ",181
				dc.b	"Show ",169
				dc.b	" 1987 Darrin Massena"

				even
nscrPic
				dc.w	0,0,640,400,2
				dc.b	0,1
				dc.w	0					;ViewModes
				dc.w	CUSTOMSCREEN
pscrPic
				dc.l	0,szMe			;WARNING! nwinPic structure MUST follow
nwinPic
				dc.w	0,0,24,10
				dc.b	0,1
				dc.l	CLOSEWINDOW|RAWKEY|MENUPICK
				dc.l	SIMPLE_REFRESH|BORDERLESS|ACTIVATE|WINDOWCLOSE
pwinPic
				dc.l	0,0,0,0,0
pfhPic		dc.l	0					;ptr to picture file handle
				dc.l	0
				dc.w	CUSTOMSCREEN

ccoMap
szDos			dc.b	"dos.library",0
				even
chunkBuff
szIntuition
chunkType	dc.l	'intu'						;IFF chunk info read here
chunkLen		dc.l	'itio'
chunkSubType dc.l	'n.li'
prgbPicBuff	dc.l	'brar'
fGotCMAP		dc.b	'y',0
szGfx
GfxBase		dc.l	'grap'
IBase			dc.l	'hics'
DosBase		dc.l	'.lib'
				dc.b	"rary",0

* ===========================================================================
				END

