; scrsh v2.1 : opens a shell on its own public screen
; by Kyzer/CSG
; $VER: scrsh.asm 2.1 (10.02.00)
;
	incdir	include:
	include	dos/dos.i
	include	intuition/screens.i
	include	lvo/dos_lib.i
	include	lvo/exec_lib.i
	include	lvo/graphics_lib.i
	include	lvo/intuition_lib.i
	include	utility/tagitem.i

stackf	MACRO	; stack_symbol, stackelement_symbol, [size=4]
	IFND	\1
\1	set	0
	ENDC
	IFGE	NARG-3
\1	set	\1-\3
	ELSE
\1	set	\1-4
	ENDC
\2	equ	\1
	ENDM

INTBASE equr d7
DOSBASE	equr d6

CMD_SIZE=128
PUB_SIZE=16

numtags = 11				; number of tags in taglist
tagsize = numtags*8 + 4			; real size of taglist
pubtag	= (_pub  +1-taglist)<<2		; real offsets for tag datas
tasktag	= (_task +1-taglist)<<2
modetag	= (_mode +1-taglist)<<2
ttltag	= (_ttl  +1-taglist)<<2
penstag	= (_pens +1-taglist)<<2

	stackf	stk, cmd, CMD_SIZE	; newcli cmd
	stackf	stk, pubname, PUB_SIZE	; public screen name
	stackf	stk, scrtags, tagsize	; openscreen tags
	stackf	stk, screen
	stackf	stk, gfxbase

ScrSh	link	a5,#stk
	move.l	4.w,a6

	; uncompress the tag-array into real tags on the stack
	lea	scrtags(a5),a4		; A4 = scrtags
	lea	taglist(pc),a0		; a0 = taglist (as bytes)
	move.l	a4,a1			; a1 = taglist (to be written) on stack
	moveq	#numtags*2-1,d0		; d0 = number of tags
	moveq	#0,d1
.tags	bchg	#31,d1			; alternately $80000000+num, 0+num, ...
	move.b	(a0)+,d1		; set low byte of long
	move.l	d1,(a1)+		; write long
	dbra	d0,.tags
	clr.l	(a1)			; end with TAG_DONE


	lea	scrname(pc),a0
	move.l	a0,ttltag(a4)		; title pointer
	lea	pens(pc),a0
	move.l	a0,penstag(a4)		; pens pointer

	suba.l	a1,a1			; create the pubname
	jsr	_LVOFindTask(a6)
	move.l	d0,-(sp)
	lea	pubfmt(pc),a0
	move.l	sp,a1
	lea	putchar(pc),a2
	lea	pubname(a5),a3
	move.l	a3,pubtag(a4)
	jsr	_LVORawDoFmt(a6)
	move.l	(sp)+,tasktag(a4)	; write the sigtask to tags

	lea	intname(pc),a1		; open libraries
	bsr.s	.opnlib
	move.l	d0,INTBASE
	beq.s	.noint
	lea	gfxname(pc),a1
	bsr.s	.opnlib
	move.l	d0,gfxbase(a5)
	beq.s	.nogfx
	lea	dosname(pc),a1
	bsr.s	.opnlib
	move.l	d0,DOSBASE
	beq.s	.nodos

	bra.s	.screen			; open the screen and prepare command

.opnlib	moveq	#37,d0
	jmp	_LVOOpenLibrary(a6)

.exec	move.l	a3,d1			; the command
	moveq	#0,d2
	moveq	#0,d3
	exg.l	DOSBASE,a6
	jsr	_LVOExecute(a6)
	exg.l	DOSBASE,a6
	tst.l	d0
	beq.s	.close

.wait	move.l	4.w,a6
	move.l	#SIGBREAKF_CTRL_C,d0
	jsr	_LVOWait(a6)		; wait for screen close or ctrl-c
.close	move.l	screen(a5),a0
	exg.l	INTBASE,a6
	jsr	_LVOCloseScreen(a6)	; try to close screen
	exg.l	INTBASE,a6
	tst.l	d0
	beq.s	.wait			; loop back on error
.noscr	move.l	4.w,a6
	move.l	DOSBASE,a1
	jsr	_LVOCloseLibrary(a6)
.nodos	move.l	gfxbase(a5),a1
	jsr	_LVOCloseLibrary(a6)
.nogfx	move.l	INTBASE,a1
	jsr	_LVOCloseLibrary(a6)
.noint	unlk	a5
	moveq	#0,d0
	rts

.screen	; open the screen
	move.l	INTBASE,a6
	suba.l	a0,a0
	jsr	_LVOGetDefaultPubScreen(a6)
	tst.l	d0
	beq.s	.nodef
	move.l	d0,a0
	lea	sc_ViewPort(a0),a0
	move.l	gfxbase(a5),a6
	jsr	_LVOGetVPModeID(a6)
	move.l	d0,modetag(a4)
.nodef	move.l	INTBASE,a6
	suba.l	a0,a0
	move.l	a4,a1
	jsr	_LVOOpenScreenTagList(a6)
	move.l	d0,screen(a5)
	beq.s	.noscr
	move.l	d0,a0
	moveq	#0,d0
	jsr	_LVOPubScreenStatus(a6)		; make us a public screen
	lea	pubname(a5),a0			; make us the default screen
	jsr	_LVOSetDefaultPubScreen(a6)

	; create the newcli command
	moveq	#3,d1
	pea	pubname(a5)			; %s arg - public screen name
	move.l	screen(a5),a0
	move.w	sc_Height(a0),-(sp)		; %d arg - height
	sub.w	d1,(sp)
	move.w	sc_Width(a0),-(sp)		; %d arg - width
	move.l	d1,-(sp)			; %d %d args - left/top

	lea	cmdfmt(pc),a0
	move.l	sp,a1
	lea	putchar(pc),a2
	lea	cmd(a5),a3
	move.l	4.w,a6
	jsr	_LVORawDoFmt(a6)
	adda.w	#4+(2*4),sp			; restore stack
	bra	.exec				; run the command (a3)

putchar	move.b	d0,(a3)+
	rts

; a long-to-byte taglist reducing macro. see starting code which expands this
tag	macro
	dc.b	(\1-$80000000),\2
	endm

taglist
_pub	tag	SA_PubName,0
	tag	SA_PubSig,SIGBREAKB_CTRL_C
_task	tag	SA_PubTask,0
	tag	SA_Type,PUBLICSCREEN
_mode	tag	SA_DisplayID,0
	tag	SA_Depth,2
_ttl	tag	SA_Title,0
	tag	SA_ShowTitle,1
_pens	tag	SA_Pens,0
	tag	SA_AutoScroll,1
	tag	SA_FullPalette,1

pens	dc.w	-1

dosname	dc.b	'dos.library',0
gfxname	dc.b	'graphics.library',0
intname	dc.b	'intuition.library',0

scrname	dc.b	'AmigaShell',0
pubfmt	dc.b	'SHELL_%08lx',0
cmdfmt	dc.b	'NewCLI CON:%d/%d/%d/%d//BACKDROP/NOBORDER/NOGADS/SCREEN%s',0
	dc.b	'$VER: scrsh 2.1 (10.02.00)',0
