aboutsummaryrefslogtreecommitdiff
path: root/src/main.S
blob: 63fa359ba36835138d96719f995fa81df4630133 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
#include "helpers/function.S"
#include "SDL/events.S"
#include "SDL/init.S"
#include "SDL/rect.S"
#include "SDL/render.S"
#include "SDL/video.S"

#define SCREEN_WIDTH 800
#define SCREEN_HEIGHT 600

// integer-params:  RDI, RSI, RDX, RCX, R8, R9
// caller-saved:    RAX, RCX, RDI, RSI, RDX, R8-R11
// callee-saved:    RBX, RSP, RBP, R12-R15

.section .rodata
  failed_to_create_renderer:    .string "Renderer could not be created\nSDL_error: %s\n"
  failed_to_create_window:      .string "Window could not be created\nSDL_error: %s\n"
  failed_to_initialize_sdl:     .string "SDL could not be initialized\nSDL_error: %s\n"

  succeeded_to_create_renderer: .string "Renderer created successfully!\n"
  succeeded_to_create_window:   .string "Window created successfully!\n"
  succeeded_to_initialize_sdl:  .string "SDL2 initialized successfully!\n"

  window_title:                 .string "snake.s"

.section .text

  function_begin main

    push %r12
    push %r13

    define_local window_handle, 8
    define_local renderer_handle, 8
    define_local rect, SIZE_SDL_Rect
    define_local event, SIZE_SDL_Event
    allocate_locals

    // initialize SDL
    mov $SDL_INIT_VIDEO, %rdi
    call SDL_Init@PLT

    // check if initialization was successful
    test %rax, %rax
    jae 1f
      lea failed_to_initialize_sdl(%rip), %rdi
      call _print_sdl_error@PLT
      mov $1, %rax
      function_exit
  1:
    lea succeeded_to_initialize_sdl(%rip), %rdi
    xor %rax, %rax
    call printf@PLT

    // create a window
    lea window_title(%rip), %rdi
    mov $SDL_WINDOWPOS_UNDEFINED, %rsi
    mov $SDL_WINDOWPOS_UNDEFINED, %rdx
    mov $SCREEN_WIDTH, %rcx
    mov $SCREEN_HEIGHT, %r8
    mov $SDL_WINDOW_SHOWN, %r9
    call SDL_CreateWindow@PLT
    store_local %rax, window_handle

    // check if window creation was successful
    test %rax, %rax
    jne 1f
      lea failed_to_create_window(%rip), %rdi
      call _print_sdl_error@PLT
      mov $1, %rax
      jmp .Lquit_sdl
  1:
    lea succeeded_to_create_window(%rip), %rdi
    xor %rax, %rax
    call printf@PLT

    // create a renderer
    load_local window_handle, %rdi
    mov $-1, %rsi
    mov $(SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC), %rdx
    call SDL_CreateRenderer@PLT
    store_local %rax, renderer_handle

    // check if renderer creation was successful
    test %rax, %rax
    jne 1f
      lea failed_to_create_renderer(%rip), %rdi
      call _print_sdl_error@PLT
      jmp .Ldestroy_window
  1:
    lea succeeded_to_create_renderer(%rip), %rdi
    xor %rax, %rax
    call printf@PLT

    // initialize a simple square, located at the screen's center
    mov $(SCREEN_HEIGHT / 2), %r8d
    mov $(SCREEN_WIDTH / 2), %r9d

    address_of_local rect, %rdi
    mov %r8d, OFFSET_SDL_Rect_w(%rdi)
    mov %r8d, OFFSET_SDL_Rect_h(%rdi)
    mov %r9d, %r10d
    shr $1, %r8d
    sub %r8d, %r10d
    mov %r10d, OFFSET_SDL_Rect_x(%rdi)
    mov %r8d, OFFSET_SDL_Rect_y(%rdi)

    //! @var bool quit_requested
    xor %r12, %r12

    // main loop
  .Lloop:

    address_of_local event, %rdi
    mov %rdi, %r13
    call SDL_PollEvent@PLT
    mov (%r13), %r8d

    // user requested to quit
    cmp $SDL_EVENT_QUIT, %r8d
    je .Lloop_end

    // use white color
    load_local renderer_handle, %rdi
    mov %rdi, %r13
    mov $0xff, %rsi
    mov %rsi, %rdx
    mov %rsi, %rcx
    mov %rsi, %r8
    call SDL_SetRenderDrawColor@PLT
    test %rax, %rax

    // clear the screen
    mov %r13, %rdi
    call SDL_RenderClear@PLT

    // use red color
    mov %r13, %rdi
    mov $0xff, %rsi
    mov $0x00, %rdx
    mov $0x00, %rcx
    mov %rsi, %r8
    call SDL_SetRenderDrawColor@PLT

    // draw the square
    mov %r13, %rdi
    address_of_local rect, %rsi
    call SDL_RenderFillRect@PLT

    // update the screen
    mov %r13, %rdi
    call SDL_RenderPresent@PLT

    jmp .Lloop
  .Lloop_end:

  .Ldestroy_renderer:
    // destroy the renderer
    load_local renderer_handle, %rdi
    call SDL_DestroyRenderer@PLT

  .Ldestroy_window:
    // destroy the window
    load_local window_handle, %rdi
    call SDL_DestroyWindow@PLT

  .Lquit_sdl:
    call SDL_Quit@PLT

    xor %rax, %rax
    pop %r13
    pop %r12
  function_end