include '%lib%/freshlib.inc'

@BinaryType console

include '%lib%/freshlib.asm'

; Topic: Complex data structures in FASM
;   subtopic: Easy way to create initialized arrays of structures in FASM.
;
;       This example was written, because this is one of most common
;    questions on FASM message board. Sometimes it is problem even for
;    expirianced assembly programmers using other assemblers. Actually it is
;    not so hard to create not only arrays but even more complex data structures
;    as linked lists or trees, using so powerfull macro system of FASM.
;
;       I will refrain from using very complex macroses, because it is not
;    very useful for beginers to use them, even using ready for use libraries.
;    IMHO, it is better for every beginer to understand what actually happen and
;    then to begin to use complex macro libaries with full understanding.
;
;       Actually structures in FASM are almost same thing as macroses.
;    Only difference is that structures need label before it, but macro does
;    not need it.
;
;      There are two aspects in the "arrays" problem: "definition" and "using".
;    I will try to explain both aspects on the simple example.
;    Let we need some array with points and then we need some procedure that will
;    draw poliline from the first point to the last point of the array.
;    Indication for end of the array will be the point with negative x coordinate.
;
;    At first we will define base point structure, because we will need it when we
;    want to access defined data:

struct TPoint
  .x dd ?
  .y dd ?
ends

;    Then we will define macro for definition of initialized array.
macro PointArray [x, y] {
  forward  ; This means that following rows will be repeated for every set of arguments
    dd x
    dd y
  common
    dd -1  ; This will define one dword with content -1 at the end of the array.
}


iglobal

; Ok, we have the macro definitions, let's define an array:
MyArray:
        PointArray                      \
          100, 100,                     \
          200, 100,                     \
          200, 200,                     \
          100, 200,                     \
          100, 100,                     \
          150, 130,                     \
          200, 100

cMessage:
         db 'Look at upper left side of the console. There you can see', 13
         db 'black wireframe figure like "envelope".',13, 13, 13
         db 'This is example how to create and use initialized arrays in FASM.',13
         db 'author: John Found', 13, 0
endg


start:
        invoke  GetConsoleWindow
        invoke  GetDC, eax
        mov     edi, eax

        invoke  Rectangle, edi, 0, 0, 300, 300

; And here the program will make some draw on the surface of the application console.
; I make it this way to keep additional code as small as possible.

        mov     esi, MyArray
        invoke  MoveToEx, edi, [esi+TPoint.x], [esi+TPoint.y], NULL   ; first point
        add     esi, sizeof.TPoint

.drawloop:
        cmp    [esi+TPoint.x], -1
        je     .enddraw

        invoke  LineTo, edi, [esi+TPoint.x], [esi+TPoint.y]
        add     esi, sizeof.TPoint
        jmp     .drawloop

.enddraw:
        invoke  ReleaseDC, edi
        invoke  MessageBoxA, NULL, cMessage, NULL, MB_OK or MB_ICONINFORMATION
        invoke  ExitProcess, 0

