#set HFEv3_NOP		= &F0
#set HFEv3_INDEX	= &F1
#set HFEv3_BITRATE	= &F2
#set HFEv3_SKIP		= &F3
#set HFEv3_RAND		= &F4
#set HFEv3_RESERVED	= &FF

#set debug_HFE = 0
#set debug_1772 = 0


;Entry:
; R12 - pointer to VARS

.Entry_ADFMount_HFE			;read HFE
 MOV     R4, #64 * 1024			;start with a 64KB buffer, extend as required
 BL      MemAlloc			;Allocate memory
 BLVC    init_crc_ccitt
 MOVVS   R2, #0				;if an error occurred, zero address
 MOVVS   R4, #0

 LDRVC   R2, [R12, #DA_address - VARS]	;increase start of buffer
 MOVVC   R3, #APD_Track_Buffer
 ADDVC   R1, R2, R3			;by size of APD track buffer
 STRVC   R1, [R12, #ADF_Buffer_Address - VARS]
 ADDVC   R4, R2, #Max_Track_Count * 4
 STR     R2, [R12, #JFD_Tracks - VARS]
 STR     R4, [R12, #JFD_Sectors - VARS]
 BVS     Entry_ADFMount_Exit		;exit on error

 BL      clear_track_sector_table

 MOV     R1, R11			;filename
 MOV     R0, #&4F			;open read only
 SWI     XOS_Find			;PRM2-78
 STR     R0, [R12, #File_Handle - VARS]	;store file handle for later

 BL      HFE_Read_File
 STMFD   R13!, {R0}			;store any error
 MOV     R0, #0				;close file
 LDR     R1, [R12, #File_Handle - VARS]
 STR     R0, [R12, #File_Handle - VARS]
 SWI     XOS_Find			;close the file PRM2-77
 LDMFD   R13!, {R0}
 TEQ     R0, #0
 BNE     Entry_ADFMount_Exit		;exit on error

 ADD     R1, R12, #JFD_tmp - VARS	;buffer address
 LDR     R2, [R12, #DA_address - VARS]
 LDR     R3, [R12, #JFD_Tracks - VARS]
 SUB     R0, R3, R2			;offset to Track table
 ADD     R0, R0, #JFD_Header
 STR     R0, [R1, #JFD_Track_Table]
 LDR     R3, [R12, #JFD_Sectors - VARS]
 SUB     R5, R3, R2
 ADD     R5, R5, #JFD_Header
 STR     R5, [R1, #JFD_Sector_Table]	;offset to Sector table
 MOV     R4, #APD_Track_Buffer
 ADD     R4, R4, #JFD_Header
 STR     R4, [R1, #JFD_Data]		;offset to data
 LDR     R5, [R12, #DA_size - VARS]
 STR     R5, [R1, #JFD_Size]		;memory required to load
 SUB     R0, R4, R0			;R7 = size of Track+Sector table
 STR     R0, [R12, #JFD_TrackSector_size - VARS]	;store so we can expand if required

 MOV     R2, #Type_HFE
 BL      floppy_type_changed

 MOV     R0, #0				;no error
B       Entry_ADFMount_mounted




;HFE_Read_File
;-------------
;Read HFE file read only
;
;Entry:
; R0 - pointer to filename
; R12 - pointer to VARS

.HFE_Read_File
 STMFD   R13!, {R1-R5, R11, R14}

 MOV     R0, #Module_Claim		;claim space for HFE header
 MOV     R3, #1024+32			;amount to claim
 SWI     XOS_Module			;PRM1-237
;### needs error code
 LDMVSFD R13!, {R1-R5, R11, PC}
 STR     R2, [R12, #tmp_Header - VARS]	;store address

 MOV     R0, #4
 LDR     R1, [R12, #File_Handle - VARS]	;file handle
 MOV     R3, #26			;bytes to read
 SWI     XOS_GBPB			;read the HFE header
 BVS     _exit

 LDR     R2, [R12, #tmp_Header - VARS]

 LDRB    R5, [R2, #3]			;HXC_   HXCP=v1/v2	HXCH=v3
 TEQ     R5, #ASC("H")			;v3
 LDRB    R5, [R2, #8]
 ADDEQ   R5, R5, #2			;increase to as v3 strangly resets this to zero
 STREQB  R5, [R2, #8]
 CMP     R5, #2				;0=v1 1=v2 2=v3
 ADRHI   R0, Error_GreaseWeazle		;error if its a version we don't support
 MOVHI   R5, #1 << 31
 ADDHIS  R5, R5, R5
 BVS     _exit

 ADD     R5, R5, #ASC("1")
 STRB    R5, [R12, #FileType_Loaded+4 - VARS]
 MOV     R5, #ASC("v")
 STRB    R5, [R12, #FileType_Loaded+3 - VARS]

 LDRB    R5, [R2, #9]			;R5=track counter / assume 2 heads
 MOV     R3, R5, LSL #2			;track table size in bytes
 SUB     R5, R5, #1
 MOV     R5, R5, LSL #1			;double as sides are interleaved
 LDR     R4, [R2, #16]
 MOV     R4, R4, LSR #16		;R4=track list offset/512
 MOV     R4, R4, LSL #9			;R4=byte offset of track table
 ADD     R2, R2, #32			;don't overwrite the header
 MOV     R0, #3
 SWI     XOS_GBPB			;read track table
 BVS     _exit

 LDR     R_buffer, [R12, #ADF_Buffer_Address - VARS]	;address we're writing too
 LDR     R_sectorinfo, [R12, #JFD_Sectors - VARS]	;sector table
 MOV     R2, #0				;track pointer
 ._L1
   RSB     R0, R5, #163			;YES
   MOV     R0, R0, LSR #1
   ADD     R0, R0, R5, LSR #3		;R0 = 100/160 * R5
   BL      hourglass_percentage

   LDR     R0, [R12, #tmp_Header - VARS]
   ADD     R0, R0, #32
   LDR     R0, [R0, R5, LSL #1]		;<offset><length>
   MOVS    R3, R0, LSR #17		;R3=length/2
   MOV     R2, R0, LSL #16
   MOV     R2, R2, LSR #16-9		;R2=file offset for track

   LDR     R0, [R12, #JFD_Tracks - VARS]	;pointer to track table
   LDR     R14, [R12, #JFD_Sectors - VARS]	;sector table
   SUB     R14, R_sectorinfo, R14	;ptr to start of track in sector table
   STR     R14, [R0, R5, LSL #2]	;store track start pointer
					;*****************************
#if debug_HFE == 1
MOV R1, R5
BL outputHexTruncated
SWI &100+ASC(":")
MOV R1, R2
BL outputHexTruncated
SWI &100+ASC("+")
MOV R1, R3
BL outputHexTruncated
SWI &100+ASC(" ")
#endif
   TEQ     R3, #0
   CMNNE   R3, #1
   MOVNE   R0, R3			;bytes to read
   MOVEQ   R0, #0

   STMFD   R13!, {R0, R14, R_curbit, R_nextbit, R_bitrot, R_bitsleft}
   TEQ     R0, #0
   BEQ     _Unformatted0		;if length is 0, its unformatted
   BL      HFE_Read_Track
   LDMVSFD R13!, {R0, R14, R_curbit, R_nextbit, R_bitrot, R_bitsleft}
   BVS     _exit

   LDR     R14, [R12, #MFM_Stream_Pos - VARS]
   STMIB   R13, {R14, R_curbit, R_nextbit, R_bitrot, R_bitsleft}
#if debug_HFE == 1
SWI XOS_WriteS
DCB "FM-",0
ALIGN
#endif
   MOV     R1, #1			;FileCore for SD
   BL      decodeFM			;decode FM data
#if debug_HFE == 1
SWI XOS_WriteS
DCB "MFM-",0
ALIGN
#endif
   LDMFD   R13, {R0, R14, R_curbit, R_nextbit, R_bitrot, R_bitsleft}
   STR     R14, [R12, #MFM_Stream_Pos - VARS]
   MOV     R1, #2			;FileCore for DD
   BL      decodeMFM			;decode MFM data
   ._Unformatted0

   LDR     R0, [R12, #JFD_Sectors - VARS]	;sector table
   SUB     R14, R_sectorinfo, R0	;get offset within table
   LDR     R0, [R12, #JFD_Tracks - VARS]	;track table
   LDR     R1, [R0, R5, LSL #2]		;load sector pointer of current track
   SUBS    R14, R14, R1			;did we find any sectors?
   MVN     R14, #0
   STREQ   R14, [R0, R5, LSL #2]	;NO, mark track as unformatted
   STRNE   R14, [R_sectorinfo], #4	;YES, terminate sector info
					;.. for this track
   ADD     R5, R5, #1			;go to side 1
   LDR     R0, [R12, #JFD_Tracks - VARS]	;pointer to track table
   LDR     R14, [R12, #JFD_Sectors - VARS]	;sector table
   SUB     R14, R_sectorinfo, R14	;ptr to start of track in sector table
   STR     R14, [R0, R5, LSL #2]	;store track start pointer
					;*****************************

   LDMFD   R13, {R0, R14, R_curbit, R_nextbit, R_bitrot, R_bitsleft}
   STR     R14, [R12, #MFM_Stream_Pos - VARS]
   TEQ     R0, #0
   BEQ     _Unformatted1		;if length is 0, its unformatted
   ADD     R2, R2, #256			;side 1
   BL      HFE_Read_Track
   LDMVSFD R13!, {R0, R14, R_curbit, R_nextbit, R_bitrot, R_bitsleft}
   BVS     _exit
#if debug_HFE == 1
SWI XOS_WriteS
DCB "FM-",0
ALIGN
#endif
   MOV     R1, #1			;FileCore for SD
   BL      decodeFM			;decode FM data
#if debug_HFE == 1
SWI XOS_WriteS
DCB "MFM-",0
ALIGN
#endif
   LDMFD   R13, {R0, R14, R_curbit, R_nextbit, R_bitrot, R_bitsleft}
   STR     R14, [R12, #MFM_Stream_Pos - VARS]
   MOV     R1, #2			;FileCore for DD
   BL      decodeMFM			;decode MFM data

   ._Unformatted1
   LDMFD   R13!, {R0, R14, R_curbit, R_nextbit, R_bitrot, R_bitsleft}	;clear stack

   LDR     R0, [R12, #JFD_Sectors - VARS]	;sector table
   SUB     R14, R_sectorinfo, R0	;get offset within table
   LDR     R0, [R12, #JFD_Tracks - VARS]	;track table
   LDR     R1, [R0, R5, LSL #2]		;load sector pointer of current track
   SUBS    R14, R14, R1			;did we find any sectors?
   MVN     R14, #0
   STREQ   R14, [R0, R5, LSL #2]	;NO, mark track as unformatted
   STRNE   R14, [R_sectorinfo], #4	;YES, terminate sector info
					;.. for this track
#if debug_HFE == 1
SWI XOS_NewLine
#endif
   SUBS    R5, R5, #3			;increase track counter
 BPL     _L1

 BL      Reduce_DynamicArea		;hand back any unused memory
 MOV     R0, #0				;no error
 ._exit
 STMFD   R13!, {R0}			;preserve any error
 BL      free_temp_track
LDMFD   R13!, {R0-R5, R11, PC}




;HFE_Read_Track
;--------------
;Read one track into memory and pre-read the first two words
;
;Entry:
; R0 - number of bytes to read
; R2 - file position pointer
; R12 - pointer to VARS
;
;Exit:
; R_curbit  - 1st word of track
; R_nextbit - 2nd word of track
; R_bitrot  - 32
; R_bitsleft - size * 8

.HFE_Read_Track
 STMFD   R13!, {R0-R5, R14}

 BL      allocate_temp_track		;R4=file position pointer
 ADDVS   R13, R13, #4
 LDMVSFD R13!, {R1-R5, PC}
 MOV     R_curbit, R2			;R2 / R_curbit=buffer address
					;R3=stream size
					;R4=file position pointer
 LDR     R1, [R12, #File_Handle - VARS]	;file handle
 MOV     R5, R3
 ._L1
   MOV     R0, #3
   MOV     R3, R5
   CMP     R3, #256
   MOVHI   R3, #256
   SUB     R5, R5, R3
   SWI     XOS_GBPB			;read the track in
   ADDVS   R13, R13, #4
   LDMVSFD R13!, {R1-R5, PC}

   ADD     R4, R4, #256
   TEQ     R5, #0
 BNE     _L1

 MOV     R2, R_curbit
 LDR     R0, [R12, #tmp_Header - VARS]
 LDRB    R5, [R0, #8]		;R5= 0=v1  1=v2  2=v3
 LDR     R4, [R13, #0]		;get entry R0 from stack
 ADD     R4, R4, R2		;R4=end of buffer
 MOV     R1, R2			;R1=in buffer
 MOV     R_bitsleft, R2		;R_bitsleft=out buffer
 ._start_again
 MOV     R_curbit, #32		;bits in R0
 LDR     R_nextbit, [R1], #4
 MOV     R0, #0
 ._L2
   CMP     R1, R4		;end of buffer?
   BHS     _exit_L2
   AND     R0, R_nextbit, #&FF
   MOV     R_nextbit, R_nextbit, LSR #8
   SUB     R_curbit, R_curbit, #8
   ._L3
     LDRB    R14, [R1], #1
     ORR     R_nextbit, R_nextbit, R14, LSL R_curbit
     ADD     R_curbit, R_curbit, #8
     CMP     R_curbit, #32-8
   BLS     _L3
					;reverse the bit order
   MOV     R3, R0, ROR #4		;		4321 / 8765
   ORR     R3, R3, R3, LSR #24		;		43218765
   AND     R0, R3, #%11001100		; 43--87--
   AND     R3, R3, #%00110011		;		--21--65
   MOV     R0, R0, LSR #2		; --43--87
   ORR     R0, R0, R3, LSL #2		; 21436587
   AND     R3, R0, #%10101010		;		2-4-6-8-
   AND     R0, R0, #%01010101		; -1-3-5-7
   MOV     R0, R0, LSL #1		; 1-3-5-7-
   ORR     R0, R0, R3, LSR #1		;		12345678

   TEQ     R5, #0			;v1
   BEQ     _skip_opcodes		;YES, no opcodes

   TEQ     R5, #2			;v3 opcodes?
   BEQ     _opcodes_v3			;YES
   ._opcodes_v2				;NO, must be v2
   TEQ     R0, #0			;is it an opcode
   BNE     _skip_opcodes		;NO
   MOV     R_curbit, #8			;drop the next 3 bytes
   AND     R0, R_nextbit, #&FF		;R0=opcode
   MOV     R_nextbit, R_nextbit, LSR #8		;drop 1 byte
   AND     R14, R_nextbit, #&FF		;value
   MOV     R_nextbit, R_nextbit, LSR #16	;drop next 2 bytes
   TEQ     R0, #6			;BREAK
     SUBEQ   R1, R1, R2			;R1=offset
     ADDEQ   R1, R1, #511
     BICEQ   R1, R1, #511
     ADDEQ   R1, R1, R2			;next 512 byte block
     BEQ     _start_again
   TEQ     R0, #3			;DATA
     MOVEQ   R0, R14
     BEQ     _skip_opcodes
   TEQ     R0, #2			;RANDOM
     BEQ     _random
   B       _L2

   ._opcodes_v3
   AND     R14, R0, #&F0
   TEQ     R14, #&F0
   BNE     _skip_opcodes
   TEQ     R0, #HFEv3_NOP
   TEQNE   R0, #HFEv3_INDEX
   TEQNE   R0, #HFEv3_RESERVED
     BEQ     _L2
   TEQ     R0, #HFEv3_BITRATE
     MOVEQ   R_nextbit, R_nextbit, LSR #8	;drop next byte
     SUBEQ   R_curbit, R_curbit, #8
     BEQ     _L2
   TEQ     R0, #HFEv3_SKIP
     ANDEQ   R0, R_nextbit, #&FF
     ADDEQ   R0, R0, #8
     MOVEQ   R_nextbit, R_nextbit, LSR R0
     SUBEQ   R_curbit, R_curbit, R0		;drop bits
     BEQ     _L2
   TEQ     R0, #HFEv3_RAND
   ._random
     BLEQ    random_number_R0
   ._skip_opcodes

   STRB    R0, [R_bitsleft], #1
 B       _L2
 ._exit_L2

 SUB     R_bitsleft, R_bitsleft, R2
 MOV     R_bitsleft, R_bitsleft, LSL #3		;bits in buffer
 LDR     R0, [R2], #4				;load the first word
 BL      little_endian
 MOV     R_curbit, R0
 LDR     R0, [R2], #4				;load the next word
 BL      little_endian
 MOV     R_nextbit, R0
 STR     R2, [R12, #MFM_Stream_Pos - VARS]	;store updated pointer back

 MOV     R_bitrot, #32				;bits remaining in next word
LDMFD   R13!, {R0-R5, PC}
