;#copy %s t:temp.asm
;#default t:temp.asm
;#delete %f
;#rename temp %f
;#copy %f rram:
;
; ### NewBench by JM v 1.05 ###
;
; - Created 891213 by JM -
;
;
; This program opens extra Workbench Screens and closes them.
;
;
;
;
; Bugs: yet unknown
;
;
; Edited:
;
; - 891213 by JM -> v0.01	- Source from Wati.asm.
; - 891213 by JM -> v0.02	- Works.
; - 891213 by JM,TM -> v0.10	- Command line parser.
; - 891213 by JM -> v1.00	- Screen size limiting added.
;				- Initial message added.
; - 891214 by JM -> v1.01	- Code compressing, (c) message added.
; - 891215 by JM -> v1.02	- Now recognizes NTSC mode and handles screen
;				  limits more intelligently.
; - 891215 by JM -> v1.03	- Some compressing...
; - 900317 by JM -> v1.04	- No longer closes screens that no longer
;				  exist.
; - 900803 by JM -> v1.05	- No longer exits while Forbidden.
;
;



		include	"exec.xref"
		include	"dos.xref"
		include	"intuition.xref"
		include	"JMPLibs.i"
		include	"relative.i"
		include	"com.i"
		include	"constants.i"
		include	"exec/types.i"
		include	"exec/nodes.i"
		include	"exec/lists.i"
		include	"exec/ports.i"
		include	"exec/memory.i"
		include	"exec/devices.i"
		include	"exec/io.i"
		include	"exec/tasks.i"
		include	"exec/execbase.i"
		include	"dosextens.i"
		include	"devices/input.i"
		include	"devices/inputevent.i"
		include	"intuition/intuitionbase.i"
		include	"intuition/screens.i"
		include	"graphics/gfxbase.i"


strcpy		macro	* a0,a1
strcpy\@	move.b	(\1)+,(\2)+
		bne.s	strcpy\@
		endm


RELATIVE	equ	1
MAXSCREEN	equ	16

 STRUCTURE  GlobalPort,MP_SIZE
    STRUCT  gp_scrs,4*MAXSCREEN
    STRUCT  gp_name,24
    STRUCT  gp_title,24
 LABEL gp_sizeof


		.var	global		allocates variables from stack
		dl	.DosBase	 using LINK a4,#-size
		dl	.IntuitionBase
		dl	.GfxBase
		dl	globport,newscr
		dl	cmdlin


start		.begin				this turns to LINK a4,#-NN
		clr.b	-1(a0,d0)		NULL terminate cmd line
		move.l	a0,cmdlin(a4)

		move.l	a4,a0			let's clear the variables
		clr.l	-(a0)
		clr.l	-(a0)
		clr.l	-(a0)
		clr.l	-(a0)

		openlib	Dos,cleanup		open dos.library ..
		openlib	Intuition,cleanup	intuition.library ..
		openlib	Gfx,cleanup		and gfx.library

		lea	MESSAGE(pc),a2		output initial message
		bsr	print

		lea	NS_temp,a1		copy default newscreen data
		move.l	a1,newscr(a4)		save ptr for later use
		lea	NS(pc),a0
		moveq	#ns_SIZEOF-1,d0
1$		move.b	(a0)+,(a1)+
		dbf	d0,1$

		lea	portname(pc),a1		test if port already exists
		lib	Exec,FindPort
		move.l	d0,globport(a4)

		move.l	cmdlin(a4),a0		address of cmd line
		move.l	newscr(a4),a1
		bsr	pars			parse parameters
		bcs.s	cleanup
		beq.s	Remove

MoreScreen	move.l	globport(a4),d0
		bne.s	Install1		-> port already exists
Install		bsr	CreatePort		create messageport
		bcs.s	cleanup			-> can't CreatePort()
Install1	bsr	MakeScreen
		bcc.s	cleanup
		lea	OSERR(pc),a2
		bsr	print
		bra.s	cleanup

Remove		move.l	globport(a4),d0
		beq.s	cleanup			-> no port exists
		bsr	RemoveScreens
		bne.s	cleanup			screens still open
		bsr	DeletePort		delete messageport

cleanup		closlib	Gfx
		closlib	Intuition		close intuition.library
		closlib	Dos			close dos.library
		moveq.l	#0,d0
		.end				UNLK and RTS



*************************************************************************
*									*
* Create messageport so that the screen pointers can be found by this	*
* program when run again.						*
*									*
* This messageport stays in memory as long as any of the screens is	*
* open.									*
*									*
*************************************************************************

CreatePort	move.l	#gp_sizeof,d0
		move.l	#MEMF_PUBLIC!MEMF_CLEAR,d1
		lib	Exec,AllocMem
		move.l	d0,globport(a4)
		beq.s	CreatePort_e
		move.l	d0,a2
		clr.b	LN_PRI(a2)
		move.b	#NT_MSGPORT,LN_TYPE(a2)

		lea	gp_name(a2),a1		space for port name
		move.l	a1,LN_NAME(a2)
		lea	portname(pc),a0
		strcpy	a0,a1			copy name into myport

		lea	gp_title(a2),a1		space for screen title
		lea	title(pc),a0
		strcpy	a0,a1			copy title

		move.l	a2,a1
		flib	Exec,AddPort		AddPort!  - Crash!? - No.
		clrc
		rts

CreatePort_e	setc
		rts


DeletePort	move.l	globport(a4),d2		get pointer to port
		beq.s	DeletePort_ok		if NULL nothing to delete
		move.l	d2,a1
		lib	Exec,RemPort		remove port from system list
		move.l	#gp_sizeof,d0
		move.l	d2,a1
		flib	Exec,FreeMem		free the memory used by port
DeletePort_ok	rts




MakeScreen	move.l	globport(a4),a2		get pointer to port
		lea.l	gp_scrs(a2),a2
		moveq	#MAXSCREEN-1,d0		max. number of screens
1$		tst.l	(a2)+			search for an empty ptr
		dbeq	d0,1$
		beq.s	MakeScreen1
MakeScreen_e	setc
		rts
MakeScreen1	move.l	newscr(a4),a0		NewScreen structure
		move.l	globport(a4),a1
		lea	gp_title(a1),a1		title string in our port
		move.l	a1,ns_DefaultTitle(a0)	set title to NewScreen

		move.w	#800,d2			Xmax
		move.w	#600,d3			Ymax for PAL
		move.w	#300,d4			limit for LACE

		move.l	.GfxBase(a4),a1		check if PAL system?
		btst	#2,gb_DisplayFlags+1(a1)
		bne.s	1$			.ne -> yup
		move.w	#470,d3			Ymax for NTSC
		move.w	#240,d4			new limit for LACE

1$		move.w	ns_Depth(a0),d0		depth of requested screen
		subq.w	#4,d0
		bls.s	2$			4 or less planes
		move.w	#352,d2			Xmax for >4 bitplanes
		subq.w	#2,d0			check if illegal size
		bhi.s	MakeScreen_e		too deep -> error
2$		cmp.w	ns_Width(a0),d2
		blo.s	MakeScreen_e		too wide -> error
		cmp.w	ns_Height(a0),d3
		blo.s	MakeScreen_e		too high -> error

		moveq	#0,d0
		cmp.w	#352,ns_Width(a0)
		bls.s	100$
		or.w	#V_HIRES,d0		Width > 352 -> HIRES
100$		cmp.w	ns_Height(a0),d4
		bhs.s	110$
		or.w	#V_LACE,d0		Height > limit -> LACE
110$		move.w	d0,ns_ViewModes(a0)

		lib	Intuition,OpenScreen
		move.l	d0,-(a2)
		beq.s	MakeScreen_e		couldn't OpenScreen
		rts


RemoveScreens	move.l	globport(a4),a2
		lea.l	gp_scrs(a2),a2
		moveq	#0,d3			flag: screens open
		moveq	#MAXSCREEN-1,d2
1$		move.l	(a2)+,d0
		bne.s	3$
4$		dbf	d2,1$
		move.l	d3,d0			# of screens still open
		rts
3$		push	d0
		lib	Exec,Forbid
		pull	d0
		move.l	.IntuitionBase(a4),a0
		move.l	ib_FirstScreen(a0),a0
31$		move.l	a0,d1
		beq.s	2$			screen no longer exists
		cmp.l	d1,d0			this screen found?
		beq.s	32$			yep -> okay to close it
		move.l	sc_NextScreen(a0),a0
		bra.s	31$
32$		move.l	d0,a0
		tst.l	sc_FirstWindow(a0)	windows open?
		bne.s	2$
		lib	Intuition,CloseScreen
		clr.l	-4(a2)
		bra.s	5$
2$		addq.l	#1,d3			yup -> incr cntr
5$		lib	Exec,Permit
		bra.s	4$

		

*************************************************************************
*									*
* Check for a command:							*
*									*
*************************************************************************

pars		;a0=cmdlin, a1=newscreen; p.z=cmd
		;handle the command line parameters:
		moveq	#0,d2			;no R gotten yet
100$		move.b	(a0)+,d0		;get one character
		beq.s	pars_end		;no more?
		cmp.b	#32,d0			;if space, get next
		beq.s	100$
		cmp.b	#'a',d0
		blo.s	101$
		cmp.b	#'z',d0
		bhi.s	101$			;lower-case alphabet?
		sub.b	#32,d0			;convert to upper case
101$		cmp.b	#'D',d0
		bne.s	200$
		bsr.s	pars_cvlo		;get depth
		bcs.s	pars_usage		;error?
		move.w	d0,ns_Depth(a1)		;no, assign it there
		bra.s	100$			;and go for next parameter
200$		cmp.b	#'W',d0
		bne.s	300$
		bsr.s	pars_cvlo		;get width
		bcs.s	pars_usage		;error?
		move.w	d0,ns_Width(a1)		;no, assign width
		bra.s	100$			;and get next parameter
300$		cmp.b	#'H',d0
		bne.s	400$
		bsr.s	pars_cvlo		;get height
		bcs.s	pars_usage		;error?
		move.w	d0,ns_Height(a1)	;no, assign that for height
		bra.s	100$			;and get the next one
400$		cmp.b	#'R',d0
		bne.s	500$
		move.b	d0,d2			;save the R (remove) flag
		bra.s	100$
500$		;now it was some unidentified character:
pars_usage	lea.l	pars_usage.(pc),a2	;print out
		bsr.s	print			;  "usage: bla bla bla"
		setc				;and return an error
		rts				;/otherwise:
pars_end	cmp.b	#'R',d2			;was there an R somewhere?
		clrc				;return OK
		rts

pars_cvlo	;get a base-10 number:
		;(for technical reasons does not accept the value 0)
		moveq	#0,d0			;clear the result
1$		moveq	#0,d1
		move.b	(a0)+,d1		;get one digit
		cmp.b	#'9',d1			;greater than "9" ..
		bhi.s	2$
		sub.b	#'0',d1			;.. or less than "0"?
		blo.s	2$			;if so, go ->
		add.l	d0,d0			;otherwise * result by 2
		add.l	d0,d1			;and save
		asl.l	#2,d0			;multiply by 4
		add.l	d1,d0			;and add the by-2 and ..
		bra.s	1$			;.. the digit and get next one
2$		;now some other character than a numeric digit was found:
		subq.l	#1,a0			;go back to that dummy
		tst.l	d0			;any value gotten this far?
		bne.s	3$			;yes, return no error
		setc				;no, return error
3$		rts


print		lib	Dos,Output
		move.l	d0,d1
		beq.s	print_e			no output file handle
		moveq	#0,d3
		move.b	(a2)+,d3		length
		move.l	a2,d2
		flib	Dos,Write		output text
print_e		rts


NS		dc.w	0,0,640,256,2		x,y,xs,ys,dpth
		dc.b	0,1			block,detail
		dc.w	V_SPRITES		viewmodes
		dc.w	WBENCHSCREEN		type
		dc.l	0			text attr
		dc.l	0			title
		dc.l	0			ggs
		dc.l	0			bm


portname	equ	*
title		dc.b	'NewBenchScreen',0
MESSAGE		dc.b	38,'NewBench v1.05 by Supervisor Software',LF
OSERR		dc.b	06,'Error',LF
pars_usage.	dc.b	46			;text length here!
			;01234567890123456789012345678901234567890123456789
		dc.b	'Usage: newbench ([Ddepth][Wwidth][Hheight])|R',LF
		ds.w	0


*************************************************************************
*									*
* This macro produces the library names in this program.		*
*									*
*************************************************************************

		libnames

		section	help,bss
NS_temp		ds.b	ns_SIZEOF

		end

