; muscode.a
; Assembler source code for some of the 'icky' bits of Musmus
;  Musus Umbra, 1997
; (written for Nick Roberts' !Asm - check it out it's really quite good :-)


	AREA	C$$CODE , CODE , READONLY

	EXPORT	Module_VersionH
	EXPORT	Module_Version
	EXPORT	Object_Type
	EXPORT	File_Type
	EXPORT	Handler_Border
	EXPORT	Make_Dir
	EXPORT	Copy_File
	EXPORT	Save_Typed
	EXPORT	Read_CMOS
	EXPORT	Write_CMOS
	EXPORT	OSVar
	EXPORT	ToolSprSize
	EXPORT	Wimp_SetMode
	EXPORT	OSCLI
	EXPORT	SetVarVal
	EXPORT	GetWimpFont
	EXPORT	ShiftPressed
	EXPORT	Hourglass
	EXPORT	AltDown
	EXPORT	NextSlot

;-------------------------------------------------------------------------------


Module_VersionH:	; int Module_VersionH( char *help_string );

	; we use the following registers:
	;	r0 = char *help
	;	r1 = int c
	;	r2 = int t
	;	r3 = int m
	;	r4 = int l

	stmfd	sp!,{r4,lr}
	mov	r4,#0		; l = 0

mvhl1:				; do {
	ldrb	r1,[r0],#1	; 	c = *help++;
	teq	r1,#0		; 	if ( !c ) {
	moveq	r0,#0		; 		return 0;
	ldmeqfd	sp!,{r4,pc}^	; 	}
	add	r4,r4,#1	; 	l++;
	teq	r1,#9		; 	if ( c==9 ) {
	addeq	r4,r4,#7	; 		l += 7;
	biceq	r4,r4,#7	; 		l &= ~7; }
	cmp	r4,#16		; }
	blt	mvhl1		; while (l<16);

mvhl2:				; do {
	ldrb	r1,[r0],#1	;	c = *help++;
	cmp	r1,#9		;	if ( c!=9 &&
	cmpne	r1,#32		;		c<32 ) {
	movlt	r0,#0		;		return 0;
	ldmltfd	sp!,{r4,pc}^	;	}
	subs	r1,r1,#48	; c -= 48;
	bmi	mvhl2		; while ( c<0 ||
	cmp	r1,#9		; c>9
	bgt	mvhl2		; );

	sub	r0,r0,#1	; help--;
	mov	r4,#0		; l = 0;
	mov	r3,#10		; m = 10;
	mov	r2,#0		; t = 0;

mvhl3:				; do {
	ldrb	r1,[r0],#1	; 	c = *help++;
	teq	r1,#32		; } while (
	beq	mvhl3		; 	c==32 );

mvhl4:				; do {
	subs	r1,r1,#48	;	c -= 48;
	bmi	emvhl4		;	if ( c<0 ) { break; }
	cmp	r1,#9		;	if ( c>9 )
	bgt	emvhl4		;		break;
	mla	r4,r3,r4,r1	;	l = (l*10) + c;
	ldrb	r1,[r0],#1	;	c = *help++;
	b	mvhl4		; } while (1);

emvhl4:	cmn	r1,#2		; if ( c != -2 )
	movne	r3,#100		; {
	mulne	r0,r4,r3	;	temp = l * 100;
	ldmnefd	sp!,{r4,pc}^	;	return temp; }

mvhl5:				; do {
	ldrb	r1,[r0],#1	;	c = *help++;
	subs	r1,r1,#48	;	c -= 48;
	bmi	emvhl5		;	if ( c<0 ) { break; }
	cmp	r1,#9		;
	bgt	emvhl5		;	if ( c>9 ) { break; }
	mla	r2,r1,r3,r2	;	t += (c*m);
	teq	r3,#10		;	if ( m==10 )
	moveq	r3,#1		;		m = 1;
	beq	mvhl5		;		continue;
				; } while (0);
emvhl5:	mov	r3,#100
	mla	r0,r4,r3,r2	; return t + (l * 100);
	ldmfd	sp!,{r4,pc}^



;------------------------------------------------------------------------------



Module_Version:	; int Module_Version( char *module_name );

	stmfd	sp!,{r4,r5,lr}
	mov	r1,r0			; module name
	mov	r0,#18			; reason code
	swi	"XOS_Module"		; lookup module name
	mvnvs	r0,#0			; if an error, return -1
	ldmvsfd	sp!,{r4,r5,pc}^		;
	ldr	r0,[r3,#&14]		; get offset from module start to help
	add	r0,r0,r3		; address of help string
	ldmfd	sp!,{r4,r5,lr}		; restore stacked regs
	b	Module_VersionH		; tail call optimised, as it were.



;-------------------------------------------------------------------------------


Object_Type:	; int Object_Type( char *pathname );

	stmfd	sp!,{r4,r5,lr}
	mov	r1,r0
	mov	r0,#17
	swi	"XOS_File"
	movvs	r0,#0		; treat errors as "not found"
	ldmfd	sp!,{r4,r5,pc}^


File_Type:	; int File_Type( char *pathname );

	stmfd	sp!,{r4,r5,lr}
	mov	r1,r0
	mov	r0,#17
	swi	"XOS_File"
	mov	r1,#0
	mvnvs	r0,#1		; -2 = error

	teq	r0,#0
	mvneq	r0,#0		; -1 = not found

	teq	r0,#2
	moveq	r0,#&1000	; &1000 = directory

	teq	r0,#1		; file ?
	teqne	r0,#3		; archive ?
	ldmnefd	sp!,{r4,r5,pc}^

	and	r0,r2,#&ff000000
	teq	r0,#&ff000000
	andeq	r0,r2,#&00f00000
	teqeq	r0,#&00f00000
	movne	r0,#&3000	; &3000 = untyped
	ldmnefd	sp!,{r4,r5,pc}^
	mov	r0,r2,lsr #8	; shift type into bits 0..11 of r0
	bic	r0,r0,#&ff000000
	bic	r0,r0,#&00ff0000
	bic	r0,r0,#&0000f000
	ldmfd	sp!,{r4,r5,pc}^



;-------------------------------------------------------------------------------



Handler_Border:	; BOOL Handler_Border( event_pollblock *pb, void *ref )


	ldr	r1,[r0]
	teq	r1,#1
	movne	r0,#0
	movnes	pc,lr

	stmfd	sp!,{r1-r10,lr}
	add	r10,r0,#4		; r10 -> the event_data

	mov	r1,r10			; block returned by Wimp_Poll
	swi	"XWimp_RedrawWindow"
	ldmvsfd	sp!,{r1-r10,pc}^

	ldr	r3,[r10,#4]		; r3 = min_x
	ldr	r4,[r10,#8]		; r4 = min_y
	ldr	r5,[r10,#12]		; r5 = max_x
	ldr	r6,[r10,#16]		; r6 = max_y
	sub	r5,r5,#2		; max_x --;
	sub	r6,r6,#2		; max_y --;

	teq	r0,#0			; nothing to do?
	moveq	r0,#1			;    return TRUE
	ldmeqfd	sp!,{r1-r10,pc}^		;    and exit.

hbl1:	mov	r0,#4
	swi	"XWimp_SetColour"	; set grey fg
	mov	r0,#4			; MOVE
	mov	r1,r3			; minx
	mov	r2,r4			; miny
	swi	"XOS_Plot"		;
	mov	r0,#5			; DRAW
	mov	r1,r5			; maxx
	mov	r2,r4			; miny
	swi	"XOS_Plot"
	mov	r0,#5			; DRAW
	mov	r1,r5			; maxx
	mov	r2,r6			; maxy
	swi	"XOS_Plot"
	mov	r0,#4			; MOVE
	add	r1,r3,#2		; minx+2
	add	r2,r4,#2		; miny+2
	swi	"XOS_Plot"
	mov	r0,#5			; DRAW
	sub	r1,r5,#2		; maxx-2
	add	r2,r4,#2		; miny+2
	swi	"XOS_Plot"
	mov	r0,#5			; DRAW
	sub	r1,r5,#2		; maxx-2
	sub	r2,r6,#2		; maxy-2
	swi	"XOS_Plot"
	mov	r0,#0
	swi	"XWimp_SetColour"	; set white fg
	mov	r0,#4			; MOVE
	mov	r1,r3			; minx
	mov	r2,r4			; miny
	swi	"XOS_Plot"
	mov	r0,#5			; DRAW
	mov	r1,r3			; minx
	mov	r2,r6			; maxy
	swi	"XOS_Plot"
	mov	r0,#5			; DRAW
	sub	r1,r5,#2		; maxx-2
	mov	r2,r6			; maxy
	swi	"XOS_Plot"
	mov	r0,#4			; MOVE
	add	r1,r3,#2		; minx+2
	add	r2,r4,#2		; miny+2
	swi	"XOS_Plot"
	mov	r0,#5			; DRAW
	add	r1,r3,#2		; minx+2
	sub	r2,r6,#2		; maxy-2
	swi	"XOS_Plot"
	mov	r0,#5			; DRAW
	sub	r1,r5,#4		; maxx-4
	sub	r2,r6,#2		; maxy-2
	swi	"XOS_Plot"
	mov	r1,r10			; block
	swi	"XWimp_GetRectangle"	; get next rectangle
	ldmvsfd	sp!,{r1-r10,pc}^
	teq	r0,#0			; done yet?
	bne	hbl1			; loop until we are
	mov	r0,#1
	ldmfd	sp!,{r1-r10,pc}^

;-------------------------------------------------------------------------------


Make_Dir:	; os_error *Make_Dir( char *path );
	stmfd	sp!,{r4,lr}
	mov	r1,r0
	mov	r0,#8
	mov	r4,#77
	swi	"XOS_File"
	movvc	r0,#0
	ldmfd	sp!,{r4,pc}^



Copy_File:	; os_error *Copy_File( char *dest, char *source );
	mov	ip,lr
	mov	r2,r0		; destination
	mov	r0,#26		; copy files
	mov	r3,#3		; ie. only Force
	swi	"XOS_FSControl"	; do the copy
	movvc	r0,#0		; to indicate success
	movs	pc,ip



Save_Typed:	; os_error *Save_Typed( char *name, int type, void *b, int size );
	stmfd	sp!,{r4,r5,lr}
	mov	r4,r2		; start address
	add	r5,r4,r3	; end address
	mov	r2,r1		; filetype
	mov	r1,r0		; filename
	mov	r0,#10		; save typed
	swi	"XOS_File"	; do the save
	movvc	r0,#0		; for success
	ldmfd	sp!,{r4,r5,pc}^


;-------------------------------------------------------------------------------


Read_CMOS:	; int Read_CMOS( int address );
	mov	ip,lr
	mov	r1,r0		; address
	mov	r0,#161		; read
	swi	"XOS_Byte"	;
	mvnvs	r0,#0		; return -1 for failure
	movvc	r0,r2		; else return value read
	movs	pc,ip

Write_CMOS:	; int Write_CMOS( int address, int value );
	mov	ip,lr
	mov	r2,r1		; value to write
	mov	r1,r0		; address
	mov	r0,#162		; write
	swi	"XOS_Byte"	;
	mvnvs	r0,#0		; return -1 for error
	movvc	r0,r2		; else return value written
	movs	pc,ip


;-------------------------------------------------------------------------------


OSVar:		;int OSVar( char *buffer, int buffer_size, char *variable );

	stmfd	sp!,{r4,lr}
	mov	r4,r0		; temp
	mov	r0,r2		; name of variable to read
	mov	r2,r1		; size of buffer
	mov	r1,r4		; buffer address
	mov	r3,#0		; context
	mov	r4,#0		; string, GSTrans now
	swi	"XOS_ReadVarVal"
	movvc	r0,r2		; bytes read
	movvs	r0,#0		; failure!
	ldmfd	sp!,{r4,pc}^


;-------------------------------------------------------------------------------


ToolSprSize:	; int ToolSprSize( void );

	stmfd	sp!,{r4-r5,lr}
	mov	r0,#9
	swi	"XWimp_ReadSysInfo"
	movvs	r0,#0
	ldmvsfd	sp!,{r4-r5,pc}^
	mov	r1,r0
	mov	r0,#8
	orr	r0,r0,#256
	swi	"XOS_SpriteOp"
	movvs	r0,#0
	movvc	r0,r2
	ldmfd	sp!,{r4-r5,pc}^

Wimp_SetMode:	; os_error *Wimp_SetMode( int mode );
	mov	ip,lr
	swi	"XWimp_SetMode"
	movvc	r0,#0
	movs	pc,ip

OSCLI:		; os_error *OSCLI( char *s )
	stmfd	sp!,{lr}
	swi	"XOS_CLI"
	movvc	r0,#0
	ldmfd	sp!,{pc}^


SetVarVal:	; os_error *SetVarValS( char *v, char *s );
	stmfd	sp!,{r4,lr}
	mov	r2,#0
svvl:	ldrb	r3,[r1,r2]
	cmp	r3,#31
	addgt	r2,r2,#1
	bgt	svvl
	mov	r3,#0
	mov	r4,#0
	swi	"XOS_SetVarVal"
	movvc	r0,#0
	ldmfd	sp!,{r4,pc}^


;-------------------------------------------------------------------------------

; This is a new idea for 1.10

GetWimpFont:	; void ...( char *buffer, int *xpts, int *ypts )
	stmfd	sp!,{r4-r9,lr}
	mov	r6,r0
	mov	r8,r1
	mov	r9,r2
	mov	r0,#0
	strb	r0,[r6]			; terminate buffer
	mov	r0,#8			; read desktop font handle
	swi	"XWimp_ReadSysInfo"
	movvs	r0,#0
	teq	r0,#0			; system font?
	ldmeqfd	sp!,{r4-r9,pc}^
	mov	r1,r6			; buffer for font name
	swi	"XFont_ReadDefn"
	ldmvsfd	sp!,{r4-r9,pc}^
	str	r2,[r8]			; xpts * 16
	str	r3,[r9]			; ypts * 16
	mov	r0,#0
gwfl:	ldrb	r2,[r1],#1		;
	cmp	r2,#32			; find terminator
	bge	gwfl			;
	strb	r0,[r1,#-1]		; and re-terminate with a NULL
	ldmfd	sp!,{r4-r9,pc}^


;-------------------------------------------------------------------------------

; This is new to 1.22

ShiftPressed:	; int ... ( void )
	stmfd	sp!,{lr}
	mov	r0,#121		; scan for particular key
	mov	r1,#&80		; Shift (either) ie. 0 EOR &80
	swi	"XOS_Byte"
	movvs	r1,#0		; If error, treat as not pressed
	and	r0,r1,#1	; convert the &FF into 1 (for C's sake)
	ldmfd	sp!,{pc}^

Hourglass:	; void ... ( int )
	stmfd	sp!,{lr}
	teq	r0,#0
	mov	r0,#0
	swieq	"XHourglass_Off"
	swine	"XHourglass_On"
	ldmfd	sp!,{pc}^


;-------------------------------------------------------------------------------

; This is new to 1.23

AltDown:
	stmfd	sp!,{lr}
	mov	r0,#121		; scan for particular key
	mov	r1,#&82		; Alt (either) ie. 2 EOR &80
	swi	"XOS_Byte"
	movvs	r1,#0		; If error, treat as not pressed
	and	r0,r1,#1	; convert the &FF into 1 (for C's sake)
	ldmfd	sp!,{pc}^

NextSlot:
	stmfd	sp!,{r4,lr}
	mov	r3,r0
	mvn	r0,#0
	mvn	r1,#0
	swi	"XWimp_SlotSize"	; read the current values
	mvnvs	r0,#0
	ldmvsfd	sp!,{r4,pc}^
	mov	r14,r1			; old 'next' slot
	mvn	r0,#0
	mov	r1,r3			; next slot to set
	swi	"XWimp_SlotSize"	; set the slottsize
	movvc	r0,r14			; previous next slot
	mvnvs	r0,#0
	ldmfd	sp!,{r4,pc}^		; and return it
