******************************************************************************
*                                                                            *
*  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				     *
*									     *
*  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              *
*                                                                            *
******************************************************************************

	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
	public	_LVOOpenLibrary,_LVOCloseLibrary,_LVOAllocMem,_LVOFreeMem
	public	_LVOOpenWindow,_LVOCloseWindow,_LVOOpenScreen,_LVOCloseScreen
	public	_LVOOpen,_LVORead,_LVOWrite,_LVOSeek,_LVOClose,_LVOLoadRGB4
	public	_LVOWait

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

* ===========================================================================
	public	MainEntry
MainEntry
	link	a5,#cmap		;grab space on stack for cmap/bmhd
	move.l	a0,a2			;save copy to a2 for open file
	clr.b	-1(a0,d0.w)		;clear \n
	tst.b	(a0)			;test for args
	beq	Quit9			;no args, just quit

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

	move.l	SysBase,a6
	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
	move.l	d0,a1
	move.l	100(a1),GfxBase		;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
	move.l	DosBase,a6
	call	Open			;open picture file
	move.l	d0,pfhPic		;save ptr to file handle
	beq	Quit			;no, forget about error msgs for now

	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
	public	CkCMAP
CkCMAP
	cmp.l	#'CMAP',d0		;is it a color map?
	bne	CkBODY			; no
	move.l	chunkLen,d4		;# of colors to read * 3
	move.l	d4,d3			;# of data to read
	lea.l	ctable,a0		; color table
	jsr	Read

	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
	lea.l	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$

	addq.b	#1,fGotCMAP		;set found CMAP flag
	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
	public	Continue
Continue
	move.l	chunkLen,d7		;save length of body

* Read the rest of the data into buffer
	move.l	d7,d0
	moveq	#0,d1
	move.l	SysBase,a6
	call	AllocMem
	move.l	d0,prgbPicBuff		;save pointer to picture buffer
	beq	Quit			;couldn't get buffer memory
	move.l	d0,a0
	move.l	d7,d3
	jsr	Read			;read the rest of the body into buffer

* Set up the screen
	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.b	#6,bmhd_nPlanes(a3)	; 6 planes: assume it is HAM
	bne	10$
	or.w	#V_HAM,ns_ViewModes(a0)
10$
	cmp.w	#320,bmhd_pageWidth(a3)
	ble	11$
	or.w	#V_HIRES,ns_ViewModes(a0)
11$
	cmp.w	#200,bmhd_pageHeight(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
	move.l	d0,pscrPic		;save pointer to my picture screen
	beq	Quit			;error while opening

* 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
	move.l	d0,pwinPic		; save window pointer
	beq	Quit			; no window

	tst.l	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$

	public	Decomp
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$

	public	ShowDone
ShowDone
	jsr	FreeBuffer

	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.
	public	Quit
Quit
	jsr	FreeBuffer

	move.l	IBase,a6		;get intuition base
	move.l	pwinPic,d0		;is our window open?
	beq	2$			; no
	move.l	d0,a0
	call	CloseWindow
2$
	move.l	pscrPic,d0		;is our screen open?
	beq	3$			; no
	move.l	d0,a0
	call	CloseScreen
3$
	move.l	pfhPic,d1		;is the pic file still open?
	beq	4$			; no, it's closed
	move.l	DosBase,a6
	call	Close			;close that puppy
4$

	move.l	SysBase,a6
	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) 
	public	Read
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

	public	FreeBuffer
FreeBuffer
	tst.l	prgbPicBuff
	beq	1$
	move.l	d7,d0
	move.l	prgbPicBuff,a1
	move.l	SysBase,a6
	call	FreeMem			;free our load buffer
	clr.l	prgbPicBuff
1$
	rts


* ===========================================================================
		DSEG
		public	dummyVar,pfhPic,chunkType,chunkLen,chunkSubType
		public	pscrPic,pwinPic,prgbPicBuff

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	0
		even
nscrPic
		dc.w	0,0,640,400,2
		dc.b	0,1
		dc.w	0		;ViewModes
		dc.w	CUSTOMSCREEN|SCREENQUIET
pscrPic
		dc.l	0,szMe		;WARNING! nwinPic structure MUST follow

		public	nwinPic
nwinPic
		dc.w	0,0,24,10
		dc.b	0,1
		dc.l	CLOSEWINDOW|RAWKEY	; 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
		even
szDos
DosBase		dc.l	'dos.'
IBase		dc.l	'libr'
GfxBase		dc.l	'ary',0
		even
chunkBuff
szIntuition
chunkType	dc.l	'intu'		;IFF chunk info read here
chunkLen	dc.l	'itio'
chunkSubType 	dc.l	'n.li'
		public	ccoMap
ccoMap		dc.b	"brar"
fGotCMAP	dc.b	'y',0

		bss	ctable,128
* ===========================================================================
				END

