;
; ebc.asm test application
;-------------------------
;
; This program displays EFI_SYSTEM_TABLE_SIGNATURE, then waits
; for ESC key press to exit.
;
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

include 'ebc.asm'

      image efi application


section '.text' code readable executable

display_message:

      movnw r5, @r1(EFI_SYSTEM_TABLE.ConOut)
      pushn r4
      pushn r5
      callex @r5(EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString)
      movnw r0, r0(+2, +0)
      ret


efi_main:

      movrel r4, image_entry
      movn r1, @r0(+1, +16)
      movn @r4(EFI_IMAGE_ENTRY_POINT.ImageHandle), @r0(+0, +16)
      movn @r4(EFI_IMAGE_ENTRY_POINT.SystemTable), r1

      movibw r6, 16
      movrel r5, signature
      movq r4, @r1(EFI_SYSTEM_TABLE.Hdr.Signature)
      pushn r6
      pushn r5
      push r4
      call itow
      movn r0, r0(+2, +8)

      movrel r4, msg_signature
      call display_message


      movrel r5, events.WaitForKey
      movn r4, @r1(EFI_SYSTEM_TABLE.ConIn)
      movn @r5, @r4(EFI_SIMPLE_TEXT_INPUT_PROTOCOL.WaitForKey)


show_msg_and_wait_keypress:

      movrel r4, msg_press_esc
      call display_message

      movrel r6, event_indx
      movrel r5, events
      movibw r4, 1
      movn r3, @r1(EFI_SYSTEM_TABLE.BootServices)
      pushn r6
      pushn r5
      pushn r4
    @@:
      callex @r3(EFI_BOOT_SERVICES.WaitForEvent)
      movn r7, r7
      cmpieq r7, EFI_SUCCESS
      jmp8cc @b


handle_keypress:

      movnw r0, r0(+3, +0)

      movrel r2, input_key
      movn r4, @r1(EFI_SYSTEM_TABLE.ConIn)
      pushn r2
      pushn r4
      callex @r4(EFI_SIMPLE_TEXT_INPUT_PROTOCOL.ReadKeyStroke)
      movn r0, r0(+2, +0)
      movn r7, r7
      cmpieq r7, EFI_SUCCESS
      jmpcc show_msg_and_wait_keypress
      cmpi32weq @r2(EFI_INPUT_KEY.ScanCode), 0x17
      jmp32cc r0(show_msg_and_wait_keypress)

      ret

;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;
; itoa, itow
;
;-----------------------------------------------------------------------
;
; Converts an integer `value` to a null-terminated ASCII (itoa) or
; UCS-2 (itow) string using the specified `base` and stores the result
; in the array given by `str` parameter.
;
; If `base` is 10 and value is negative, the resulting string is
; preceded with a minus sign (-). With any other `base`, `value` is
; always considered unsigned.
;
; `str` should be an array long enough to contain any possible value
;
; Parameters
; ----------
;
; INT64 value   - Value to be converted to a string.
; INTN  str     - Array in memory where to store the resulting
;                 null-terminated string.
; INTN  base    - Numerical base used to represent the value as a
;                 string, between 2 and 36.
;
; Return
; ------
;
; R7            - String length in bytes (excluding terminating null)
;
; (informal)
;
; R4            - Character size in bytes (1 for itoa and 2 for itow)
; R5            - Pointer to terminating null
; R6            - Base
;
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
itoa:

      movibw r4, 1
      call32 r0(__itostr)
      movibw @r5, 0
      ret

itow:

      movibw r4, 2
      call32 r0(__itostr)
      moviww @r5, 0
      ret

__itostr:
      push64 r1
      push64 r2
      movqw r1, @r0(+0, +48)
      movnw r5, @r0(+0, +56)
      movnw r6, @r0(+1, +56)
      movibw r7, 0
      cmpi32wgte r6, 2
      jmp32cc r0(.ret)
      cmpi32wlte r6, 36
      jmp32cc r0(.ret)
      cmpi32weq r6, 10
      jmp8cc @f
      cmpi64wgte r1, 0
      jmp8cs @f
      moviww @r5, '-'
      add64 r5, r4
      neg64 r1, r1
    @@:
      movqw r2, r1
      divu64 r1, r6
      modu64 r2, r6
      push32 r2
      add32 r7, r4
      cmpi64wugte r1, 2
      jmp8cs @b
      cmpi64weq r1, 0
      jmp8cs @f
      push32 r1
      add32 r7, r4
    @@:
      movreld r2, .alphabet
    @@:
      pop32 r1
      add32 r1, r1
      add32 r1, r2
      movww @r5, @r1
      add64 r5, r4
      sub32 r7, r4
      cmpi32weq r7, 0
      jmp8cc @b
      movnw r7, r5
      sub32 r7, @r0(+0, +56)

  .ret:
      pop64 r2
      pop64 r1
      ret

  .alphabet wchar '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'


section '.data' data readable writeable

image_entry     EFI_IMAGE_ENTRY_POINT

event_indx      uintn
events:
  .WaitForKey   efi_event
sizeof.events = ($ - events) / sizeof.efi_event

input_key       EFI_INPUT_KEY

msg_press_esc   wchar 13,10,'Press [ESC] to exit',0

msg_signature   wchar 'EFI_SYSTEM_TABLE Signature is 0x'
signature       wchar [34]
