; File name:	MARK_RAM.S	Revised:	1992.02.27
; Disassembler:	U.R.Andersson	Disassembled:	1992.01.31
; Purpose:	Reset-proof ramdisk hidden beyond mapped 1MB area.
;
stack_size	=	$1000
HIGHDATE	=	$19560221	;identification code
;NB: Identification is made by checking this code in high RAM during boot
;NB: But XBRA chains are also tested to avoid dual installation
;
	output	.TOS
;
	nolist
	include	URAn_SYS.S
	include	URAn_DOS.S
	include	URAn_XB.S	; This defines 9 macros handling XBRA protocol
;
;   The first 4 alter no registers
; XB_define	xbstruct,xbra_id	Defines header for XBRA function code
; XB_gonext	xbstruct		Links to next XBRA function in chain
; XB_gonext_d	xbstruct		Links to next XBRA function in chain
; XB_donext_d	xbstruct		Calls next XBRA subroutine in chain
;
;   The next 2 alter only the choosen "areg"
; Find_Frame	areg			areg->exception argument -6
; XB_donext	xbstruct,areg		Calls next XBRA function in chain
;
;   The next 3 affect d0-d2/a0-a2, since they use XBIOS Supexec
; XB_check	xbstruct,root		d0= found_codead/zero  flagged NE/EQ
;   -"-           -"-			a0->found_vector/last_vector 
; XB_install	xbstruct,root		Installs xbstruct in chain(root)
; XB_remove	xbstruct,root		Removes xbstruct from chain(root)
;
; Legal forms for xbstruct & root here are mostly the same as for LEA & PEA,
;   except that for XB_define "xbstruct" is a free name for the new structure.
; "xbstruct" always refers to the first byte of the entire structure.
; "xbra_id" is a 4-character (longword) string
; "areg" is a free address register of your choice.
; XB_gonext_d & XB_donext_d are faster versions of XB_gonext & XB_donext,
;   but can only handle address modes where "xbstruct" begins with identifier.
;   eg:   "XB_donext_d  my_ikbd_sub(pc)"   but:   "XB_donext  (a5)+"
; Find_Frame makes XBRA exception functions (eg: gemdos etc.) TT compatible.
;
;
	nolist
;
	text
	opt	a+
	opt	p+
	opt	o+
;
text_base:
tb:
	bra	startup
;
;
	data
;
static		;static data uses only positive indexing
;
OS_calljump_s:	dc.w	$4EF9		;32bit abs jump instruction
OS_calllink_s:	dc.l	0		;address for jump above
OS_callsave_s:	dc.l	0,0		;place for saved a1 & a2
;
copyright_s:
	dc.b	ESC,'E',ESC,'e',ESC,'v',ESC,'p'
	dc.b	' *** Public domain software ***         '
	dc.b	' (C) Ulf Ronald Andersson    25.02.1992 ',ESC,'q'
	dc.b	CR,LF
	dc.b	'M A R K _ R A M   V e r s i o n   1.0 : '
	dc.b	'Hides RAM_disk beyond hw_mapped 1M area',CR,LF
	dc.b	ESC,'p'
	dc.b	' *** Public domain software ***         '
	dc.b	' (C) Ulf Ronald Andersson    25.02.1992 ',ESC,'q'
	dc.b	CR,LF,NUL
;
not_got_mem_s:
	dc.b	'There is too little free RAM !!!',CR,LF,NUL
;
mpb_err_s:
	dc.b	"The MPB's look too strange !!!",CR,LF,NUL
;
alldone_s:
	dc.b	CR,LF
	dc.b	'All available RAM has now been marked !',CR,LF,NUL
;
data_end:
;
;
	RSSET	(data_end-static)	;some statics are in BSS too
basepage_p	rs.l	1	;->basepage of highdisk program
URAn_mpb	rs.l	1	;->MPB'variables in OS RAM  (TOS independent search)
URAn_movesize	rs.l	1	;long for size of protected RAM during init (screen etc.)
URAn_movedist	rs.l	1	;long for distance to move protected data during init
local_sp	rs.l	1
convbuff	rs.l	12/4	;10 bytes minimum for hex to dec conversion
static_end	= __RS
;
data_static	= (data_end-static)
bss_static	= (static_end-data_static)
;
;
	text
;
;
	include	FIND_MPB.S
;
;
mark_1024:
	move.b	#5,(hw_mapper).w
	move	SR,-(sp)
	ori	#$0700,SR
	move.b	#6,(hw_mapper).w
	rept	256
	move.l	a1,(a1)+
	endr
	move.b	#5,(hw_mapper).w
	move	(sp)+,SR
	rts
;
;
fast_512:
	rept	128
	move.l	(a0)+,(a1)+
	endr
	rts
;
move_512:
	rept	512
	move.b	(a0)+,(a1)+
	endr
move_null:
	rts
;
fast_move:
	asl	#1,d0
	neg	d0
	jmp	move_null(pc,d0)
;
;
startup:
	move.l	4(sp),a5	;a5->bp
	lea	static(pc),a4
	move.l	bp_textlen(a5),d0
	add.l	bp_datalen(a5),d0
	add.l	bp_bss_len(a5),d0
	add.l	#$100,d0		;d0 += basepage size
	add.l	#stack_size,d0		;d0 += stack margin
	move.l	d0,d1
	add.l	a5,d1			;d1= a5 + d0
	and.l	#-2,d1			;masked even
	move.l	d1,sp			;then made new USP !!!
	move.l	d1,local_sp(a4)
	gemdos	Mshrink!_IND,!,a5,d0	;returns memory to system
	move.l	a5,basepage_p(a4)
main:
	link	a6,#-4
	sub_xbios	Cursconf,!,!
	sub_gemdos	Cconws,copyright_s(pc)
	sub_gemdos	Super,!
	move.l	d0,-4(a6)	;entry SSP
	cmp.b	#5,(memctrl).w
	beq.s	join_warmcold
.install_high:
	sub_gemdos	Malloc,?
	move.l	(phystop).w,d1
	cmpi.l	#$108000,d1	;demand phystop 32KB above 1MB to init HighDisk
	blo	bad_memsize
	sub.l	d0,d1
	cmpi.l	#$0F8000,d1	;demand 32KB free below 1MB to init HighDisk
	bhi	bad_memsize
	jsr	take_HIGH_RAM(pc)	;d0= take_HIGH_RAM()
	tst.l	d0
	beq	mpb_err_main		;exit with error if pointer is NULL
	move.b	#5,(memctrl).w
	move.b	#5,(hw_mapper).w
join_warmcold:
	sub_gemdos	Malloc,?
	move.l	d0,d6			;d6= Size
	sub_gemdos	Malloc,d6	;re-grab all RAM
	move.l	d0,d7			;d7= Base
	ble.s	mark_high
mark_low:
	move.l	d6,d0
	lsr.l	#8,d0			;d0= Size/256
	lsr.l	#2,d0			;d0= Size/1024
	subq	#1,d0			;d0 adjusted for dbra
	move.l	d7,a1
mark_loop_1:
	bsr	mark_1024
	dbra	d0,mark_loop_1
mark_high:
	move	#$180000/$400,d0
	subq	#1,d0			;d0 adjusted for dbra
	move.l	#$100000,a1
mark_loop_2:
	bsr	mark_1024
	dbra	d0,mark_loop_2
	sub_gemdos	Mfree!_IND,d7
	sub_gemdos	Cconws,alldone_s
	sub_gemdos	Super!_IND,-4(a6)
.fnend_main_OK:
	clr.l	d0
	bra.s	fnend_main
;
bad_memsize:
	sub_gemdos	Cconws,not_got_mem_s-static(a4)
	bra.s	fnend_main_err
;
mpb_err_main:
	sub_gemdos	Cconws,mpb_err_s-static(a4)
fnend_main_err:
	moveq	#-1,d0
fnend_main:
	gemdos	Pterm,d0
;
;
; void	*take_HIGH_RAM(void)
take_HIGH_RAM:
	link	a6,#-18
	move.l	(phystop).w,d0
	sub.l	#$100000,d0
	add.l	#$1FE,d0		;to allow screen basing
	move.l	d0,-10(a6)		;RAM_need= d0
	and	#-$200,d0		;ensures screen at 512_byte multiple
	move.l	d0,URAn_movedist(a4)
	addq.l	#8,-10(a6)		;bump RAM_need a bit to ensure release_ability
	sub_gemdos	Malloc,?	;d0= Malloc(-1)
	move.l	d0,-6(a6)		;Free_RAM= d0
	sub.l	-10(a6),d0		;d0= Free_RAM - RAM_need
	sub_gemdos	Malloc,d0	;d0= Malloc(d0)
	move.l	d0,-14(a6)		;store void *UNwantedp
	beq.s	.take_failed
	sub_gemdos	Malloc,-10(a6)	;d0= Malloc(RAM_need)
	move.l	d0,-18(a6)		;store void *WANTED_RAM_p
	beq.s	.take_failed
	sub_gemdos	Mfree!_IND,-14(a6)	;Mfree(UNwantedp)
	move.l	-10(a6),-(sp)
	move.l	-18(a6),-(sp)
	bsr	find_mpb		;find_mpb(WANTED_RAM_p, RAM_need)
	addq	#8,sp
	subq.l	#1,d0
	beq.s	.mpb_found
.take_failed:
	clr.l	d0			;NULL return pointer flags failure
	bra	.exit_take_HIGH
;
.mpb_found:
	move.l	a0,URAn_mpb(a4)
	move.l	(phystop).w,d0
	sub.l	(_memtop).w,d0
	and.l	#-2,d0
	move.l	d0,URAn_movesize(a4)
	move.l	URAn_mpb(a4),a2		;a2-> MPB root vector group
	move.l	4(a2),a2		;a2-> MPB of *WANTED_RAM_p
	move.l	(_memtop).w,a0		;a0->old _memtop  NB: orig assumed == _v_bas_ad
	move.l	a0,a1
	move.l	URAn_movedist(a4),d0
	sub.l	d0,a1			;a1->new _memtop for data move
	sub.l	d0,8(a2)		;shrink MPB, so we can lock up properly!!! 
	sub.l	d0,(_memtop).w		;NB: orig did not move _memtop, or shrink MPB
	sub.l	d0,(phystop).w		;Here new areas are protected
	move.l	URAn_movesize(a4),d0	;NB: orig used constant size 32000
	beq.s	.screen_lpx		;phystop may equal _memtop if screen Malloc'd
	lsr.l	#4,d0			;move as quad longwords (overlap doesn't matter)
	subq.l	#1,d0
	swap	d0
.screen_lp1:				;Loop 1 start
	swap	d0
.screen_lp2:				;Loop 2 start
	move.l	(a0)+,(a1)+		;move screen data to new area
	move.l	(a0)+,(a1)+		;move screen data to new area
	move.l	(a0)+,(a1)+		;move screen data to new area
	move.l	(a0)+,(a1)+		;move screen data to new area
	dbra	d0,.screen_lp2		;Loop for whole screen
	swap	d0
	dbra	d0,.screen_lp1
.screen_lpx:
	move.l	(_v_bas_ad).w,d0
	sub.l	URAn_movedist(a4),d0
	move.l	d0,(screenpt).w
	sub_xbios	Vsync
	clr.l	(screenpt).w
	sub_gemdos	Mfree!_IND,-18(a6)	;release unused part of MPB
	move.l	#$100000,d0
.exit_take_HIGH:
	unlk	a6
	rts			;return d0= new phystop  URAn_movedist= highdisk area size
;
;
; strtoul(char *digitp)
strtoul:
	link	a6,#-4
	clr.l	-4(a6)	;value= 0
	bra.s	.LCB2
;
.LC84:				;Loop start
	move.l	-4(a6),d0
	asl.l	#2,d0		;d0= value * 4
	add.l	-4(a6),d0	;d0= value * 5
	asl.l	#1,d0		;d0= value * 10
	move.l	8(a6),a0	;a0= digitp
	addq.l	#1,8(a6)	;digitp += 1
	move.b	(a0),d3
	sub.b	#'0',d3		;d3= new bcd digit
	ext.w	d3
	ext.l	d3
	add.l	d3,d0
	move.l	d0,-4(a6)	;value= value*10 + digit
.LCB2:
	move	#'0',d0
	move.l	8(a6),a0
	move.b	(a0),d1		;d1= next ascii digit
	ext.w	d1
	cmp	d1,d0
	bgt	.LCD4		;exit loop if '0' > digit
	cmp	#$39,d1
	ble.s	.LC84		;loop back if digit <= '9'
.LCD4:
	move.l	-4(a6),d0
	unlk	a6
	rts
;
;
;char *ultoa(long value)
ultoa:
	link	a6,#-4
	lea	convbuff(a4),a0
	move.l	#$3B9ACA00,-4(a6)	;limit= 1000,000,000
	bra	.LD12
;
.LCF8:
	move.l	-4(a6),-(sp)
	move.l	#10,-(sp)
	jsr	long_div(pc)	;long_div(limit,10)
	move.l	(sp)+,-4(a6)	;limit /= 10
	addq.l	#4,sp
.LD12:
	move.l	8(a6),d0	;d0= value
	cmp.l	-4(a6),d0
	bge	.LD2A		;go .LD2A if value >= limit
	cmpi.l	#$1,-4(a6)
	bgt.s	.LCF8		;go .LCF8 if limit >1
;here value>=limit, or limit==1
.LD2A:				;Loop start
	move.l	8(a6),-(sp)
	move.l	-4(a6),-(sp)
	jsr	long_div(pc)	;long_div(value,limit)
	move.l	(sp)+,d0	;d0= quotient
	move.l	(sp)+,8(a6)	;value= remainder
	add.l	#'0',d0
	move.b	d0,(a0)+	;store new digit
	move.l	-4(a6),-(sp)
	move.l	#10,-(sp)
	jsr	long_div(pc)	;long_div(limit,10)
	move.l	(sp)+,-4(a6)	;limit /= 10
	addq.l	#4,sp
	bne.s	.LD2A		;loop back for each digit
	clr.b	(a0)		;terminate string
	lea	convbuff(a4),a0
	move.l	a0,d0
	unlk	a6
	rts			;return with d0= a0->convbuff
;
;
; long_div(Divs,Divd)
long_div:
	link	a6,#-2
	movem.l	d0-d3,-(sp)
	move.l	8(a6),d2	;d2= Divs
	bne.b	L1872		;go L1872 unless Divs==0
	divu	#$0,d0		;div by ZERO !!!
	clr.l	d0
	clr.l	d1
	bra.b	L18BC
;
L1872:
	move.l	12(a6),d1	;d1= Divd
	clr	-2(a6)		;x1= 0
	tst.l	d1		;Divd >= 0 ?
	bge.b	L1884
	addq	#3,-2(a6)	;x1+=3
	neg.l	d1		;Divd= abs(Divd)
L1884:
	tst.l	d2		;Divs >= 0
	bge.b	L188E
	addq	#1,-2(a6)	;x1 += 1
	neg.l	d2		;Divs= abs(Divs)
L188E:
	moveq	#1,d3		;d3= 1
L1890:				;loop start
	cmp.l	d1,d2		;Divs - Divd ?
	bhs.b	L189A		;exit loop if Divs >= Divd
	asl.l	#1,d2		;Divs *= 2
	asl.l	#1,d3		;d3 *= 2
	bra.b	L1890		;loop back
;
L189A:
;here d3 is the factor Divs needed to match or exceed Divd
	clr.l	d0		;d0= 0
L189C:				;loop start
	cmp.l	d1,d2		;Divs - Divd ?
	bhi.b	L18A4		;keep Divd & d0 if Divs > Divd
	or.l	d3,d0		;d0 |= d3
	sub.l	d2,d1		;Divd -= Divs
L18A4:
	lsr.l	#1,d2		;Divs /= 2
	lsr.l	#1,d3		;d3 /= 2
	bcc.b	L189C		;loop until d3 lost a bit
;here d0 is the quotient abs(Divd)/abs(Divs)
	cmpi	#3,-2(a6)	;x1 - 3 ?
	blt.b	L18B4		;keep Divd if originally positive
	neg.l	d1		;else negate Divd
L18B4:
	lsr	-2(a6)		;CF = x1 & 1
	bcc.b	L18BC		;keep d0 if orig Divs had sign of Divd
	neg.l	d0		;else negate d0
L18BC:
	move.l	d0,8(a6)	;return quotient in Divs, but NOT in d0
	move.l	d1,12(a6)	;return remainder in Divd
	movem.l	(sp)+,d0-d3
	unlk	a6
	rts			;return from function
;
;
bios_sub:
	movem.l	a1-a2,OS_callsave_s-static(a4)
	move.l	(sp)+,OS_calllink_s-static(a4)
	trap	#13
	movem.l	OS_callsave_s-static(a4),a1-a2
	jmp	OS_calljump_s-static(a4)
;
;
xbios_sub:
	movem.l	a1-a2,OS_callsave_s-static(a4)
	move.l	(sp)+,OS_calllink_s-static(a4)
	trap	#14
	movem.l	OS_callsave_s-static(a4),a1-a2
	jmp	OS_calljump_s-static(a4)
;
;
gemdos_sub:
	movem.l	a1-a2,OS_callsave_s-static(a4)
	move.l	(sp)+,OS_calllink_s-static(a4)
	trap	#1
	movem.l	OS_callsave_s-static(a4),a1-a2
	jmp	OS_calljump_s-static(a4)
;
;
	bss
;
	ds.l	(bss_static+3)/4
;
bss_limit:
;
;
	end	;of file:	MARK_RAM.S
