-
Notifications
You must be signed in to change notification settings - Fork 37
/
pinpog.asm
328 lines (271 loc) · 7 KB
/
pinpog.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
org 0x7C00
%define WIDTH 320
%define HEIGHT 200
%define COLUMNS 40
%define ROWS 25
%define COLOR_BLACK 0
%define COLOR_BLUE 1
%define COLOR_GREEN 2
%define COLOR_CYAN 3
%define COLOR_RED 4
%define COLOR_MAGENTA 5
%define COLOR_BROWN 6
%define COLOR_LIGHTGRAY 7
%define COLOR_DARKGRAY 8
%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
%define BALL_WIDTH 16
%define BALL_HEIGHT 16
%define BALL_VELOCITY 6
%define BALL_COLOR COLOR_YELLOW
%define BAR_INITIAL_Y 50
%define BAR_HEIGHT 3
%define BAR_COLOR COLOR_LIGHTBLUE
%define BAR_VELOCITY 10
%define VGA_OFFSET 0xA000
%define SCORE_DIGIT_COUNT 5
struc GameState
.running: resb 1
.ball_x: resw 1
.ball_y: resw 1
.ball_dx: resw 1
.ball_dy: resw 1
.bar_x: resw 1
.bar_y: resw 1
.bar_dx: resw 1
.bar_len: resw 1
.score_sign resb SCORE_DIGIT_COUNT
endstruc
entry:
; VGA mode 0x13
; 320x200 256 colors
mov ax, 0x13
int 0x10
xor ax, ax
mov es, ax
mov ds, ax
mov cx, GameState_size
mov si, initial_game_state
mov di, game_state
rep movsb
mov dword [0x0070], draw_frame
.loop:
hlt
mov ah, 0x1
int 0x16
jz .loop
xor ah, ah
int 0x16
cmp al, 'a'
jz .swipe_left
cmp al, 'd'
jz .swipe_right
cmp al, ' '
jz .toggle_pause
cmp al, 'f'
jz entry
jmp .loop
.swipe_left:
mov word [game_state + GameState.bar_dx], - BAR_VELOCITY
jmp .loop
.swipe_right:
mov word [game_state + GameState.bar_dx], BAR_VELOCITY
jmp .loop
.toggle_pause:
not byte [game_state + GameState.running]
jmp .loop
draw_frame:
pusha
xor ax, ax
mov ds, ax
mov es, ax
mov ah, 0x13
mov bx, 0x0064
mov cl, SCORE_DIGIT_COUNT
xor dx, dx
mov bp, game_state + GameState.score_sign
int 10h
mov ax, VGA_OFFSET
mov es, ax
test byte [game_state + GameState.running], 1
jz stop_state
running_state:
mov al, BACKGROUND_COLOR
call fill_bar
call fill_ball
;; if (ball_x <= 0 || ball_x >= WIDTH - BALL_WIDTH) {
;; ball_dx = -ball_dx;
;; }
mov ax, word [game_state + GameState.ball_x]
cmp ax, 0
jle .neg_ball_dx
cmp ax, WIDTH - BALL_WIDTH
jl .ball_x_col_end
.neg_ball_dx:
neg word [game_state + GameState.ball_dx]
.ball_x_col_end:
;; if (ball_y >= HEIGHT - BALL_HEIGHT) {
;; gameOver();
;; } else if (ball_y <= 0) {
;; ball_dy = -ball_dy;
;; }
mov ax, word [game_state + GameState.ball_y]
cmp ax, HEIGHT - BALL_HEIGHT
jge .game_over
cmp ax, 0
jg .ball_y_col_end
neg word [game_state + GameState.ball_dy]
.ball_y_col_end:
;; if (bar_x <= 0 || bar_x >= WIDTH - BAR_WIDTH) {
;; bar_dx = -bar_dx;
;; bar_x = snap_to(side_it_collided_with);
;; }
xor ax, ax
cmp word [game_state + GameState.bar_x], ax
jle .neg_bar_dx
mov ax, WIDTH
sub ax, word [game_state + GameState.bar_len]
cmp word [game_state + GameState.bar_x], ax
jl .bar_x_col
.neg_bar_dx:
neg word [game_state + GameState.bar_dx]
mov word [game_state + GameState.bar_x], ax
.bar_x_col:
;;; Kebab Begin ------------------------------
;; bar_x <= ball_x && ball_x - bar_x <= BAR_WIDTH - BALL_WIDTH
mov bx, word [game_state + GameState.ball_x]
cmp word [game_state + GameState.bar_x], bx
jg .unkebab
sub bx, word [game_state + GameState.bar_x]
mov ax, word [game_state + GameState.bar_len]
sub ax, BALL_WIDTH
cmp bx, ax
jg .unkebab
; ball_y > bar_y => ignore
mov ax, [game_state + GameState.bar_y]
cmp word [game_state + GameState.ball_y], ax
jg .kebab_end
; ball_y >= bar_y - BALL_HEIGHT / 2 => kebab
sub ax, BALL_HEIGHT / 2
cmp word [game_state + GameState.ball_y], ax
jge .kebab
; ball_y >= bar_y - BALL_HEIGHT => bounce
sub ax, BALL_HEIGHT / 2
cmp word [game_state + GameState.ball_y], ax
jl .kebab_end
.bounce:
mov word [game_state + GameState.ball_dy], -BALL_VELOCITY
mov word [game_state + GameState.ball_dx], BALL_VELOCITY
mov ax, word [game_state + GameState.bar_dx]
test ax, ax
jns .score_point
neg word [game_state + GameState.ball_dx]
jmp .score_point
.kebab:
mov word [game_state + GameState.ball_dy], 0
;; Fall through
.score_point:
mov si, SCORE_DIGIT_COUNT
.loop:
inc byte [game_state + GameState.score_sign + si - 1]
cmp byte [game_state + GameState.score_sign + si - 1], '9'
jle .end
mov byte [game_state + GameState.score_sign + si - 1], '0'
dec si
jz .end
jmp .loop
.end:
cmp word [game_state + GameState.bar_len], 20
jle .kebab_end
dec word [game_state + GameState.bar_len]
jmp .kebab_end
.unkebab:
cmp word [game_state + GameState.ball_dy], 0
jnz .kebab_end
mov word [game_state + GameState.ball_dy], -BALL_VELOCITY
.kebab_end:
;;; Kebab End ------------------------------
;; ball_x += ball_dx
mov ax, [game_state + GameState.ball_dx]
add [game_state + GameState.ball_x], ax
;; ball_y += ball_dy
mov ax, [game_state + GameState.ball_dy]
add [game_state + GameState.ball_y], ax
;; bar_x += bar_dx
mov ax, [game_state + GameState.bar_dx]
add [game_state + GameState.bar_x], ax
mov al, BAR_COLOR
call fill_bar
mov al, BALL_COLOR
call fill_ball
jmp stop_state
.game_over:
xor ax, ax
mov es, ax
mov ah, 0x13
mov bx, 0x0064
; ch = 0 ; cl = game_over_sign_len
mov cx, game_over_sign_len
; dh = ROWS / 2 ; dl = COLUMNS / 2 - game_over_sign_len / 2
mov dx, (ROWS / 2) << 8 | (COLUMNS / 2 - game_over_sign_len / 2)
mov bp, game_over_sign
int 10h
mov byte [game_state + GameState.running], 0
stop_state:
popa
iret
fill_bar:
mov cx, word [game_state + GameState.bar_len]
mov bx, BAR_HEIGHT
mov si, game_state + GameState.bar_x
jmp fill_rect
fill_ball:
mov cx, BALL_WIDTH
mov bx, BALL_HEIGHT
mov si, game_state + GameState.ball_x
fill_rect:
;; al - color
;; cx - width
;; bx - height
;; si - pointer to ball_x or bar_x
; di = rect_y * WIDTH + rect_x
imul di, [si + 2], WIDTH
add di, [si]
.row:
push cx
rep stosb
pop cx
sub di, cx
add di, WIDTH
dec bx
jnz .row
ret
initial_game_state:
istruc GameState
at GameState.running, db 1
at GameState.ball_x, dw 30
at GameState.ball_y, dw 30
at GameState.ball_dx, dw BALL_VELOCITY
at GameState.ball_dy, dw -BALL_VELOCITY
at GameState.bar_x, dw 10
at GameState.bar_y, dw HEIGHT - BAR_INITIAL_Y
at GameState.bar_dx, dw BAR_VELOCITY
at GameState.bar_len, dw 100
at GameState.score_sign, times SCORE_DIGIT_COUNT db '0'
iend
game_over_sign: db "Game Over"
game_over_sign_len equ $ - game_over_sign
%assign sizeOfProgram $ - $$
%warning Size of the program: sizeOfProgram bytes
times 510 - ($-$$) db 0
game_state:
dw 0xaa55
%if $ - $$ != 512
%fatal Resulting size is not 512
%endif