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
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
|
covered_color equ 0x70
controls_color equ 0x70
flag_character equ 'F'
bombs_per_65535 equ 5000
board_width equ 26
board_height equ 10
offset_x equ 1
offset_y equ 1
org 0x0100
mov ax, 0x0501
int 0x10
xor ah, ah
int 0x1a
test dx, dx
jnz nonzero
inc dx
nonzero:
mov word [xorshift_state], dx
mov cx, board_width * board_height
mov si, cx
mov di, board_flags
bomb_loop:
call xorshift
cmp ax, bombs_per_65535
ja .no_bomb
mov byte [di], board_bomb
dec si
.no_bomb:
inc di
loop bomb_loop
mov word [non_bombs_left], si
xor bx, bx
mov di, board_numbers
number_loop:
call get_number_of_bx
mov byte [di], al
inc di
inc bl
cmp bl, board_width
jne number_loop
xor bl, bl
inc bh
cmp bh, board_height
jne number_loop
push 0xb900
pop es
xor di, di
mov ax, (covered_color << 8) | ' '
mov cx, 80 * 25
rep stosw
; mov di, offset_y * 80 * 2 + offset_x * 2
; mov cx, board_width * 3
; mov ax, (covered_color << 8) | 0xdf
; rep stosw
;
; mov di, (offset_y + 1) * 80 * 2 + offset_x * 2
; mov ax, (covered_color << 8) | ' '
;gray_loop:
; mov cx, board_width * 3
; rep stosw
; add di, (80 - board_width * 3) * 2
; cmp di, (offset_y + board_height * 2) * 80 * 2 + offset_x * 2
; jne gray_loop
;
; mov cx, board_width * 3
; mov ax, (covered_color << 8) | 0xdc
; rep stosw
mov si, controls_str
mov di, (offset_y + board_height * 2 + 2) * 80 * 2 + offset_x * 2 + ((board_width * 3 - controls_str.len) / 4) * 2
mov cx, controls_str.len
mov ah, controls_color
show_controls_loop:
mov al, byte [si]
mov word [es:di], ax
inc si
add di, 2
loop show_controls_loop
call set_cursor
main_loop:
xor ah, ah
int 0x16
cmp ah, 0x48
je up_arrow
cmp ah, 0x50
je down_arrow
cmp ah, 0x4b
je left_arrow
cmp ah, 0x4d
je right_arrow
cmp ah, 0x20
je dig
cmp ah, 0x21
je flag
cmp ah, 0x10
jne main_loop
mov ax, 0x0500
int 0x10
mov ax, 0x4c00
int 0x21
xorshift_state:
dw 0
xorshift:
mov ax, word [xorshift_state]
mov dx, ax
shl dx, 7
xor ax, dx
mov dx, ax
shr dx, 9
xor ax, dx
xor ah, al
mov word [xorshift_state], ax
ret
;bx - y:x
;preserves bx, di, and si
;returns in ax
bx_has_bomb:
push bx
movzx ax, bh
mov cx, board_width
mul cx
xor bh, bh
add bx, ax
mov ax, board_bomb
and al, byte [board_flags + bx]
pop bx
ret
;bx - y:x
;preserves bx, di, and si
;returns in ax
bx_uncovered:
push bx
movzx ax, bh
mov cx, board_width
mul cx
xor bh, bh
add bx, ax
mov ax, board_uncovered
and al, byte [board_flags + bx]
pop bx
ret
;bx - y:x
;preserves bx and di
;returns in al
get_number_of_bx:
xor si, si
test bh, bh
jz .no_ups
dec bh
test bl, bl
jz .no_ul
dec bl
call bx_has_bomb
add si, ax
inc bl
.no_ul:
call bx_has_bomb
add si, ax
cmp bl, board_width - 1
je .no_ur
inc bl
call bx_has_bomb
add si, ax
dec bl
.no_ur:
inc bh
.no_ups:
test bl, bl
jz .no_cl
dec bl
call bx_has_bomb
add si, ax
inc bl
.no_cl:
cmp bl, board_width - 1
je .no_cr
inc bl
call bx_has_bomb
add si, ax
dec bl
.no_cr:
cmp bh, board_height - 1
je .no_downs
inc bh
test bl, bl
jz .no_bl
dec bl
call bx_has_bomb
add si, ax
inc bl
.no_bl:
call bx_has_bomb
add si, ax
cmp bl, board_width - 1
je .no_br
inc bl
call bx_has_bomb
add si, ax
dec bl
.no_br:
dec bh
.no_downs:
mov ax, si
ret
set_cursor:
mov ah, 0x02
mov bh, 0x01
mov cx, word [cursor_x]
mov dl, cl
add dl, cl
add dl, cl
add dl, offset_x + 1
mov dh, ch
add dh, ch
add dh, offset_y + 1
int 0x10
jmp main_loop
up_arrow:
mov al, byte [cursor_y]
test al, al
jz main_loop
dec al
mov byte [cursor_y], al
call set_cursor
jmp main_loop
down_arrow:
mov al, byte [cursor_y]
cmp al, board_height - 1
je main_loop
inc al
mov byte [cursor_y], al
call set_cursor
jmp main_loop
left_arrow:
mov al, byte [cursor_x]
test al, al
jz main_loop
dec al
mov byte [cursor_x], al
call set_cursor
jmp main_loop
right_arrow:
mov al, byte [cursor_x]
cmp al, board_width - 1
je main_loop
inc al
mov byte [cursor_x], al
call set_cursor
jmp main_loop
dig:
push main_loop
do_dig:
call get_board_flags_at_cursor
test al, board_uncovered | board_flagged
jz .can_dig
ret
.can_dig:
test al, board_bomb
jnz lose
or al, board_uncovered
call set_board_flags_at_cursor
push ax
call get_cursor_vram_offset
mov di, ax
pop ax
call get_number_at_cursor
push ax
movzx bx, al
mov al, byte [bx + uncovered_numbers]
mov ah, byte [bx + uncovered_colors]
mov word [es:di], ax
mov bx, word [cursor_x]
test bh, bh
jz .top_half_block
dec bh
call bx_uncovered
inc bh
test al, al
jz .top_half_block
mov word [es:di - 80 * 2 - 2], ' '
mov word [es:di - 80 * 2], ' '
mov word [es:di - 80 * 2 + 2], ' '
jmp .middle
.top_half_block:
mov word [es:di - 80 * 2 - 2], (covered_color << 8) | 0xdc
mov word [es:di - 80 * 2], (covered_color << 8) | 0xdc
mov word [es:di - 80 * 2 + 2], (covered_color << 8) | 0xdc
.middle:
mov byte [es:di - 2 + 1], 0
mov byte [es:di + 2 + 1], 0
cmp bh, board_height - 1
je .bottom_half_block
inc bh
call bx_uncovered
dec bh
test al, al
jz .bottom_half_block
mov word [es:di + 80 * 2 - 2], ' '
mov word [es:di + 80 * 2], ' '
mov word [es:di + 80 * 2 + 2], ' '
jmp .dec_bombs
.bottom_half_block:
mov word [es:di + 80 * 2 - 2], (covered_color << 8) | 0xdf
mov word [es:di + 80 * 2], (covered_color << 8) | 0xdf
mov word [es:di + 80 * 2 + 2], (covered_color << 8) | 0xdf
.dec_bombs:
mov ax, word [non_bombs_left]
dec ax
test ax, ax
jz win
mov word [non_bombs_left], ax
pop ax
test al, al
jz .expand
ret
.expand:
mov al, byte [cursor_y]
test al, al
jz .no_up
dec al
mov byte [cursor_y], al
call do_dig
mov al, byte [cursor_y]
inc al
mov byte [cursor_y], al
.no_up:
mov al, byte [cursor_y]
cmp al, board_height - 1
je .no_down
inc al
mov byte [cursor_y], al
call do_dig
mov al, byte [cursor_y]
dec al
mov byte [cursor_y], al
.no_down:
mov al, byte [cursor_x]
test al, al
jz .no_left
dec al
mov byte [cursor_x], al
call do_dig
mov al, byte [cursor_x]
inc al
mov byte [cursor_x], al
.no_left:
mov al, byte [cursor_x]
cmp al, board_width - 1
je .no_right
inc al
mov byte [cursor_x], al
call do_dig
mov al, byte [cursor_x]
dec al
mov byte [cursor_x], al
.no_right:
ret
uncovered_colors:
db 0x08, 0x08, 0x0a, 0x0c, 0x0b, 0x0e, 0x09, 0x07, 0x0f
uncovered_numbers:
db " 12345678"
flag:
call get_board_flags_at_cursor
test al, board_uncovered
jnz main_loop
xor al, board_flagged
push ax
call get_cursor_vram_offset
mov di, ax
pop ax
call set_board_flags_at_cursor
test al, board_flagged
jz .not_flagged
mov byte [es:di], flag_character
jmp main_loop
.not_flagged:
mov byte [es:di], ' '
jmp main_loop
;as rows
board_flags:
times board_width * board_height db 0
board_bomb equ 1
board_uncovered equ 2
board_flagged equ 4
board_numbers:
times board_width * board_height db 0
get_board_flags_at_cursor:
movzx ax, byte [cursor_y]
mov cx, board_width
mul cx
movzx bx, byte [cursor_x]
add bx, ax
mov al, byte [board_flags + bx]
ret
get_cursor_vram_offset:
mov cx, word [cursor_x]
mov bl, cl
add bl, cl
add bl, cl
add bl, offset_x + 1
mov bh, ch
add bh, ch
add bh, offset_y + 1
mov cx, 80
movzx ax, bh
mul cx
xor bh, bh
add ax, bx
add ax, ax
ret
;preserves ax and di
set_board_flags_at_cursor:
mov si, ax
movzx ax, byte [cursor_y]
mov cx, board_width
mul cx
movzx bx, byte [cursor_x]
add bx, ax
mov ax, si
mov byte [board_flags + bx], al
ret
;preserves di
get_number_at_cursor:
movzx ax, byte [cursor_y]
mov cx, board_width
mul cx
movzx bx, byte [cursor_x]
add bx, ax
mov al, byte [board_numbers + bx]
ret
cursor_x:
db 0
cursor_y:
db 0
non_bombs_left:
dw 0
controls_str:
db "Controls: Arrows - Move Cursor D - Dig F - Flag Q - Quit"
.len equ $ - controls_str
win:
push ds
pop es
mov ax, 0x1300
mov bx, 0x010f
mov cx, .len
mov dx, 0x0a24
mov bp, .str
int 0x10
jmp win_or_lose
.str:
db "You win!"
.len equ $ - .str
lose:
push ds
pop es
mov ax, 0x1300
mov bx, 0x010f
mov cx, .len
mov dx, 0x0a23
mov bp, .str
int 0x10
jmp win_or_lose
.str:
db "You lose!"
.len equ $ - .str
win_or_lose:
mov ax, 0x1300
mov bx, 0x010f
mov cx, .len
mov dx, 0x0c1d
mov bp, .str
int 0x10
xor ax, ax
int 0x16
mov ax, 0x0500
int 0x10
mov ax, 0x4c00
int 0x21
.str:
db "Press any key to quit."
.len equ $ - .str
|