
; --------------------------------------------------------
;
;  Takes a date/time passed in a systemtime structure
;  and formats it into a simple string representation.
;
;  Function FormatDate(tSysTime As SYSTEMTIME) As String
;
;     ' 9/05/2021  9:08 AM'   '24/12/2045 10:22 PM'
;
;  The output from FormatDate is intended to be displayed
;  using the MS Sans Serif font whose space character is
;  exactly half the width of a digit.
;
; --------------------------------------------------------

 .486            ; 32-bit instruction set
 .model flat     ; Protected memory, 4GB limit
 .code           ; Start of code

FormatDate proc near

   wYear   equ [esi+00h] ; Specifies the year.
   wMonth  equ [esi+02h] ; Specifies the month (Jan=1,Feb=2..)
   wDay    equ [esi+06h] ; Specifies the day of the month.
   wHour   equ [esi+08h] ; Specifies the hour (24 hr)
   wMinute equ [esi+0Ah] ; Specifies the minute.

   push esi
   push edi
   push ebx

   mov esi,[esp+20]  ; Pointer to systemtime structure

   mov ecx, 21
   cmp wDay,word ptr 10
   jb @f
   dec ecx
  @@:

   mov dx, wHour
   mov ebx,4d0041h   ; 'AM'
   cmp dx, 12
   jb @f
   mov bl, 50h       ; 'PM'
  @@:
   test dx, dx
   jnz @f
   dec ecx
   jmp _alloc
  @@:
   cmp dx, 13
   jb @f
   sub dx, 12        ; 24 hr to 12 hr
  @@:
   cmp dx, 10
   jb @f
   dec ecx
  @@:

  _alloc:
   mov edx,8876543h  ; api address patched on init
   push ecx          ; SysAllocStringLen len param
   push 0            ; string to copy (null pointer)
   call edx          ; call SysAllocStringLen api
   mov edi, eax      ; store the return pointer

   mov eax,200020h   ; '  '
   mov ecx,[edi-4]
   mov [edi],eax
   mov [edi+4],eax
   mov [edi+8],eax
   mov [edi+12],eax
   mov [edi+16],eax
   mov [edi+20],eax
   mov [edi+24],eax
   mov [edi+28],eax
   mov [edi+32],eax
   mov [edi+36],eax
   mov [edi+40],ax
   mov [edi+ecx-4],ebx

   mov dx, 3030h     ; dl='0',dh='0'
   mov ax, wMinute
   aam
   add ax, dx

   mov [edi+ecx-8],al
   mov [edi+ecx-10],ah
   mov [edi+ecx-12],word ptr 3ah ; ':'

   mov ax, wHour
   test ax, ax
   jnz @f
   mov ax, 3132h     ; '12' midnight
   jmp _hour
  @@:
   cmp ax, 13
   jb @f
   sub ax, 12        ; convert to 12 hr clock
  @@:
   aam
   add ax, dx ;3030h

  _hour:
   mov [edi+ecx-14],al
   cmp ah, dh
   je @f
   mov [edi+ecx-16],ah
  @@:

   mov ax, wDay
  @@:  ;aam
   cmp al, 10
   jb @f
   sub al, 10
   inc ah
   cmp al, 10
   jb @f
   sub al, 10
   inc ah
   cmp al, 10
   jb @f
   sub al, 10
   inc ah
  @@:
   add ax, dx

   mov ebx, edi
   cmp ah, dh ;30h
   ja @f
   mov ah, 20h       ; ' 9/05/2021  9:08 AM'
   add edi, 2
  @@:
   mov [edi],ah
   mov [edi+2],al
   mov [edi+4],word ptr 2fh ; '/'

   mov ax, wMonth    ; '24/12/2045 10:22 PM'
   aam
   add ax, dx

   mov [edi+6],ah
   mov [edi+8],al
   mov [edi+10],word ptr 2fh ; '/'

   mov ax, wYear
   mov cx, dx ;3030h

  @@:
   cmp ax, 1000
   jb @f
   sub ax, 1000
   inc ch
   jmp @b
  @@:
   cmp ax, 100
   jb @f
   sub ax, 100
   inc cl
   jmp @b
  @@:
   cmp al, 10
   jb _assign
   sub al, 10
   inc ah
   jmp @b

  _assign:     ; 2036 -> ch=2, cl=0, ah=3, al=6
   add ax, dx
   mov [edi+12],ch
   mov [edi+14],cl
   mov [edi+16],ah
   mov [edi+18],al

  _return:
   mov edi,[esp+24]
   mov [edi],ebx

  _exitp:
   pop ebx
   pop edi       ; restore registers
   pop esi
   xor eax, eax  ; clear eax tell VB all okay
   ret 12        ; cleanup (lpObj, p1, rc)

FormatDate endp  ; end of procedure
end FormatDate   ; end of code, indicate entry point


; The SYSTEMTIME structure represents a date and time
; using individual members for the month, day, year,
; weekday, hour, minute, second, and millisecond.
;
; typedef struct _SYSTEMTIME { // st
;    WORD wYear;         // Specifies the year.
;    WORD wMonth;        // Specifies the month; January = 1, February = 2, and so on.
;    WORD wDayOfWeek;    // Specifies the day of the week; Sunday = 0, Monday = 1, and so on.
;    WORD wDay;          // Specifies the day of the month.
;    WORD wHour;         // Specifies the hour.
;    WORD wMinute;       // Specifies the minute.
;    WORD wSecond;       // Specifies the second.
;    WORD wMilliseconds; // Specifies the millisecond.
; } SYSTEMTIME;


