;R1=value to output
.outputHex
 STMFD   R13!, {R0-R3, R14}

 MOV     R2, #28
 .outputHex_MainLoop
   MOV     R3 ,R1, LSR R2
   AND     R3, R3, #&F
   CMP     R3, #&A
   ADDHS   R0, R3, #ASC("A")-10
   ADDLO   R0, R3, #ASC("0")
   SWI     XOS_WriteC

   SUBS    R2, R2, #4
 BHS     outputHex_MainLoop
LDMFD   R13!, {R0-R3, PC}




;R1=value to output
.outputHexByte
 STMFD   R13!, {R0-R3, R14}
B       outputHex_MainLoop




;R1=value to output
.outputHexTruncated
 STMFD   R13!, {R0-R3, R14}

 MOVS    R2, R1
 BEQ     outputHex_MainLoop

 MOV     R2, #28
 ._L1
   MOVS    R3, R1, LSR R2
   SUBEQ   R2, R2, #4
 BEQ     _L1
B       outputHex_MainLoop



#if debug_Delta == 1
;R1=value to output
.outputDecimal
 STMFD   R13!, {R0-R8, R14}
 TEQ     R1, #0
 SWIEQ   &100+ASC("0")
 CMP     R1, #0
 LDMEQFD R13!, {R0-R8, PC}
 RSBMI   R0, R1, #0
 MOVPL   R0, R1

 MOV     R1, #0
 MOV     R4, R13
 SUB     R13, R13, #12
 MOV     R14, #12
 STRB    R1, [R4, #-1]!

 MOV     R8, #&19999999
 ._wd_loop
   MOV     R7, R0
   MOV     R1, R8

   MOV     R6, R0, LSR #16
   MOV     R3, R1, LSR #16
   BIC     R0, R0, R6, LSL #16
   BIC     R1, R1, R3, LSL #16
   MUL     R2, R0, R1
   MUL     R1, R6, R1
   MUL     R0, R3, R0
   MUL     R3, R6, R3
   ADDS    R0, R0, R1
   ADDCS   R3, R3, #1 << 16
   ADDS    R2, R2, R0, LSL #16
   ADC     R3, R3, R0, LSR #16

   SUB     R2, R7, R3, LSL #3
   SUB     R2, R2, R3, LSL #1

   CMP     R2, #9
   SUBHI   R2, R2, #10
   ADDHI   R3, R3, #1
   ADD     R1, R2, #ASC("0")
   STRB    R1, [R4, #-1]!

   SUBS    R14, R14, #1		;end of buffer?
   BEQ     _wd_loop2		;YES
   MOVS    R0, R3
 BNE     _wd_loop
 CMP     R2, #9
 MOVHI   R1, #ASC("1")
 STRHIB  R1, [R4, #-1]!

 ._wd_loop2
   LDRB    R0, [R4], #1
   TEQ     R0, #0
   SWINE   XOS_WriteC
 BNE     _wd_loop2

 ADD     R13, R13, #12
LDMFD   R13!, {R0-R8, PC}
#endif





#if use_overlay == 1 AND JIT_debug == 1
.create_debug_overlay
 STMFD   R13!, {R0-R9, R14}
 BL      destroy_debug_overlay
 LDR     R8, current_display_driver
 MOV     R8, R8, LSL #24		;R8=driver ID
 ADR     R0, debug_overlay_mode
 MOV     R1, #(320<<16)+(10*8)		;aspect ratio
 MOV     R2, #0				;scaling not required
 MOV     R3, #%1			;head mask - use head 0
 ORR     R4, R8, #20			;create overlay
 MOV     R9, #Vector_GraphicsV
 SWI     XOS_CallAVector		;PRM1-70  GraphicsV 20
 TEQ     R4, #0				;did the overlay get created?
 ORREQ   R8, R8, R0, LSL #16		;YES, R0=<driver><overlay><15..0 unset>
 STREQ   R8, debug_overlay_id		; |

 MOVEQ   R0, #0
 MOVEQ   R1, #0
 MOVEQ   R2, #debug_overlay_width*2	;right clip
 MOVEQ   R3, #debug_overlay_height*2	;bottom clip
 ORREQ   R4, R8, #27
 MOVEQ   R5, R2				;scaled width
 MOVEQ   R6, R3				;scaled height
 ORREQ   R7, R6, R5, LSL #16
 SWIEQ   XOS_CallAVector		;PRM1-70  GraphicsV 27

 TEQ     R4, #0
 BLEQ    map_debug_overlay_bank		; |+ and map the memory

LDMFD   R13!, {R0-R9, PC}


.map_debug_overlay_bank
 STMFD   R13!, {R14}
 LDR     R14, debug_overlay_address
 TEQ     R14, #0
 LDMNEFD R13!, {PC}

 STMFD   R13!, {R0-R4, R9}
 LDR     R8, debug_overlay_id
 MOV     R0, #0				; | bank#
 ORR     R4, R8, #23			; | map bank
 MOV     R9, #Vector_GraphicsV
 SWI     XOS_CallAVector		; | PRM1-70  GraphicsV 23
 TEQ     R4, #0				; | was the framebuffer mapped?
 LDMEQIA R0, {R3, R4}			; | YES
 STREQ   R3, debug_overlay_address	; | logical address
 STREQ   R4, debug_screen_1_line	; |+
LDMFD   R13!, {R0-R4, R9, PC}


.display_debug_overlay
 STMFD   R13!, {R0-R4, R8-R9, R14}
 LDR     R8, debug_overlay_id
 MOV     R9, #Vector_GraphicsV

 ADR     R0, debug_overlay_pos
 LDR     R14, debug_overlay_on
 AND     R1, R14, #1
 TEQ     R1, R14, LSR #31		;did the visibility state change?
 ORRNE   R14, R1, R1, LSL #31		;YES
 STRNE   R14, debug_overlay_on
 MOVNE   R2, #0				;bank
 ORRNE   R4, R8, #22			;set overlay position
 SWINE   XOS_CallAVector		;PRM1-70  GraphicsV 22
LDMFD   R13!, {R0-R4, R8-R9, PC}


.destroy_debug_overlay
 STMFD   R13!, {R4, R9, R14}
 LDR     R4, debug_overlay_id
 CMN     R4, #1
 LDMEQFD R13!, {R4, R9, PC}

 MOV     R9, #Vector_GraphicsV
 ORR     R4, R4, #21			;destroy overlay
 SWI     XOS_CallAVector		;PRM1-70  GraphicsV 21

 MOV     R4, #0
 STR     R4, debug_overlay_address
 MVN     R4, #0
 STR     R4, debug_overlay_id
LDMFD   R13!, {R4, R9, PC}


.debug_overlay_pos
 DCD	0,0,0		;debug overlay position onscreen

.debug_overlay_mode	;Mode Selector Block
 DCD	1	;flags
 #if JIT_debug == 1 AND use_overlay == 1 AND JIT_report_registers == 0
   #set debug_overlay_width  = 44*8
   #set debug_overlay_height = 10*8
 #endif
 #if JIT_debug == 1 AND use_overlay == 1 AND JIT_report_registers == 1
   #set debug_overlay_width  = (8*9)*8
   #set debug_overlay_height = 14*8
 #endif
 DCD	debug_overlay_width
 DCD	debug_overlay_height
 DCD	5	;log2bpp     3=8bpp 5=32bpp
 DCD	-1	;hz (-1 use any frame rate)
		;Mode Variable Numbers
 DCD	0	;0=ModeFlags
 DCD	0	;framebuffer format - 32bpp TBGR
 DCD	3	;3=NColour
 DCD	-1	;ncolour      -1=RGB
 DCD    13,1
 DCD	-1

 .debug_overlay_on	DCD 1
 .debug_overlay_id	DCD -1
 .debug_overlay_address	DCD 0
#endif
#if JIT_debug == 1
.debug_screen_addr	DCD 0		;offset from MEMC_Vinit of next CHR
.debug_screen_1_line	DCD 0
.debug_screen_1_CHR	DCD 8*4
.debug_screen_8_lines	DCD 0
.debug_screen_next_line	DCD 0
.debug_screen_next_CR	DCD 0

.debug_writeDecimal
 STMFD   R13!, {R2-R3, R5-R8, R14}
 MOV     R14, R1
 MRS     R5, CPSR
 CMP     R0, #0
 MOVEQ   R0, #ASC("0")
 BLEQ    our_XOS_WriteC
 BEQ     _wd_end

 MOV     R1, #0
 STRB    R1, [R4, #-1]!
 RSBMI   R0, R0, #0

 MOV     R8,     #&00000099
 ORR     R8, R8, #&00009900
 ORR     R8, R8, #&00990000
 ORR     R8, R8, #&19000000
 ._wd_loop
   MOV     R7, R0
   MOV     R1, R8

   MOV     R6, R0, LSR #16
   MOV     R3, R1, LSR #16
   BIC     R0, R0, R6, LSL #16
   BIC     R1, R1, R3, LSL #16
   MUL     R2, R0, R1
   MUL     R1, R6, R1
   MUL     R0, R3, R0
   MUL     R3, R6, R3
   ADDS    R0, R0, R1
   ADDCS   R3, R3, #1 << 16
   ADDS    R2, R2, R0, LSL #16
   ADC     R3, R3, R0, LSR #16

   SUB     R2, R7, R3, LSL #3
   SUB     R2, R2, R3, LSL #1

   CMP     R2, #9
   SUBHI   R2, R2, #10
   ADDHI   R3, R3, #1
   ADD     R1, R2, #ASC("0")
   STRB    R1, [R4, #-1]!

   SUBS    R14, R14, #1		;end of buffer?
   BEQ     _wd_loop2		;YES
   MOVS    R0, R3
 BNE     _wd_loop
 CMP     R2, #9
 MOVHI   R1, #ASC("1")
 STRHIB  R1, [R4, #-1]!

 ._wd_loop2
   LDRB    R0, [R4], #1
   TEQ     R0, #0
   BLNE    our_XOS_WriteC
 BNE     _wd_loop2

 ._wd_end
 MSR     CPSR_f, R5
LDMFD   R13!, {R2-R3, R5-R8, PC}




.debug_outputHex			;PRESERVES FLAGS
 STMFD   R13!, {R0-R4, R14}
 MRS     R4, CPSR

 MOV     R2, #28
 .debug_outputHex_MainLoop
   MOV     R3 ,R1, LSR R2
   AND     R3, R3, #&F
   CMP     R3, #&A
   ADDHS   R0, R3, #ASC("A")-10
   ADDLO   R0, R3, #ASC("0")
   BL      our_XOS_WriteC

   SUBS    R2, R2, #4
 BHS     debug_outputHex_MainLoop
 MSR     CPSR_f, R4
LDMFD   R13!, {R0-R4, PC}

.debug_outputHexByte
 STMFD   R13!, {R0-R4, R14}
 MRS     R4, CPSR
B       debug_outputHex_MainLoop




.debug_outputHexTruncated		;PRESERVES FLAGS
 STMFD   R13!, {R0-R4, R14}
 MRS     R4, CPSR

 MOVS    R2, R1
 BEQ     debug_outputHex_MainLoop

 MOV     R2, #28
 ._L1
   MOVS    R3, R1, LSR R2
   SUBEQ   R2, R2, #4
 BEQ     _L1
B       debug_outputHex_MainLoop




.our_VDU30
 STMFD   R13!, {R3-R5, R14}
 #if compile_IOMD == 1 AND JIT_debug == 1
   ADR     R3, vidc20_regs - (VIDC20_HCR << 2)
   LDR     R4, [R3, #VIDC20_HDSR << 2]
   LDR     R5, [R3, #VIDC20_HDER << 2]
   SUB     R4, R5, R4
   LDR     R3, current_screen_mode		;IOMD, use current bpp
   LDRB    R3, [R3, #6 * 4]			;R3 = bpp
   RSB     R14, R3, #3
   MOV     R4, R4, LSR R14			;R4 = bytes for 1 line
 #endif
 #if use_overlay == 0 AND compile_GPU == 1 AND JIT_debug == 1
   #if use_overlay == 0 AND compile_GPU == 1 AND use_EDID == 0 AND JIT_debug == 1
     LDR     R4, HAL_vidc_list + VIDC_Type3.hdisp
     ADD     R4, R4, #32 - 1			;screen is DIV 32 on Pi
     BIC     R4, R4, #32 - 1
   #endif					;R4 = screen width
   MOV     R3, #5				;Pi, use 32bpp
 #endif

 #if use_overlay <> 1 AND JIT_debug == 1
   MOV     R5, #1
   MOV     R5, R5, LSL R3			;R5 = bytes for 1 CHR
   STR     R5, debug_screen_1_CHR
   #if use_overlay <> 1 AND compile_GPU == 1 AND JIT_debug == 1
     MOV     R4, R4, LSL #2
   #endif
   STR     R4, debug_screen_1_line
 #endif
 #if use_overlay == 1 AND JIT_debug == 1
   LDR     R4, debug_screen_1_line
 #endif
 STR     R4, debug_screen_next_line
 MOV     R4, R4, LSL #3				;add 8 lines
 STR     R4, debug_screen_8_lines
 STR     R4, debug_screen_next_CR
 MOV     R3, #0
 STR     R3, debug_screen_addr			;0 moves to top/left of screen
 LDMFD   R13!, {R3-R5, PC}


#if JIT_debug == 1 AND use_overlay == 1
.our_VDU16
 STMFD   R13!, {R14}
 LDR     R0, debug_overlay_mode + 4		;width
 LDR     R11, debug_overlay_mode + 8		;height
 LDR     R12, debug_overlay_address
 TEQ     R12, #0				;does the overlay exist?
LDMFD   R13!, {PC}
#endif



.our_XOS_NewLine
 STMFD   R13!, {R3, R14}
 LDR     R3, debug_screen_next_CR
 LDR     R14, debug_screen_1_line
 STR     R3, debug_screen_addr
 ADD     R14, R3, R14
 STR     R14, debug_screen_next_line
 LDR     R14, debug_screen_8_lines
 ADD     R14, R3, R14
 STR     R14, debug_screen_next_CR
LDMFD   R13!, {R3, PC}




.our_XOS_WriteS
 STMFD   R13!, {R0-R2}

 MRS     R2, CPSR
 #if compile_RO > 311 AND compile_RO < 450 AND JIT_debug == 1
   BIC     R1, R14, #&FC000003		;26bit, clear flags
 #endif
 #if compile_RO > 400 AND JIT_debug == 1
   MOV     R1, R14
 #endif
 ._L1
   LDRB    R0, [R1], #1
   TEQ     R0, #0
   BLNE    our_XOS_WriteC
 BNE     _L1

 ADD     R14, R1, #%11
 BIC     R14, R14, #%11
 MSR     CPSR_f, R2
 LDMFD   R13!, {R0-R2}
MOV     PC, R14



;our_XOS_WriteN
;--------------
;print string at pointer
;
;Entry:
; R1 - pointer to string
; R2 - max string length

.our_XOS_WriteN
 STMFD   R13!, {R0-R3, R14}

 MRS     R3, CPSR
 ._L1
   SUBS    R2, R2, #1
   LDRPLB  R0, [R1], #1
   CMPPL   R0, #31
   BLPL    our_XOS_WriteC
 BPL     _L1

 MSR     CPSR_f, R3
LDMFD   R13!, {R0-R3, PC}




;our_XOS_WriteC
;--------------
;print a char direct to screen memory
;
;Entry:
; R0 - char

.our_XOS_WriteC						;PRESERVES FLAGS
 STMFD   R13!, {R0-R6, R14}
 MRS     R5, CPSR				;R5 = CPU flags

 LDR     R1, debug_screen_addr
 LDR     R14, debug_screen_1_CHR
 LDR     R3, debug_screen_next_line
 ADD     R2, R1, R14
 CMP     R2, R3
 STRNE   R2, debug_screen_addr
 BLEQ    our_XOS_NewLine

 #if compile_IOMD == 1 AND JIT_debug == 1
   LDR     R2, MEMC_Vinit			;IOMD, and below use DA2
   CMP     R2, #&1F00000			;double check its valid
   BHI     _good
   MSR     CPSR_f, R5
   LDMFD   R13!, {R0-R6, PC}
   ._good
 #endif
 #if compile_GPU == 1 AND use_overlay == 0 AND JIT_debug == 1
   LDR     R4, current_GPU_bank
   ADR     R2, logical_VDU_start		;Pi, use GPU buffer
   LDR     R2, [R2, R4, LSL #2]
 #endif
 #if use_overlay == 1 AND compile_GPU == 1 AND JIT_debug == 1
   LDR     R2, debug_overlay_address
 #endif
 #if compile_GPU == 1 AND JIT_debug == 1
   TEQ     R2, #0				;is the address set?
   LDMEQFD R13!, {R0-R6, PC}			;NO, exit
 #endif
 ADD     R1, R1, R2				;R1 = screen address

 SUB     R0, R0, #ASC(" ")			;go to char in table (CHR * 8)
 ADR     R2, charSet
 ADD     R2, R2, R0, LSL #3			;R2 = CHR

 LDR     R4, debug_screen_1_line		;R4 = bytes for 1 line

 MOV     R14, #8				;R14 = vloop

 #if compile_IOMD == 1 AND JIT_debug == 1
   LDR     R3, current_screen_mode		;IOMD, use current bpp
   LDRB    R3, [R3, #6 * 4]			;R3 = bpp

   CMP     R3, #2
   BHI     _8bpp
   BEQ     _4bpp
   TEQ     R3, #0
   BNE     _2bpp

  ._1bpp
     LDRB    R0, [R2], #1
     STRB    R0, [R1], R4
     SUBS    R14, R14, #1
   BNE     _1bpp

  ._2bpp
   MSR     CPSR_f, R5
  LDMFD   R13!, {R0-R6, PC}


  ._4bpp
     LDRB    R0, [R2], #1
     MOV     R0, R0, LSL #23
     MOV     R3, #3
     ._4bpp_L1
       MOVS    R0, R0, LSL #2			;shift to top bit
       MOVCS   R6, #&70
       MOVCC   R6, #0
       ORRMI   R6, R6, #&07

       STRB    R6, [R1, R3]
       SUBS    R3, R3, #1
     BPL     _4bpp_L1
     ADD     R1, R1, R4
     SUBS    R14, R14, #1
   BNE     _4bpp

   MSR     CPSR_f, R5
  LDMFD   R13!, {R0-R6, PC}


  ._8bpp
     LDRB    R0, [R2], #1
     MOV     R0, R0, LSL #23
     MOV     R3, #7
     ._8bpp_L1
       MOV     R0, R0, LSL #1			;shift to top bit
       MOVS    R6, R0, ASR #31
;       #if debug_overlay == 1 AND compile_DEBUG == 1
;         STRNEB   R6, [R1, R3]
;       #endif
;       #if debug_overlay == 0 AND compile_DEBUG == 1
         STRB    R6, [R1, R3]
;       #endif
       SUBS    R3, R3, #1
     BPL     _8bpp_L1
     ADD     R1, R1, R4
     SUBS    R14, R14, #1
   BNE     _8bpp

   MSR     CPSR_f, R5
  LDMFD   R13!, {R0-R6, PC}
 #endif

 #if compile_GPU == 1 AND JIT_debug == 1
  ._32bpp
     LDRB    R0, [R2], #1
     MOV     R0, R0, LSL #23
     MOV     R3, #7 * 4
     ._32bpp_L1
       MOV     R0, R0, LSL #1			;shift to top bit
       MOV     R6, R0, ASR #31
       MOVS    R6, R6, LSR #8			;00BBGGRR
       #if debug_overlay == 1 AND compile_GPU == 1 AND JIT_debug == 1
         STRNE   R6, [R1, R3]
       #endif
       #if debug_overlay == 0 AND compile_GPU == 1 AND JIT_debug == 1
         STR     R6, [R1, R3]
       #endif
       SUBS    R3, R3, #4
     BPL     _32bpp_L1
     ADD     R1, R1, R4
     SUBS    R14, R14, #1
   BNE     _32bpp

   MSR     CPSR_f, R5
  LDMFD   R13!, {R0-R6, PC}
 #endif

.charSet
INCBIN "<Tmp$Dir>.debug.font"
ALIGN
#endif
