;
; RISC OS / ARM assembler glue code for DOOM.
; (C) 1998 Andreas Dehmel.
;

r0	RN	0
r1	RN	1
r2	RN	2
r3	RN	3
r4	RN	4
r5	RN	5
r6	RN	6
r7	RN	7
r8	RN	8
r9	RN	9
r10	RN	10
r11	RN	11
r12	RN	12



	;
	; Chapter 1: RISC OS specific stuff.
	;

;	IDFN	(C) 1998 by Andreas Dehmel


	AREA	|Asm$$Code|, CODE, READONLY

	EXPORT	|ReadMonotonicTime|
	=	"ReadMonotonicTime"
	ALIGN	4

|ReadMonotonicTime|
	swi	0x20042		; XOS_ReadMonotonicTime
	movs	pc,lr



	EXPORT	|LowerCaseTable|
	=	"LowerCaseTable"
	ALIGN	4

|LowerCaseTable|
	mvn	r0,#0
	swi	0x63057		; XTerritory_LowerCaseTable
	movs	pc,lr



	EXPORT	|ReadFileInfo|
	=	"ReadFileInfo"
	ALIGN	4

|ReadFileInfo|
	stmdb	sp!, {r4-r6}
	mov	r6, r1
	mov	r1, r0
	mov	r0, #0x11
	swi	0x20008		; XOS_File
	stmia	r6, {r2-r5}
	ldmia	sp!, {r4-r6}
	movs	pc, lr



	EXPORT	|SetFiletype|
	=	"SetFiletype"
	ALIGN	4

|SetFiletype|
	mov	r2, r1
	mov	r1, r0
	mov	r0, #0x12
	swi	0x20008
	movs	pc, lr



	EXPORT	|ChangeEscapeEffect|
	=	"ChangeEscapeEffect"
	ALIGN	4

|ChangeEscapeEffect|		; r0 eor, r1 and
	mov	r2, r1
	mov	r1, r0
	mov	r0, #0xc8
	swi	0x20006		; XOS_Byte 200
	mov	r0, r1
	movs	pc, lr



	EXPORT	|FillMemoryWord|
	=	"FillMemoryWord"
	ALIGN	4

|FillMemoryWord|		; r0 *scr, r1 value (32bit), r2 size
	stmdb	sp!, {r4, lr}
	bic	r0, r0, #3
	bics	r2, r2, #3	; words only
	beq	|FMWexit|
	mov	r3, r1
	mov	r4, r1
	mov	lr, r1
	subs	r2, r2, #0x10
	blt	|FMWsmall|
|FMWloop|
	stmia	r0!, {r1, r3, r4, lr}
	subs	r2, r2, #0x10
	bge	|FMWloop|
|FMWsmall|
	adds	r2, r2, #0x10
	ble	|FMWexit|
	tst	r2, #0x08
	stmneia	r0!, {r1, r3}
	tst	r2, #0x04
	strne	r1, [r0], #4
|FMWexit|
	ldmia	sp!, {r4, pc}^



	EXPORT	|FillMemoryShort|
	=	"FillMemoryShort"
	ALIGN	4

|FillMemoryShort|
	stmdb	sp!, {r4, lr}
	bic	r0, r0, #1
	bic	r2, r2, #1	; shorts only
	tst	r2, #2
	beq	|FMSnoALIGN|
	strb	r1, [r0], #1
	mov	lr, r1, lsr #8
	strb	lr, [r0], #1
	subs	r2, r2, #2
	ble	|FMSexit|
|FMSnoALIGN|
	orr	r1, r1, r1, lsl #16
	mov	r3, r1
	mov	r4, r1
	mov	lr, r1
	subs	r2, r2, #0x10
	blt	|FMSsmall|
|FMSloop|
	stmia	r0!, {r1, r3, r4, lr}
	subs	r2, r2, #0x10
	bge	|FMSloop|
|FMSsmall|
	adds	r2, r2, #0x10
	ble	|FMSexit|
	tst	r2, #0x08
	stmneia	r0!, {r1, r3}
	tst	r2, #0x04
	strne	r1, [r0], #4
	tst	r2, #0x02
	strneb	r1, [r0], #1
	movne	lr, r1, lsr #8
	strneb	lr, [r0], #1
|FMSexit|
	ldmia	sp!, {r4, pc}^






screen_desc_base	EQU	0
screen_desc_size	EQU	4
screen_desc_resx	EQU	8
screen_desc_resy	EQU	12

	EXPORT	|ReadScreenInfo|
	=	"ReadScreenInfo"
	ALIGN	4

|ReadScreenInfo|		; r0 *screen_desc
	mov	r3, r0
	mov	r0, #2
	swi	0x2005c
	stmia	r3, {r0, r1}
	mvn	r0, #0
	mov	r1, #0x0b
	swi	0x20035		; XOS_ReadModeVariable
	add	r2, r2, #1
	str	r2, [r3, #screen_desc_resx]
	mov	r1, #0x0c
	swi	0x20035
	add	r2, r2, #1
	str	r2, [r3, #screen_desc_resy]
	movs	pc, lr



	EXPORT	|PrepareWithoutFrames|
	=	"PrepareWithoutFrames"
	ALIGN	4

|PrepareWithoutFrames|			; r0 *frame_buffer
	mov	r3, r0
	mov	r0, #0x03000000
	mov	r1, #0			; use first screen
	stmdb	sp!, {r0, r1}
	mov	r0, #22
	add	r1, sp, #3
	swi	0x20007
	add	sp, sp, #8
	swi	0x20036
	mov	r0, #0
	movs	pc, lr



	EXPORT	|ScanKeyboard|
	=	"ScanKeyboard"
	ALIGN	4

|ScanKeyboard|				; R0 = low tide mark of internal key number
	mov	r1, r0
	mov	r0, #0x79
	swi	0x20006
	mov	r0, r1
	movs	pc,lr



	EXPORT	|FlushABuffer|
	=	"FlushABuffer"
	ALIGN	4

|FlushABuffer|
	mov	r1, r0
	mov	r0, #0x15
	swi	0x20006
	movs	pc,lr



	EXPORT	|InsertInBuffer|
	=	"InsertInBuffer"
	ALIGN	4

|InsertInBuffer|
	mov	r2, r1
	mov	r1, r0
	mov	r0, #0x8a
	swi	0x20006
	movcc	r0, #0
	movcs	r0, #1
	movs	pc, lr



	EXPORT	|WaitForVSync|
	=	"WaitForVSync"
	ALIGN	4

|WaitForVSync|
	mov	r0, #0x13
	swi	0x20006
	movs	pc, lr



	EXPORT	|HomeCursor|
	=	"HomeCursor"
	ALIGN	4

|HomeCursor|
	swi	0x11e			; VDU 30
	movs	pc, lr



	EXPORT	|ReadMouseState|
	=	"ReadMouseState"
	ALIGN	4

|ReadMouseState|
	str	r4, [sp, #-4]!
	mov	r4, r0
	swi	0x2001c			; XOS_Mouse
	stmia	r4, {r0-r3}
	ldr	r4, [sp], #4
	movs	pc, lr



	EXPORT	|PutMouseAt|
	=	"PutMouseAt"
	ALIGN	4

|PutMouseAt|
	mov	r2, #3
	orr	r2, r2, r0, lsl #8
	bic	r2, r2, #0xff000000
	orr	r2, r2, r1, lsl #0x18
	mov	r3, r1, lsr #8
	stmdb	sp!, {r2, r3}
	mov	r0, #0x15
	mov	r1, sp
	swi	0x20007
	add	sp, sp, #8
	movs	pc, lr



	EXPORT	|ReadProcessorRegisters|
	=	"ReadProcessorRegisters"
	ALIGN	4

|ReadProcessorRegisters|		; write current registers into kernel_unwind block
	stmia	r0, {r4-r9}
	str	fp, [r0, #24]
	str	sp, [r0, #28]
	str	lr, [r0, #32]		; use lr instead of pc! we want pc of caller.
	str	sl, [r0, #36]
	movs	pc, lr



	EXPORT	|ReadExceptionRegisters|
	=	"ReadExceptionRegisters"
	ALIGN	4

|ReadExceptionRegisters|		; read registers as stored by the
					; C runtime exception handler
	STMFD	sp!,{r14}
	MOV	r0,#7
	MOV	r1,#0
	MOV	r2,#0
	MOV	r3,#0
	SWI	&20040 ; XOS_ChangeEnvironment;
	MOVVS	r0,#0
	MOVVC	r0,r3
	LDMFD	sp!,{pc}



	EXPORT	|WimpReadSlotSize|
	=	"WimpReadSlotSize"
	ALIGN	4

|WimpReadSlotSize|
	str	r4, [sp, #-4]!
	mvn	r0, #0
	mvn	r1, #0
	swi	0x400ec
	ldr	r4, [sp], #4
	movs	pc, lr






	; WAD decompression code

; local vars
local_inbuff	EQU	0x00
local_insize	EQU	0x04
local_upper	EQU	0x08
local_slwm	EQU	0x0c
local_segsize	EQU	0x10
; on stack anyway
local_file	EQU	local_segsize + 0x28
local_csize	EQU	local_segsize + 0x2c


	IMPORT	|fread|
	EXPORT	|UncompressLump00|
	=	"UncompressLump00"
	ALIGN	4

|UncompressLump00|		; r0 = inBuff, r1 = inSize, r2 outBuff, r3 outSize
	stmdb	sp!, {r4-r12, lr}	; stacked: FILE *, compSize
	sub	sp, sp, #local_segsize
	str	r0, [sp, #local_inbuff]
	str	r1, [sp, #local_insize]
	str	r10, [sp, #local_slwm]	; save stack low water mark for refill code!
	mov	r12, r2
	add	r11, r12, r3
	str	r11, [sp, #local_upper]
	mov	r3, #0		; no valid bits in r2
	bl	|Uncomp00refill|
	and	r10, r2, #0x1f	; r10 literal bit length
	mov	r2, r2, lsr #5
	and	r9, r2, #0x1f	; r9 reference bit length
	mov	r2, r2, lsr #5
	and	r8, r2, #0x1f	; r8 count bit length
	mov	r2, r2, lsr #5
	sub	r3, r3, #0x0f	; valid bits in r2
|Uncomp00Loop|
	cmp	r12, r11
	bcs	|Uncomp00Done|
	cmp	r3, #0
	bleq	|Uncomp00refillreg|
	tst	r2, #1
	mov	r2, r2, lsr #1
	sub	r3, r3, #1
	bne	|Uncomp00repeat|
|Uncomp00literals|
	mov	r4, #0		; number
	mov	r5, #0		; shift
	mov	r7, #1
	mov	r7, r7, lsl r10
	sub	r7, r7, #1	; mask = (1<<len)-1
|Uncomp00litnum|
	mov	r6, r2
	cmp	r3, r10
	ble	|Uncomp00litrefill|
	add	lr, r10, #1
	mov	r2, r2, lsr lr
	sub	r3, r3, lr
|Uncomp00litjoin|
	and	lr, r6, r7
	orr	r4, r4, lr, lsl r5
	add	r5, r5, r10
	mov	r6, r6, lsr r10
	tst	r6, #1
	bne	|Uncomp00litnum|
|Uncomp00litcopy|
	cmp	r3, #8
	blt	|Uncomp00litcprefill|
	cmp	r3, #16
	blt	|Uncomp00litcpfull1|
	cmp	r3, #24
	blt	|Uncomp00litcpfull2|
|Uncomp00litcpfull3|
	strb	r2, [r12], #1
	movs	r2, r2, lsr #8
	sub	r3, r3, #8
	subs	r4, r4, #1
	blt	|Uncomp00Loop|
|Uncomp00litcpfull2|
	strb	r2, [r12], #1
	movs	r2, r2, lsr #8
	sub	r3, r3, #8
	subs	r4, r4, #1
	blt	|Uncomp00Loop|
|Uncomp00litcpfull1|
	strb	r2, [r12], #1
	mov	r2, r2, lsr #8
	sub	r3, r3, #8
	subs	r4, r4, #1
	blt	|Uncomp00Loop|
|Uncomp00litcprefill|
	mov	r5, r2
	bl	|Uncomp00refillreg|
	sub	lr, r3, #32
	orr	r5, r5, r2, lsl lr
	strb	r5, [r12], #1
	sub	r3, r3, #8
	rsb	lr, r3, #32
	mov	r2, r2, lsr lr
	subs	r4, r4, #1
	bge	|Uncomp00litcpfull3|
	b	|Uncomp00Loop|
|Uncomp00litrefill|
	bl	|Uncomp00refillreg|
	sub	lr, r3, #32	; number of valid bits before refilling
	orr	r6, r6, r2, lsl lr
	sub	r3, r3, r10
	sub	r3, r3, #1
	rsb	lr, r3, #32
	mov	r2, r2, lsr lr
	b	|Uncomp00litjoin|
|Uncomp00repeat|
	mov	r4, #0		; see literals
	mov	r5, #0
	mov	r7, #1
	mov	r7, r7, lsl r9
	sub	r7, r7, #1
|Uncomp00refnum|
	mov	r6, r2
	cmp	r3, r9
	ble	|Uncomp00refrefill|
	add	lr, r9, #1
	mov	r2, r2, lsr lr
	sub	r3, r3, lr
|Uncomp00refjoin|
	and	lr, r6, r7
	orr	r4, r4, lr, lsl r5
	add	r5, r5, r9
	mov	r6, r6, lsr r9
	tst	r6, #1
	bne	|Uncomp00refnum|
	mov	r11, #0
	mov	r5, #0
	mov	r7, #1
	mov	r7, r7, lsl r8
	sub	r7, r7, #1
|Uncomp00countnum|
	mov	r6, r2
	cmp	r3, r8
	ble	|Uncomp00countrefill|
	add	lr, r8, #1
	mov	r2, r2, lsr lr
	sub	r3, r3, lr
|Uncomp00countjoin|
	and	lr, r6, r7
	orr	r11, r11, lr, lsl r5
	add	r5, r5, r8
	mov	r6, r6, lsr r8
	tst	r6, #1
	bne	|Uncomp00countnum|
	sub	r4, r12, r4
	sub	r4, r4, #1
	subs	r5, r11, #1		; (+MINIMUM_REPEATS - 4)
	ldr	r11, [sp, #local_upper]	; restore upper output boundary
	blt	|Uncomp00repeatsmall|
|Uncomp00repeatloop|
	ldrb	lr, [r4], #1
	strb	lr, [r12], #1
	ldrb	lr, [r4], #1
	strb	lr, [r12], #1
	ldrb	lr, [r4], #1
	strb	lr, [r12], #1
	ldrb	lr, [r4], #1
	strb	lr, [r12], #1
	subs	r5, r5, #4
	bge	|Uncomp00repeatloop|
|Uncomp00repeatsmall|
	adds	r5, r5, #4
	ble	|Uncomp00Loop|
	ldrb	lr, [r4], #1
	strb	lr, [r12], #1
	subs	r5, r5, #1
	ble	|Uncomp00Loop|
	ldrb	lr, [r4], #1
	strb	lr, [r12], #1
	subs	r5, r5, #1
	ble	|Uncomp00Loop|
	ldrb	lr, [r4], #1
	strb	lr, [r12], #1
	b	|Uncomp00Loop|
|Uncomp00refrefill|
	bl	|Uncomp00refillreg|
	sub	lr, r3, #32
	orr	r6, r6, r2, lsl lr
	sub	r3, r3, r9
	sub	r3, r3, #1
	rsb	lr, r3, #32
	mov	r2, r2, lsr lr
	b	|Uncomp00refjoin|
|Uncomp00countrefill|
	bl	|Uncomp00refillreg|
	sub	lr, r3, #32
	orr	r6, r6, r2, lsl lr
	sub	r3, r3, r8
	sub	r3, r3, #1
	rsb	lr, r3, #32
	mov	r2, r2, lsr lr
	b	|Uncomp00countjoin|
|Uncomp00Done|
	mov	r0, #0
|Uncomp00Exit|
	add	sp, sp, #local_segsize
	ldmia	sp!, {r4-r12, pc}^

|Uncomp00refillreg|
	cmp	r0, r1
	ldrcc	r2, [r0], #4
	addcc	r3, r3, #32
	movccs	pc, lr
|Uncomp00refill|
	ldr	r0, [sp, #local_csize]
	cmp	r0, #0
	mvnle	r0, #0
	ble	|Uncomp00Exit|
	ldr	r1, [sp, #local_insize]
	cmp	r1, r0
	movge	r2, r0
	movlt	r2, r1
	sub	r0, r0, r2
	str	r0, [sp, #local_csize]
	ldr	r0, [sp, #local_inbuff]
	stmdb	sp!, {r3, r10, r11, r12, lr}
	ldr	r3, [sp, #(local_file+0x14)]
	ldr	r10, [sp, #(local_slwm+0x14)]
	mov	r1, #1
	bl	|fread|		; fread(inbuff, 1, min(inSize, compSize), file)
	ldr	r2, [sp, #(local_inbuff+0x14)]
	add	r1, r2, r0
	mov	r0, r2
	ldr	r2, [r0], #4
	ldmia	sp!, {r3, r10, r11, r12, lr}
	add	r3, r3, #32
	movs	pc, lr



	END
