;Entry_ADFBootFloppy
;-------------------
;Simulates a Shift-Break soft-reset
;
;Entry:
; R0 - Command tail
; R12 - pointer to module private word OR undefined

 .Entry_ADFBootFloppy_CSD	DCB "DIR "
 .Entry_ADFBootFloppy_URD	DCB "adfs::0.$", 0
 .Entry_ADFBootFloppy_ObeyRun	DCB "Obey -c "
 .Entry_ADFBootFloppy_Obey	DCB "ADFFS:!Obey", 0
				DCB "F"
 .Entry_ADFBootFloppy_Fno	DCB "12345"
 .Entry_ADFBootFloppy_Fdsk	DCB "67", 0
				ALIGN

.Entry_ADFBootFloppy
 STMFD   R13!, {R1-R5, R12, R14}
 ADR     R12, VARS			;could be called via CallBack from
					;service._Entry_ADFBootFloppyCB
 #if ZLib_RMASpace > 0
  MVN     R0, #0
  BL      Entry_RMAFree			;increase RMA for ZLib
 #endif

 MOV     R0, #0				;get number of WIMP tasks
 SWI     XWimp_ReadSysInfo		;PRM3-216
 TEQ     R0, #0				;R0>0 if WIMP is active
 BNE     _leave_time

 SWI     XOS_ReadMonotonicTime		;reset MonotonicTime
 LDR     R2, [R12, #MonotonicTime - VARS]	;get the current offset
 ADD     R0, R0, R2			;add it to the current result
 STR     R0, [R12, #MonotonicTime - VARS]	;and store it back
 ._leave_time
 ADR     R3, JFD_tmp			;JFD header
 LDR     R0, [R3, #JFD_ID]		;JFD Fxxxxxx
 ADR     R1, Entry_ADFBootFloppy_Fno	;buffer address
 MOV     R2, #7				;length of buffer
 SWI     XOS_ConvertCardinal4		;PRM1-483

 LDR     R0, [R3, #JFD_Sequence]	;JFD floppy no
 AND     R0, R0, #&FF			;mask down to <99
 CMP     R0, #10
 MOVLT   R2, #ASC("0")			;pad with 0 if necessary
 STRLTB  R2, [R1], #1
 MOV     R2, #2				;length of buffer
 SWI     XOS_ConvertCardinal1

 BL      _extractObey			;does ADFFS:Obey.Fxxxxxnn exist?
 BVC     _RunExtractedFile		;YES
 TEQ     R0, #0				;was there an error?
 BNE     _exit				;YES

 LDR     R4, [R12, #obey_file_offset - VARS]	;offset to Obey file
 TEQ     R4, #0				;is there an Obey file?
 BNE     _ADFRunObeyFile		;YES, run it

					;*********************************
					;setup boot environment
					;*********************************
#if compile_RO == 400
  MOV     R0, #0
  BL      Entry_ADFScreenCaching	;turn screen caching off for RO4/SA
#endif

 MOV     R0, #14			;select ADFS
 MOV     R1, #8				;PRM2-21
 SWI     XOS_FSControl			;PRM2-98

 ADR     R0, Entry_ADFBootFloppy_CSD	;set CSD
 SWI     XOS_CLI

 MOV     R0, #39			;set User Root Directory
 ADR     R1, Entry_ADFBootFloppy_URD
 SWI     XOS_FSControl			;PRM2-124

 BL      _set_floppy_options

 MOV     R0, #47			;PRM2-132
 ADR     R1, Entry_ADFBootFloppy_URD
 SWI     XOS_FSControl			;check if the floppy is bootable
 CMP     R2, #2				;2/3 is Run/Exec
 BLO     _exit				;oops, no boot option

 MOV     R0, #15			;boot the filesystem
 SWI     XOS_FSControl			;PRM2-99
 BVS     _exit

 LDR     R0, [R12, #BootFloppyRequested - VARS]
 TEQ     R0, #0				;has the filer requested a floppy boot?
 MOVNE   R0, #138			;YES, need to workaround *EXEC not
 MOVNE   R1, #0				; | triggering via CallBack by..
 STRNE   R1, [R12, #BootFloppyRequested - VARS]	; |   eg Repton 3, Chuck Rock
 MOVNE   R2, #ASC(" ")			; | ..inserting a key into the keybuffer
 SWINE   XOS_Byte			;PRM1-172
					;*********************************
 ._exit
LDMFD   R13!, {R1-R5, R12, PC}


;Entry:
; R4 - offset to obey file in buffer

 ._ADFRunObeyFile
 ADR     R5, Entry_ADFBootFloppy_Obey	;our obey save location
 MOV     R1, R5				;filename
 MOV     R0, #&8F			;open for writing
 SWI     XOS_Find			;PRM2-78

 ADRVC   R2, JFD_tmp			;buffer address
 LDRVC   R3, [R2, #JFD_Obey_Length]	;length of Obey file
 LDRVC   R2, [R12, #ADF_Buffer_Address - VARS]
 ADDVC   R2, R2, R4			;address of Obey file
 MOVVC   R1, R0				;file handle
 MOVVC   R0, #2				;write from current pointer
 SWIVC   XOS_GBPB			;PRM2-68

 MOVVC   R0, #0
 SWIVC   XOS_Find			;close the file PRM2-77

 ._RunExtractedFile
 MOVVC   R0, #18			;set filetype
 MOVVC   R1, R5				;our filename
 MOVVC   R2, #&FEB			;FEB - Obey
 SWIVC   XOS_File			;PRM2-36

 ADRVC   R0, Entry_ADFBootFloppy_ObeyRun

 BVS     _exit
 BL      _set_floppy_options

 SWI     XOS_CLI			;run Obey file
B       _exit


 ._set_floppy_options
 STMFD   R13!, {R0-R1, R3-R6, R14}

 ADR     R1, JFD_tmp			;buffer address

 LDR     R0, [R1, #JFD_MinVersion]
 CMP     R0, #206			;2.06+ images have these values
 LDMLOFD R13!, {R0-R1, R3-R6, PC}

 LDR     R0, [R1, #JFD_FPS]
 TEQ     R0, #0				;do we have a FPS?
 BLNE    _set_FPS			;YES, set it

 MOV     R4, #0
 LDR     R0, [R1, #JFD_Bit_Flags]

 LDR     R3, [R12, #prevent_CMOSchanges - VARS]
 CMN     R3, #1				;has it been manually set?
 BEQ     _P2				;YES
 TST     R0, #JFD_BF_ProtectCMOS	;do we need to protect the CMOS?
 STREQ   R4, [R12, #prevent_CMOSchanges - VARS]	;NO
 STRNE   R0, [R12, #prevent_CMOSchanges - VARS]	;YES
 ._P2

 LDR     R3, [R12, #prevent_RMKills - VARS]
 CMN     R3, #1				;has it been manually set?
 BEQ     _P3				;YES
 TST     R0, #JFD_BF_ProtectModules	;do we need to protect modules?
 STREQ   R4, [R12, #prevent_RMKills - VARS]	;NO
 STRNE   R0, [R12, #prevent_RMKills - VARS]	;YES
 ._P3

 LDR     R3, [R12, #prevent_Hourglass - VARS]
 CMN     R3, #1				;has it been manually set?
 BEQ     _P4				;YES
 TST     R0, #JFD_BF_HideHourglass	;do we need to hide the hourglass?
 STREQ   R4, [R12, #prevent_Hourglass - VARS]	;NO
 BEQ     _P4
 LDR     R3, [R12, #prevent_Hourglass - VARS]	;YES, get previous value
 STR     R0, [R12, #prevent_Hourglass - VARS]	; |  turn off
 TEQ     R3, #0				; |  was hourglass previously on?
 SWIEQ   XHourglass_Off			; +- YES, turn hourglass off PRM2-748
 ._P4
 LDMFD   R13!, {R0-R1, R3-R6, PC}




;_extractObey
;-----------
;Looks for a suitable boot file in <ADFFS$Dir>.Obey and extracts it

;Exit:
;  V set if file not found
;  if file found:
;    V clear
;    R1 - file handle
;    R5 - filename

._extractObey
 STMFD   R13!, {R1-R12, R14}

 ADR     R1, _obeyzip			;filename
 MOV     R0, #&4F			;open read only
 SWI     XOS_Find			;PRM2-78
 MOVVS   R0, #0				;don't return an error
 LDMVSFD R13!, {R1-R12, PC}		;file not found
 MOV     R11, R0			;R11=file handle
 MOV     R10, #0			;R10=current file pointer
 MOV     R12, #0			;R12=pointer to memory block

 ._L1
   BL      _get32			;get header
   EORS    R0, R0, #&04034B50		;ZIP file header?
   BNE     _file_not_found		;NO, file not found

   MOV     R0, #2+2+2+2+2+4
   BL      _skip			;skip to compressed size

   BL      _get32
   MOV     R6, R0			;R6=compressed size

   BL      _get32
   MOV     R7, R0			;R7=uncompressed size

   ADD     R3, R6, R7			;space required to extract
   ADD     R3, R3, #56 + 7		;add some extra space for stream block
   BIC     R3, R3, #3			;align
   MOV     R0, #Module_Claim		;claim space
   SWI     XOS_Module			;PRM1-237
   BVS     _file_not_found		;claim failed
   MOV     R12, R2			;R12=pointer to space

   BL      _get16
   MOV     R8, R0			;R8=filename size

   BL      _get16
   MOV     R9, R0			;R9=extra field length

   MOV     R0, #4			;read from current pointer
   MOV     R1, R11			;file handle
   MOV     R2, R12			;use allocated space for data
   MOV     R3, R8			;read the filename
   SWI     XOS_GBPB			;PRM2-69
   MOV     R10, R4			;update file pointer

   MOV     R0, R9
   BL      _skip			;skip the extra field

   ADR     R5, Entry_ADFBootFloppy_Fno - 1	;pointer to F10xxxyy filename
   MOV     R4, R12				;ZIP filename
   MOV     R3, R8			;length of filename
   ._L2
     LDRB    R0, [R5], #1
     LDRB    R1, [R4], #1
     BIC     R0, R0, #32
     BIC     R1, R1, #32		;ignore case
     TEQ     R0, R1			;chars match?
     BNE     _wrong_file		;NO
     SUBS    R3, R3, #1			;last char?
   BNE     _L2				;NO

   LDRB    R0, [R5], #1
   TEQ     R0, #0			;does the string match?
   BNE     _wrong_file

   MOV     R0, #4			;read from current pointer
   MOV     R1, R11			;file handle
   ADD     R2, R12, #56			;use allocated space for data
   MOV     R3, R6			;read the compressed stream
   SWI     XOS_GBPB			;PRM2-69
   MOV     R10, R4			;update file pointer

   B       _expand_obey

   ._wrong_file
   MOV     R2, R12			;free allocated space
   MOV     R0, #Module_Free
   SWI     XOS_Module			;PRM1-238
   MOV     R12, #0

   MOV     R0, R6
   BL      _skip			;skip the compessed stream
 B       _L1


 ._expand_obey
 MOV     R1, #56 - 4			;clear streamCB
 MOV     R0, #0
 ._L3
   STR     R0, [R12, R1]
   SUBS    R1, R1, #4
 BNE     _L3

 ADD     R0, R12, #56
 STR     R0, [R12, #0]			;pointer to compressed stream

 STR     R6, [R12, #4]			;compressed size
 STR     R7, [R12, #16]			;uncompressed size

 ADD     R9, R0, R6			;R9=pointer to uncompressed data
 STR     R9, [R12, #12]

 SWI     XZLib_Version			;get the ZLib version string
 MOV     R2, R0
 MOV     R0, R12
 MOV     R1, #-15
 MOV     R3, #56
 SWI     XZLib_InflateInit2		;initialise streamCB
 TEQ     R0, #0				;did init work?
 BNE     _extract_failed		;NO

 MOV     R0, R12
 MOV     R1, #4				;Z_FINISH
 SWI     XZLib_Inflate			;inflate the compressed stream
 MOV     R1, R0				;store the return code

 MOV     R0, R12
 SWI     XZLib_InflateEnd		;clear down ZLib
 TEQ     R1, #0				;did inflate work?
 TEQNE   R1, #1
 BNE     _extract_failed		;NO

 ADR     R5, Entry_ADFBootFloppy_Obey	;our obey save location
 MOV     R1, R5				;filename
 MOV     R0, #&8F			;open for writing
 SWI     XOS_Find			;PRM2-78
 TEQ     R0, #0				;did we create the file?
 BEQ     _extract_failed		;NO

 STR     R0, [R13, #0 * 4]		;return file handle
 STR     R5, [R13, #4 * 4]		;return filename

 MOV     R2, R9				;buffer address
 MOV     R3, R7				;length of Obey file
 MOV     R1, R0				;file handle
 MOV     R0, #2				;write from current pointer
 SWI     XOS_GBPB			;PRM2-68

 MOV     R0, #0
 SWI     XOS_Find			;close the file

 TEQ     R3, #0				;did the write succeed?
 BNE     _extract_failed
 BL      _close_down

 SUBS    R0, R0, R0			;clear V
 LDMFD   R13!, {R1-R12, PC}		;clear down stack


 ._extract_failed
 BL      _close_down

 MOV     R0, #1<<31
 ADDS    R0, R0, R0			;set V and return R0=error
 ADR     R0, Error_ExtractFailed
 LDMFD   R13!, {R1-R12, PC}		;file not found

 ._file_not_found
 BL      _close_down

 MOV     R0, #1<<31
 ADDS    R0, R0, R0			;set V and return R0=0
 LDMFD   R13!, {R1-R12, PC}		;file not found


 ._close_down
 STR     R14, [R13, #-4]!
 MOV     R0, #0
 MOV     R1, R11
 SWI     XOS_Find			;close ADFFS:Obey

 MOVS    R2, R12			;did we allocate any space
 MOVNE   R0, #Module_Free		;YES,
 SWINE   XOS_Module			; |+  free allocation
 LDR     PC, [R13], #4

 ._obeyzip	DCB "ADFFS:Obey", 0
 ALIGN


;_get8
;------
;read a bytes

 ._get8
 MOV     R3, #1				;read BYTE
 B       _read_data

;_get16
;------
;read two bytes

 ._get16
 MOV     R3, #2				;read WORD
 B       _read_data

;_get32
;------
;read four bytes

 ._get32
 MOV     R3, #4				;read DWORD

 ._read_data
 MOV     R0, #0
 STMFD   R13!, {R0, R14}

 MOV     R0, #4				;read from current pointer
 MOV     R1, R11			;file handle
 MOV     R2, R13			;use stack for data
 SWI     XOS_GBPB			;PRM2-69
 MOV     R10, R4			;update file pointer

 LDMFD   R13!, {R0, PC}


;_skip
;-----
;increase file pointer

 ._skip
 STR     R14, [R13, #-4]!
 ADD     R2, R0, R10			;new file pointer
 MOV     R10, R2
 MOV     R0, #1
 MOV     R1, R11			;file handle
 SWI     XOS_Args			;PRM2-52
 LDR     PC, [R13], #4




 ._set_FPS
 MOV     R6, #200			;100 * 2ms (the FPS in JFD is doubled)
 TEMP    R3
 DIV     R5, R6, R0			;R5 = ms to wait
 LOCK    R3
 STR     R5, [R12, #force_vsync - VARS]	;set the forced FPS
MOV     PC, R14
