-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.asm
367 lines (257 loc) · 6.1 KB
/
main.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
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
[org 0x0100]
jmp main
;each word of array is the position of that part of snake on screen.
snake: times 240 dw 0
size: dw 0 ;curr size of the snake array.
direction: dw 0 ;0 for right, 1 for down, 2 for left, 3 for up.
foodGreen: dw 0 ;position of the fruit on screen.
bonusFood: dw 0
bonusFoodCountdown: dw 0
bombFood: dw 0
bombFoodCountdown: dw 0
lives: dw 3
level: dw 0
hitSound: dw 4536
eatSound: dw 1569
soundDuration: dw 2;in half seconds.
resetMessageCountdown: dw 0
int0divisor: dw 0xffff ;initial divisor.
int0frequency: dw 0
halfSeconds: dw 0
seconds: dw 0
minutes: dw 0
tickCount: dw 0
delayCount: dw 4 ;initially starts with 4 second delay at the slowest possible frequency of 18.2.
currCount: dw 0 ;the purpose is almost same as tickCount defined above, but that variable is used for maintaining time and music.
controlWord: dw 0
WelcomeMsg: db 'Welcoe to Snake Xenia', 0
stage1Msg: db 'Press 1 for stage 1',0
stage2Msg: db 'Press 2 for stage 2',0
stage3Msg: db 'Press 3 for stage 3',0
instruct0: db 'INSTRUCTIONS', 0
instruct01: db 'You have three lives. Eating food increases points and length', 0
instruct1: db 'You lose life if you hit walls, yourself, or eat the black food', 0
instruct2: db 'Yellow food gives you 4 points.', 0
instruct3: db 'Pink food gives you 20 points, and appears for a temporary time', 0
instruct4: db 'In stage 3, green portal on one side leads to the red one on the other side.', 0
%include "snake.asm"
%include "arena.asm"
%include "food.asm"
%include "utility.asm"
%include "audio.asm"
zeroHandler:
;just to make the screen red if some div by zero occurs.
pusha
push es
mov ax, 0xb800
mov es, ax
mov di, 0 ;es:di = b800:0
mov ax, 0x4720
mov cx, 2000
cli
rep stosw
pop es
popa
iret
timer:
pusha
push ds
push cs
pop ds
inc word[tickCount]
inc word[currCount]
call updateTime
call playMusic
call updateSpeed ;these functions maintain the system.
mov ax, [delayCount] ;controls the speed.
cmp [currCount], ax
jl endTimerIsr
call makeArena
call drawFood
call moveSnake
call makeSnake
call eatFood
call foodManager
call collisionCheckMaster
call checkTimePassed
mov word[currCount], 0
endTimerIsr:
call diplayLives ;actually only displayTime needs to be outputted on every tick, this is just to group related logic.
call displayLength
call displayTime
call displayResetMessage
mov al, 0x20
out 0x20, al
pop ds
popa
iret
kbisr:
pusha
push ds
push cs
pop ds
in al, 0x60
cmp al, 0x48 ;w
jne checkDownKey
cmp word[direction], 1 ;if going down then it can't go up.
je keysChecked
mov word[direction], 3 ;for up
jmp keysChecked
checkDownKey:
cmp al, 0x50
jne checkRightKey
cmp word[direction], 3 ;if going up, cannot go down.
je keysChecked
mov word[direction], 1;for down
jmp keysChecked
checkRightKey:
cmp al, 0x4d
jne checkLeftKey
cmp word[direction], 2 ;if left,can't go right
je keysChecked
mov word[direction], 0;for right.
jmp keysChecked
checkLeftKey:
cmp al, 0x4b
jne keysChecked
cmp word[direction], 0 ;if right, can't go left
je keysChecked
mov word[direction], 2;for left.
keysChecked:
pop ds
popa
jmp far [cs:oldKbIsr]
oldKbIsr: dd 0
oldTimerIsr: dd 0
oldZeroIsr: dd 0
printMessages:
push word WelcomeMsg
push word 0x00c0
push word 8
push word 10
call printStr
push word stage1Msg
push word 0x0040
push word 10
push word 10
call printStr
push word stage2Msg
push word 0x0040
push word 11
push word 10
call printStr
push word stage3Msg
push word 0x0040
push word 12
push word 10
call printStr
push word instruct0
push word 0x0040
push word 14
push word 2
call printStr
push word instruct01
push word 0x0040
push word 15
push word 2
call printStr
push word instruct1
push word 0x0040
push word 16
push word 2
call printStr
push word instruct2
push word 0x0040
push word 17
push word 2
call printStr
push word instruct3
push word 0x0040
push word 18
push word 2
call printStr
push word instruct4
push word 0x0040
push word 19
push word 2
call printStr
ret
main:
call clearScreen
call printMessages
takeInputAgain:
mov ah, 0
int 16h
sub al, 48
dec al
cmp al, 2
ja takeInputAgain
mov ah, 0
mov [level], ax
xor ax, ax
mov es, ax
call initializeSnake
call speakerOn
call makeArena
call foodManager
push word [int0divisor]
call updateTimerFrequency
xor ax, ax
mov es, ax
mov ax, [es:0x9*4]
mov [oldKbIsr], ax
mov ax, [es:0x9*4 + 2]
mov [oldKbIsr + 2], ax
mov ax, [es:0x8*4]
mov [oldTimerIsr], ax
mov ax, [es:0x8*4 + 2]
mov [oldTimerIsr + 2], ax
mov ax, [es:0]
mov [oldZeroIsr], ax
mov ax, [es:2]
mov [oldZeroIsr + 2], ax
cli
mov word[es:0], zeroHandler
mov word[es:2], cs
mov word[es:0x8*4], timer
mov word[es:0x8*4 + 2], cs
mov word[es:0x9*4], kbisr
mov word[es:0x9*4+ 2], cs
sti
notDead:
push word 0
call terminationCondition
pop dx
cmp dx, 0
je notDead
xor ax, ax
mov es, ax
cli
mov ax, [oldKbIsr]
mov [es:0x9*4], ax
mov ax, [oldKbIsr + 2]
mov [es:0x9*4 + 2], ax
mov ax, [oldTimerIsr]
mov [es:0x8*4], ax
mov ax, [oldTimerIsr + 2]
mov [es:0x8*4 + 2], ax
mov ax, [oldZeroIsr]
mov [es:0], ax
mov ax, [oldZeroIsr + 2]
mov [es:2], ax
sti
cmp dx, 1
jne loseCheck
call winGameScreen
jmp endGameCheck
loseCheck:
call loseGameScreen
endGameCheck:
call speakerOff
mov ah, 0ch
int 21h
mov ah, 0
int 16h ;waits for input.
call clearScreen
mov ax, 0x4c00
int 21h