******************************************************************************
*                                                                            *
*  uShow.asm - The Mantis Really-Very-Tiny-Small-Micro Show command          *
*	version 2.0							     *
*                                                                            *
*  Programmed by Darrin Massena                                              *
*  Copyright (C) 1987  Darrin Massena, Mantis Development.                   *
*  All Rights Reserved.                                                      *
*                                                                            *
*  Modified by Andry Rachmat for version 2.0				     *
*									     *
*  Addtional modifications by Randy Jouett (5/31/89).			     *
*									     *
*  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.                                                   *
*									     *
*  Assembled with Manx C compiler:					     *
*	as ushow.asm							     *
*	ln ushow.o -lc							     *
*                                                                            *
*  Revision history :                                                        *
*  ------------------                                                        *
*  04/25/87 (DWM)  Created this program.                                     *
*  04/26/87 (DWM)  Finished this program.                                    *
*  04/27/87 (DWM)  Fixed last bugs in this program.                          *
*  05/01/87 (DWM)  Fixed masked images bug.                                  *
*  12/18/87 (AR)   Fixed Brushes resolution, made a bit smaller.             *
*  05/31/89 (RGJ)  Fixed addtional bugs, made a bit smaller.		     *
*									     *
******************************************************************************

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

	include	"asm.i"				;kitchen sink pre-include.

;	ADDSYM


; XLVO & SYS are both included in "macros.i"

	XLVO	OpenLibrary
	XLVO	CloseLibrary
	XLVO	AllocMem
	XLVO	FreeMem
	XLVO	OpenWindow
	XLVO	CloseWindow
	XLVO	OpenScreen
	XLVO	CloseScreen
	XLVO	Open
	XLVO	Close
	XLVO	Read
	XLVO	Seek
	XLVO	LoadRGB4
	XLVO	WaitPort

	XREF	_LinkerDB

* ===========================================================================

* 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

bmhd	equ	-bmhd_SIZEOF
cmap	equ	bmhd-700

* ===========================================================================

MicroShow:

	link	a5,#cmap		;grab space on stack for cmap/bmhd
	lea	_LinkerDB,a4		;base register for data.

	subq	#1,d0
	beq	nodos			;no args, just quit
	move.l	a0,a2			;save copy to a2 for open file
	clr.b	0(a0,d0.w)		;clear \n

* Initialize all necessary structures, open necessary libraries, etc.
* If any initializations fail, we'll just abort

	lea	dosname(a4),a1
	moveq	#0,d0
	SYS	OpenLibrary,4		;open dos.library
	move.l	d0,DBase(a4)
	beq	nodos

	lea	intuiname(a4),a1
	moveq	#0,d0
	SYS	OpenLibrary		;open intuition.library
	move.l	d0,IBase(a4)
	beq	nointui

	move.l	d0,a1
	move.l	100(a1),GBase(a4)	;he he he, don't need to open Gfx library afterall

	move.l	a2,d1			;d1 = szFileName
	move.l	#MODE_OLDFILE,d2	;d2 = access mode
	SYS	Open,DBase(a4)		;open picture file
	move.l	d0,pfhPic(a4)		;save ptr to file handle
	beq	nopfh			;no, forget about error msgs for now
1$
	lea	chunkBuff(a4),a0	;a0 = ptr to read buffer
	moveq	#12,d3			;d3 = # of bytes to read from file
	bsr	Read			;read 'em in
	bne	noread

	cmp.l	#'FORM',chunkType(a4)	;is it an IFF FORM?
	bne	noread			 ; no, quit
	cmp.l	#'ILBM',chunkSubType(a4) ;is it an ILBM?
	beq.s	ReadILBM		 ;yes. Read the file.
	cmp.l	#'ANIM',chunkSubType(a4) ;is it an ANIM?
	bne	noread			 ;nope. Thanks for the idea, J.V!
	bra.s	1$

ReadILBM:
	lea	chunkBuff(a4),a0
	moveq	#8,d3
	bsr	Read			;read in a chunk (type/len pair)
	bne	noread

CkBMHD:
	move.l	chunkType(a4),d0	; yes, get type
	cmp.l	#'BMHD',d0		;is it a BitMap header?
	bne.s	CkCMAP			; no
	lea	bmhd(a5),a0		;a0 = ptr to read buffer
	move.l	#bmhd_SIZEOF,d3		;# of bytes to read
	bsr	Read
	bne	noread
	bra.s	ReadILBM		;get next piece of data

CkCMAP:
	cmp.l	#'CMAP',d0		;is it a color map?
	bne.s	CkCAMG			; no
	move.l	chunkLen(a4),d4		;# of colors to read * 3
	move.l	d4,d3			;# of data to read
	lea	ctable,a0		; color table
	bsr	Read
	bne	noread

	divu	#3,d4			;divide by 3 to get color count
	move.w	d4,ccoMap(a4)		;save count of colors in map
	subq	#1,d4
	lea	cmap(a5),a3		;a3 = ptr to cmap buffer
	lea	ctable,a0		;a0 = color table
1$
	move.b	(a0)+,d1
	lsl.w	#4,d1
	or.b	(a0)+,d1
	lsl.w	#4,d1
	or.b	(a0)+,d1
	lsr.w	#4,d1
	move.w	d1,(a3)+
	dbra	d4,1$

	move.b	#1,CMAPflag+1(a4)	;set found CMAP flag
	bra.s	ReadILBM		;get next piece of data

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

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

* If we've gotten here, we have a BMHD and we're prepared to read the BODY

Continue:
	move.l	chunkLen(a4),d7		;save length of body
	move.l	d7,d0
	move.l	#MEMF_PUBLIC,d1
	SYS	AllocMem,4
	move.l	d0,prgbPicBuff(a4)	;save pointer to picture buffer
	beq	nomem			;couldn't get buffer memory
	move.l	d0,a0
	move.l	d7,d3
	bsr	Read			;read the rest of the body into buffer
	bne	noscr

* Set up the screen

	lea	bmhd(a5),a3		;use values from BMHD to initialize
	lea	nscrPic(a4),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.b	#2,bmhd_compression(a3) ;do I know this kind of compression?
	bge	noscr			; no, give up

* Open screen to display the picture on.

	SYS	OpenScreen,IBase(a4)
	move.l	d0,pscrPic(a4)		;save pointer to my picture screen
	beq	noscr			;error while opening

* Open a backdrop window so we can use its message port for communication.

	lea	nwinPic(a4),a0
	move.l	d0,nw_Screen(a0)	;point new window to this screen
	SYS	OpenWindow
	move.l	d0,pwinPic(a4)		; save window pointer
	beq	nowin			; no window

	tst.b	CMAPflag+1(a4)		;did we get a colormap?
	beq.s	Decomp			; no
	move.l	pscrPic(a4),a0		; yes, let's jam those colors in ther
	lea	sc_ViewPort(a0),a0
	lea	cmap(a5),a1
	moveq	#0,d0
	move.w	ccoMap(a4),d0
	SYS	LoadRGB4,GBase(a4)

Decomp:
	move.l	pscrPic(a4),a2
	lea	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.s	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,0(a6,d0.w)	;set mask planeptr = ROMs (hehheh)
	addq.b	#1,bmhd_nPlanes(a3)	;increment planes count
10$
	lea	sc_BitMap+bm_BytesPerRow(a2),a2
	move.w	(a2),d6			;d6 = bytes per row
	move.l	prgbPicBuff(a4),a0	;a0 = ptr to body data buffer
	moveq	#0,d4
	move.w	bmhd_h(a3),d4		;d4 = # of rows in image
	subq.w	#1,d4
	moveq	#0,d2
	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.s	ShowDone
3$
	move.l	(a2)+,a1		;current plane in a1
	add.w	d3,a1			;add current offset
35$
	move.w	d6,d2			;d2 = bytes per row
	tst.b	bmhd_compression(a3)	;data compressed?
	bne.s	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.s	2$			;this row done, next?
50$
	tst.w	d2			;is this line done?
	beq.s	2$			; yes, setup for next
	moveq	#0,d1
51$
	move.b	(a0)+,d1		;get token from source
	bmi.s	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.s	50$
53$
	cmp.b	#128,d1			;NULL? Is anyone that stupid?
	beq.s	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.s	50$

ShowDone:

	move.l	pwinPic(a4),a0
	move.l	wd_UserPort(a0),a0
	SYS	WaitPort,4

* ============= Quit ====================================================== *

Quit:
	move.l	pwinPic(a4),a0		;is our window open?
	SYS	CloseWindow,IBase(a4)
nowin:
	move.l	pscrPic(a4),a0		;is our screen open?
	SYS	CloseScreen
noscr:
	move.l	chunkLen(a4),d0		;save length of body
	move.l	prgbPicBuff(a4),a1
	SYS	FreeMem,4		;free our load buffer
nomem:
noread:
	move.l	pfhPic(a4),d1		;is the pic file still open?
	SYS	Close,DBase(a4)		;close that puppy
nopfh:
	move.l	IBase(a4),a1		;close the intuition.library
	SYS	CloseLibrary,4
nointui:
	move.l	DBase(a4),a1		;close the dos.library
	SYS	CloseLibrary
nodos:
	unlk	a5

	rts

* ===========================================================================
* d0.l: len = Read(a0: prgbBuff, d3.l: len) 

Read:
	move.l	pfhPic(a4),d1		;a nasty assumption, but saves space
	move.l	a0,d2			;move buff ptr to d2
	SYS	Read,DBase(a4)		;read the data in
	cmp.l	d0,d3			;did we get it all

	rts				; yes, just return

* ===========================================================================

	section	__MERGED,data

dummyVar:				;dummy, used to create my A4

* The following group of vars was created by a trained professional.
*               DO NOT try this at home.

nscrPic:
	dc.w	0,0,640,400,2
	dc.b	0,1
	dc.w	0		;ViewModes
	dc.w	CUSTOMSCREEN!SCREENQUIET
pscrPic:
	dc.l	0,0		;WARNING! nwinPic structure MUST follow
nwinPic:
	dc.w	0,0,24,10
	dc.b	0,1
	dc.l	CLOSEWINDOW	; for no keys input to quit, delete the RAWKEY
	dc.l	SIMPLE_REFRESH!BORDERLESS!ACTIVATE!WINDOWCLOSE!RMBTRAP
pwinPic:
	dc.l	0,0,0,0,0
pfhPic:
	dc.l	0		;ptr to picture file handle
	dc.l	0
	dc.w	CUSTOMSCREEN

prgbPicBuff:
	dc.l	0
dosname:
DBase:
	dc.b	'dos.'
IBase:
	dc.b	'libr'
GBase:
	dc.b	'ary',0

chunkBuff:
chunkType:
intuiname:
	dc.b	'intu'		;IFF chunk info read here
chunkLen:
	dc.b	'itio'
chunkSubType:
	dc.b	'n.li'
ccoMap:
	dc.b	'brar'
CMAPflag:
	dc.b	'y',0

	BSS
ctable:
	ds.b	512

	END
