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

@rva equ 0
@base equ 0

match =windows, format
  @rva reequ ($1000-$200)
  @base reequ $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
end match

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'
    macro name q&    ; create macro
      call_p \       ; to call with
        @#name, q    ; parameters
    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 ;;;;;;;;;;;;;;;;;;;;;;

match =windows, format
  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
end match

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

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

macro exit
  ExitProcess 0
end macro