-
Notifications
You must be signed in to change notification settings - Fork 0
/
boot.asm
333 lines (277 loc) · 6.63 KB
/
boot.asm
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
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
bits 16
org 0x7c00
; 320x200x8bit
%define VGA_MODE 0x13
%define VGA_OFFSET 0xA000
; in pixels
%define SCREEN_WIDTH 320
%define SCREEN_HEIGHT 200
; in pixels
%define CELL_WIDTH 10
%define CELL_HEIGHT 10
; in cells
%define FIELD_WIDTH 20
%define FIELD_HEIGHT 10
; in pixels
%define FIELD_Y (SCREEN_HEIGHT - (FIELD_HEIGHT * CELL_HEIGHT)) / 2
%define FIELD_X (SCREEN_WIDTH - (FIELD_WIDTH * CELL_WIDTH)) / 2
%define FIELD_END_Y (SCREEN_HEIGHT - FIELD_Y)
%define FIELD_END_X (SCREEN_WIDTH - FIELD_X)
%define FIELD_START (FIELD_Y * SCREEN_WIDTH) + FIELD_X
; in pixels
%define PALETTE_OFFSET 10
%define PALETTE_COLOR_COUNT 7
%define PALETTE_Y FIELD_Y + (FIELD_HEIGHT * CELL_HEIGHT) + PALETTE_OFFSET
%define PALETTE_X FIELD_X + (((FIELD_WIDTH * CELL_WIDTH) - (PALETTE_COLOR_COUNT * CELL_WIDTH)) / 2)
%define PALETTE_END_Y (PALETTE_Y + CELL_HEIGHT)
%define PALETTE_UNDERSCORE_PADDING 2
; in pixels
%define UNDERSCORE_START ((PALETTE_END_Y + PALETTE_UNDERSCORE_PADDING) * SCREEN_WIDTH) + PALETTE_X
%define UNDERSCORE_END (UNDERSCORE_START + (CELL_WIDTH * (COLOR_WHITE - COLOR_LIGHTBLUE + 1)))
%define COLOR_BLACK 0
%define COLOR_LIGHTGRAY 7
%define COLOR_LIGHTBLUE 9
%define COLOR_LIGHTGREEN 10
%define COLOR_LIGHTCYAN 11
%define COLOR_LIGHTRED 12
%define COLOR_LIGHTMAGENTA 13
%define COLOR_YELLOW 14
%define COLOR_WHITE 15
%define BACKGROUND_COLOR COLOR_BLACK
; ---------------------------------------------------------------
struc game_state_t
.current_col: resb 1
endstruc
; ---------------------------------------------------------------
entry:
mov ax, VGA_MODE
int 0x10
mov ax, VGA_OFFSET
mov es, ax
call put_field
call put_palette
entry_loop:
call put_underscore
xor ax, ax
int 0x16
cmp al, 'a'
jne dec_continue
call col_dec
dec_continue:
cmp al, 'd'
jne inc_continue
call col_inc
inc_continue:
cmp al, ' '
cmp al, 'q'
je end
jmp entry_loop
jmp end
; ax <- cell index
; puts 0 in 'ax' if cell doesn't belong to anybody, otherwise puts '1'
get_player:
; TODO:
ret
; ax <- cell index
; assignes cell to a player by coloring top-left corner of the cell
add_player:
; TODO:
ret
; ax <- cell index
; assignes cell first pixel index to 'ax'
get_cell_pixel:
; ax < 0
cmp ax, 0
jl get_cell_pixel_end
; ax >= FIELD_WIDTH * FIELD_HEIGHT
cmp ax, FIELD_WIDTH * FIELD_HEIGHT
jge get_cell_pixel_end
push dx
push bx
xor dx, dx ; dx = 000..
mov cx, FIELD_WIDTH ; cx = FIELD_WIDTH
div cx ; (dx:ax) == (000...ax) / cx ==> ax <- div & dx <- mod
push dx ; `dx` gets zeroed by `mul`
mov bx, CELL_HEIGHT ; bx = CELL_HEIGHT
mul bx ; ax *= bx
mov bx, SCREEN_WIDTH ; bx = SCREEN_WIDTH
mul bx ; ax *= bx
add ax, FIELD_START ; ax += FIELD_START
pop dx
mov bx, ax ; bx = ax
mov ax, CELL_WIDTH ; ax = CELL_WIDTH
mul dx ; ax *= dx
add bx, ax ; bx += ax
mov ax, bx ; ax = bx
pop bx
pop dx
get_cell_pixel_end:
ret
col_dec:
push ax
mov ax, [init_game_state + game_state_t.current_col]
cmp ax, COLOR_LIGHTBLUE
je col_dec_reset
; decrement
dec ax
mov [init_game_state + game_state_t.current_col], ax
jmp col_dec_end
; reset
col_dec_reset:
mov ax, COLOR_WHITE
mov [init_game_state + game_state_t.current_col], ax
col_dec_end:
pop ax
ret
col_inc:
push ax
mov ax, [init_game_state + game_state_t.current_col]
cmp ax, COLOR_WHITE
je col_inc_reset
; increment
inc ax
mov [init_game_state + game_state_t.current_col], ax
jmp col_inc_end
; reset
col_inc_reset:
mov ax, COLOR_LIGHTBLUE
mov [init_game_state + game_state_t.current_col], ax
col_inc_end:
pop ax
ret
put_underscore:
push ax
push bx
push cx
; clear underscore area
mov di, UNDERSCORE_START
xor cx, cx
clr_underscore_h:
mov [es:di], cl
inc di
cmp di, UNDERSCORE_END
jne clr_underscore_h
; underscore color
mov cl, [init_game_state + game_state_t.current_col]
; underscore start
mov ax, [init_game_state + game_state_t.current_col]
sub ax, COLOR_LIGHTBLUE
mov bx, CELL_WIDTH
mul bx
add ax, UNDERSCORE_START
; underscore end
mov bx, ax
add bx, CELL_WIDTH - 1 ; -1 for cell padding
; underscore index
mov di, ax
put_underscore_h:
mov [es:di], cl
inc di
cmp di, bx
jne put_underscore_h
pop cx
pop bx
pop ax
ret
put_palette:
push ax
push bx
mov ax, PALETTE_Y
mov bx, PALETTE_X
mov cl, COLOR_LIGHTBLUE
put_palette_h:
call put_cell
; increment color & x
inc cl
add bx, CELL_WIDTH
cmp cl, COLOR_WHITE + 1
jne put_palette_h
pop bx
pop ax
ret
; put field at (FIELD_X, FIELD_Y)
put_field:
push ax
push bx
mov ax, FIELD_Y
put_field_v:
mov bx, FIELD_X
put_field_h:
call rand_col
call put_cell
add bx, CELL_WIDTH
cmp bx, FIELD_END_X
jne put_field_h
add ax, CELL_HEIGHT
cmp ax, FIELD_END_Y
jne put_field_v
pop bx
pop ax
ret
; ax <- y
; bx <- x
; cl <- color
put_cell:
push ax
push bx
; di <- starting pixel coordinate
; di = y * SCREEN_WIDTH + x
mov di, SCREEN_WIDTH ; di = SCREEN_WIDTH
mul di ; ax *= di
mov di, ax ; di = ax
add di, bx ; di += bx
; ax <- lowest border
mov ax, CELL_HEIGHT - 1; -1 is a cell spacing
mov bx, SCREEN_WIDTH
mul bx
add ax, di
put_cell_v:
; bx <- rightmost boder
mov bx, di
add bx, CELL_WIDTH - 1 ; -1 is a cell spacing
push di
put_cell_h:
mov [es:di], cl
inc di
cmp di, bx
jne put_cell_h
pop di
add di, SCREEN_WIDTH
cmp di, ax
jne put_cell_v
pop bx
pop ax
ret
; puts random color in `cl`
rand_col:
push ax
push dx
; TimeStampCounter: puts counter into `ax`
rdtsc
xor dx, dx
mov cx, COLOR_WHITE - COLOR_LIGHTBLUE + 1
div cx
mov ax, dx
add ax, COLOR_LIGHTBLUE
mov cl, al
pop dx
pop ax
ret
end:
jmp $
; ---------------------------------------------------------------
init_game_state:
istruc game_state_t
at game_state_t.current_col, db COLOR_LIGHTBLUE
iend
; ---------------------------------------------------------------
; debug size before padding it with 0
%assign program_size $ - $$
%warning program size is: program_size bytes
; padding
times 510 - ($ - $$) db 0
dw 0xaa55
; error if size is exceeding 512
%if $ - $$ != 512
%fatal Program is size is not 512
%endif