;;;;;;;;;;; SYSTEM.INC - INTEL, WINDOWS ;;;;;;;;;;

@rva equ ($1000-$200)
@base equ $400000+@rva

@entry=$1000+(@main-@section)
@section_size=@end_section-@section
@image_size =\
  ((($1000+@section_size) shr 12)+1) shl 12
@import_size=@end_import-@section

macro write_exe_header
  dw 'MZ'
  db $3A dup(0)
  dd $40
  db 'PE', 0, 0
  dd $1014C, 0, 0, 0, $10F00E0, $10B, 0, 0, 0
  dd @entry, 0, 0, $400000, $1000, $200
  dd 1, 0, 4, 0, @image_size, $200, 0, 2
  dd $1000, $1000, $1000, 0, 0, 16
  dd 0, 0, $1000, @import_size
  dq 14 dup(0)
end macro

macro write_section_header
  dq '.one'
  dd @end_program-@end_section, $1000
  dd @end_program-$200, $200, 0, 0, 0
  dd $0E0000020
end macro

;;;;;;;;;;;;;;;;;;;;; IMPORT ;;;;;;;;;;;;;;;;;;;;;

macro library p&     ; import library
  irp dll, p
    dd 0, 0, 0
    dd @rva+dll#_name, @rva+dll#_table
  end irp
  dd 0, 0, 0, 0, 0
end macro

macro import dll, p& ; import functions
  dll#_name db \     ; 'name.dll'
    `dll, '.DLL', 0
  dll#_table:        ; table
  irp name, p        ; import rvas
    label @#name \
      at @base+$
    dd @rva+_#name
  end irp
  dd 0
  irp name, p        ; import names
    _#name dw 0      ; ordinal=0
    db `name, 0      ; 'name'
  end irp
  irp name, p        ; create macros
    macro name q&    ; to call with
      call_p \       ; parameters
        @#name, q
    end macro
  end irp
end macro

macro import_table

  library MSVCRT, SHELL32, KERNEL32,\
    USER32, GDI32, COMDLG32

  import MSVCRT, sprintf

  import SHELL32,\
    ShellExecuteA, ShellExecuteExA

  import KERNEL32,\
    GetModuleHandleA, GetModuleFileNameA,\
    GetCommandLineA, HeapCreate, HeapAlloc,\
    HeapReAlloc, HeapSize, HeapFree,\
    LoadLibraryA, FreeLibrary, GetProcAddress,\
    WaitForSingleObject, Sleep, ExitProcess

  import USER32,\
    GetSystemMetrics, GetDC, ReleaseDC, SetTimer,\
    MessageBoxA, RegisterClassExA, CreateWindowExA,\
    DestroyWindow, ShowWindow, MoveWindow,\
    UpdateWindow, GetMessageA, PeekMessageA,\
    TranslateMessage, DispatchMessageA,\
    SendMessageA, DefWindowProcA, PostQuitMessage,\
    WaitMessage, GetAsyncKeyState, LoadImageA,\
    LoadIconA, LoadCursorA, SetCursor, ShowCursor,\
    SetCursorPos, BeginPaint, EndPaint, FillRect,\
    InvalidateRect

  import GDI32,\
    SelectObject, DeleteObject, GetObjectA,\
    DeleteDC, TextOutA, CreateFontA,\
    CreateFontIndirectA, SetDIBits, BitBlt,\
    StretchBlt, CreateBitmap, CreateCompatibleDC

  import COMDLG32,\
    GetOpenFileNameA, GetSaveFileNameA,\
    ChooseColorA, ChooseFontA
end macro

;;;;;;;;;;;;;;;;;;;;;; MAIN ;;;;;;;;;;;;;;;;;;;;;;

write_exe_header
write_section_header

align $200
@section:
  import_table
@end_import:
align 16

macro main
  align 16
  @main:
end macro

postpone
  align 16, $90
  @end_section:
    align $200, $90
  @end_program:
end postpone

;;;;;;;;;;;;;;;;;;;;; LIBRARY ;;;;;;;;;;;;;;;;;;;;

macro say a, b
  match any, b
    MessageBoxA 0, a, b, 0
  else
    MessageBoxA 0, a, a, 0
  end match
end macro

macro exit
  ExitProcess 0
end macro
