-
Notifications
You must be signed in to change notification settings - Fork 0
/
tetris.asm
974 lines (757 loc) · 26.8 KB
/
tetris.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
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
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
;macro HELP
clearScreen MACRO
push ax
mov ax, 0003h
int 10h
pop ax
ENDM
;end macro help
.model small
.stack 100h
.data
;key bindings (configuration)
KRotate equ 48h ;Up key
KLeft equ 4Bh ;Left key
KRight equ 4Dh ;Right key
KDrop equ 50h ;Down key
KExit equ 01h ;ESC key
xSize equ 80
ySize equ 18
xField equ 25 ;size of playground
yField equ 15
oneMemoBlock equ 2
videoStart dw 0B800h
dataStart dw 0000h
sleepTime equ 10
space equ 0020h
VWallSymbol equ 0FBAh
HWallSymbol equ 0FCDh
VWallSpecialSymbol equ 0FCCh
fieldSpacingBad equ space, VWallSymbol, xField dup(space)
fieldSpacing equ fieldSpacingBad, VWallSymbol
rbSym equ 0CFDCh ;white block with red background
rbSpc equ 0CF20h ;space with red background
grSym equ 02FDBh ;white block with green background
grSpc equ 02F20h ;space with green background
screen dw xSize dup(space)
dw space, 0FC9h, xField dup(HWallSymbol), 0FCBh, xSize - xField - 5 dup(HWallSymbol), 0FBBh, space
firstBl dw fieldSpacing, xSize - xField - 5 dup(rbSpc), VWallSymbol, space
dw fieldSpacing, 2 dup(rbSpc), 7 dup(rbSym), 3 dup(rbSpc),4 dup(rbSym), 3 dup(rbSpc), 7 dup(rbSym), 3 dup(rbSpc),3 dup(rbSym), 3 dup(rbSpc),5 dup(rbSym), 3 dup(rbSpc), 5 dup(rbSym) ,2 dup(rbSpc), VWallSymbol, space
dw fieldSpacing, 5 dup(rbSpc), rbSym, 6 dup(rbSpc),rbSym, 9 dup(rbSpc), rbSym, 6 dup(rbSpc),rbSym, 2 dup(rbSpc), rbSym, 4 dup(rbSpc), rbSym, 5 dup(rbSpc), rbSym, 6 dup(rbSpc) , VWallSymbol, space
dw fieldSpacing, 5 dup(rbSpc), rbSym, 6 dup(rbSpc),4 dup (rbSym), 6 dup(rbSpc), rbSym, 6 dup(rbSpc),3 dup (rbSym), 5 dup(rbSpc), rbSym, 5 dup(rbSpc), 5 dup (rbSym) , 2 dup(rbSpc) , VWallSymbol, space
dw fieldSpacing, 5 dup(rbSpc), rbSym, 6 dup(rbSpc),rbSym, 9 dup(rbSpc), rbSym, 6 dup(rbSpc) ,rbSym, rbSpc, rbSym,5 dup(rbSpc), rbSym, 9 dup(rbSpc), rbSym, 2 dup(rbSpc) , VWallSymbol, space
dw fieldSpacing, 5 dup(rbSpc), rbSym, 6 dup(rbSpc),4 dup (rbSym), 6 dup(rbSpc), rbSym, 6 dup(rbSpc),rbSym, 2 dup(rbSpc), rbSym, 2 dup(rbSpc), 5 dup (rbSym), 3 dup(rbSpc), 5 dup(rbSym), 2 dup(rbSpc) , VWallSymbol, space
dw fieldSpacing, xSize - xField - 5 dup(rbSpc), VWallSymbol, space
delim1 dw fieldSpacingBad, 0FCCh, xSize - xField - 5 dup(HWallSymbol), 0FB9h, space
secondF dw fieldSpacing, xSize - xField - 5 dup(grSpc), VWallSymbol, space
dw fieldSpacing, 12 dup (grSpc), 7 dup (grSym), 5 dup (grSpc),grSym, 3 dup (grSpc), grSym, 5 dup (grSpc), 4 dup (grSym), 12 dup (grSpc), VWallSymbol, space
dw fieldSpacing, 15 dup (grSpc), grSym, 8 dup (grSpc),grSym, 3 dup (grSpc), grSym, 5 dup (grSpc), grSym, 15 dup (grSpc), VWallSymbol, space
dw fieldSpacing, 15 dup (grSpc), grSym, 9 dup (grSpc),grSym, 1 dup (grSpc), grSym, 6 dup (grSpc), 4 dup (grSym), 12 dup (grSpc), VWallSymbol, space
dw fieldSpacing, 15 dup (grSpc), grSym, 9 dup (grSpc),grSym, 1 dup (grSpc), grSym, 9 dup (grSpc), grSym, 12 dup (grSpc), VWallSymbol, space
dw fieldSpacing, 15 dup (grSpc), grSym, 10 dup (grSpc),grSym, 7 dup (grSpc), 4 dup (grSym), 12 dup (grSpc), VWallSymbol, space
dw fieldSpacing, xSize - xField - 5 dup(grSpc), VWallSymbol, space
dw space, 0FC8h, xField dup(HWallSymbol), 0FCAh, xSize - xField - 5 dup(HWallSymbol), 0FBCh, space
dw xSize dup(space)
; figures
figureBlock equ 0A40h
maxViewNum equ 4
currViewNum db 0
emptyBlock equ 0
fullBlock equ 0ffh
fieldSize equ xField*yField
oneFigureBigSize equ maxViewNum*fieldSize
; save: figure - row number - column number
currentFigure db oneFigureBigSize dup(emptyBlock)
futureFigure db oneFigureBigSize dup(emptyBlock)
virtualField db fieldSize dup(emptyBlock)
numOfFigures equ 7
; квадратик
figures db xField dup(emptyBlock), 12 dup(emptyBlock), 2 dup(fullBlock), 11 dup(emptyBlock), 12 dup(emptyBlock), 2 dup(fullBlock), 11 dup(emptyBlock), (fieldSize - 3*xField) dup(emptyBlock)
db xField dup(emptyBlock), 12 dup(emptyBlock), 2 dup(fullBlock), 11 dup(emptyBlock), 12 dup(emptyBlock), 2 dup(fullBlock), 11 dup(emptyBlock), (fieldSize - 3*xField) dup(emptyBlock)
db xField dup(emptyBlock), 12 dup (emptyBlock), 2 dup (fullBlock), 11 dup (emptyBlock), 12 dup (emptyBlock), 2 dup (fullBlock), 11 dup (emptyBlock), (fieldSize - 3*xField) dup(emptyBlock)
db xField dup(emptyBlock), 12 dup (emptyBlock), 2 dup (fullBlock), 11 dup (emptyBlock), 12 dup (emptyBlock), 2 dup (fullBlock), 11 dup (emptyBlock), (fieldSize - 3*xField) dup(emptyBlock)
; I
db 2*xField dup(emptyBlock), 11 dup(emptyBlock), 4 dup(fullBlock), 10 dup(emptyBlock), (fieldSize - xField*3) dup(emptyBlock)
db 12 dup(emptyBlock), 1 dup(fullBlock), 12 dup(emptyBlock), 12 dup(emptyBlock), 1 dup(fullBlock), 12 dup(emptyBlock), 12 dup(emptyBlock), 1 dup(fullBlock), 12 dup(emptyBlock), 12 dup(emptyBlock), 1 dup(fullBlock), 12 dup(emptyBlock), (fieldSize - xField*4) dup(emptyBlock)
db xField dup(emptyBlock), 11 dup(emptyBlock), 4 dup(fullBlock), 10 dup(emptyBlock), (fieldSize - xField*2) dup(emptyBlock)
db 13 dup(emptyBlock), 1 dup(fullBlock), 11 dup(emptyBlock), 13 dup(emptyBlock), 1 dup(fullBlock), 11 dup(emptyBlock), 13 dup(emptyBlock), 1 dup(fullBlock), 11 dup(emptyBlock), 13 dup(emptyBlock), 1 dup(fullBlock), 11 dup(emptyBlock), (fieldSize - xField*4) dup(emptyBlock)
; T
db xField dup(emptyBlock), 11 dup(emptyBlock), 3 dup(fullBlock), 11 dup(emptyBlock), 12 dup(emptyBlock), 1 dup(fullBlock), 12 dup(emptyBlock), (fieldSize - xField*3) dup(emptyBlock)
db xField dup(emptyBlock), 12 dup(emptyBlock), 1 dup(fullBlock), 12 dup(emptyBlock), 12 dup(emptyBlock), 2 dup(fullBlock), 11 dup(emptyBlock), 12 dup(emptyBlock), 1 dup(fullBlock), 12 dup(emptyBlock), (fieldSize - xField*4) dup(emptyBlock)
db xField dup(emptyBlock), 13 dup(emptyBlock), 1 dup(fullBlock), 11 dup(emptyBlock), 12 dup(emptyBlock), 3 dup(fullBlock), 10 dup(emptyBlock), (fieldSize - xField*3) dup(emptyBlock)
db 13 dup(emptyBlock), 1 dup(fullBlock), 11 dup(emptyBlock), 12 dup(emptyBlock), 2 dup(fullBlock), 11 dup(emptyBlock), 13 dup(emptyBlock), 1 dup(fullBlock), 11 dup(emptyBlock), (fieldSize - xField*3) dup(emptyBlock)
; z
db xField dup(emptyBlock), 12 dup(emptyBlock), 2 dup(fullBlock), 11 dup(emptyBlock), 13 dup(emptyBlock), 2 dup(fullBlock), 10 dup(emptyBlock), (fieldSize - xField*3) dup(emptyBlock)
db xField dup(emptyBlock), 13 dup(emptyBlock), 1 dup(fullBlock), 11 dup(emptyBlock), 12 dup(emptyBlock), 2 dup(fullBlock), 11 dup(emptyBlock), 12 dup(emptyBlock), 1 dup(fullBlock), 12 dup(emptyBlock), (fieldSize - xField*4) dup(emptyBlock)
db xField dup(emptyBlock), 11 dup(emptyBlock), 2 dup(fullBlock), 12 dup(emptyBlock), 12 dup(emptyBlock), 2 dup(fullBlock), 11 dup(emptyBlock), (fieldSize - xField*3) dup(emptyBlock)
db 13 dup(emptyBlock), 1 dup(fullBlock), 11 dup(emptyBlock), 12 dup(emptyBlock), 2 dup(fullBlock), 11 dup(emptyBlock), 12 dup(emptyBlock), 1 dup(fullBlock), 12 dup(emptyBlock), (fieldSize - xField*3) dup(emptyBlock)
; z зеркальное
db xField dup(emptyBlock), 12 dup(emptyBlock), 2 dup(fullBlock), 11 dup(emptyBlock), 11 dup(emptyBlock), 2 dup(fullBlock), 12 dup(emptyBlock), (fieldSize - xField*3) dup(emptyBlock)
db 12 dup(emptyBlock), 1 dup(fullBlock), 12 dup(emptyBlock), 12 dup(emptyBlock), 2 dup(fullBlock), 11 dup(emptyBlock), 13 dup(emptyBlock), 1 dup(fullBlock), 11 dup(emptyBlock), (fieldSize - xField*3) dup(emptyBlock)
db xField dup(emptyBlock), 13 dup(emptyBlock), 2 dup(fullBlock), 10 dup(emptyBlock), 12 dup(emptyBlock), 2 dup(fullBlock), 11 dup(emptyBlock), (fieldSize - xField*3) dup(emptyBlock)
db xField dup(emptyBlock), 12 dup(emptyBlock), 1 dup(fullBlock), 12 dup(emptyBlock), 12 dup(emptyBlock), 2 dup(fullBlock), 11 dup(emptyBlock), 13 dup(emptyBlock), 1 dup(fullBlock), 11 dup(emptyBlock), (fieldSize - xField*4) dup(emptyBlock)
; Г
db xField dup(emptyBlock), 12 dup(emptyBlock), 2 dup(fullBlock), 11 dup(emptyBlock), 12 dup(emptyBlock), 1 dup(fullBlock), 12 dup(emptyBlock), 12 dup(emptyBlock), 1 dup(fullBlock), 12 dup(emptyBlock), (fieldSize - xField*4) dup(emptyBlock)
db xField dup(emptyBlock), 11 dup(emptyBlock), 3 dup(fullBlock), 11 dup(emptyBlock), 13 dup(emptyBlock), 1 dup(fullBlock), 11 dup(emptyBlock), (fieldSize - xField*3) dup(emptyBlock)
db 13 dup(emptyBlock), 1 dup(fullBlock), 11 dup(emptyBlock), 13 dup(emptyBlock), 1 dup(fullBlock), 11 dup(emptyBlock), 12 dup(emptyBlock), 2 dup(fullBlock), 11 dup(emptyBlock), (fieldSize - xField*3) dup(emptyBlock)
db xField dup(emptyBlock), 12 dup(emptyBlock), 1 dup(fullBlock), 12 dup(emptyBlock), 12 dup(emptyBlock), 3 dup(fullBlock), 10 dup(emptyBlock), (fieldSize - xField*3) dup(emptyBlock)
; Г зеркальное
db 12 dup(emptyBlock), 1 dup(fullBlock), 12 dup(emptyBlock), 12 dup(emptyBlock), 1 dup(fullBlock), 12 dup(emptyBlock), 12 dup(emptyBlock), 2 dup(fullBlock), 11 dup(emptyBlock), (fieldSize - xField*3) dup(emptyBlock)
db xField dup(emptyBlock), 12 dup(emptyBlock), 3 dup(fullBlock), 10 dup(emptyBlock), 12 dup(emptyBlock), 1 dup(fullBlock), 12 dup(emptyBlock), (fieldSize - xField*3) dup(emptyBlock)
db xField dup(emptyBlock), 12 dup(emptyBlock), 2 dup(fullBlock), 11 dup(emptyBlock), 13 dup(emptyBlock), 1 dup(fullBlock), 11 dup(emptyBlock), 13 dup(emptyBlock), 1 dup(fullBlock), 11 dup(emptyBlock), (fieldSize - xField*4) dup(emptyBlock)
db xField dup(emptyBlock), 13 dup(emptyBlock), 1 dup(fullBlock), 11 dup(emptyBlock), 11 dup(emptyBlock), 3 dup(fullBlock), 11 dup(emptyBlock), (fieldSize - xField*3) dup(emptyBlock)
.code
main:
mov ax, @data ;init
mov ds, ax
mov dataStart, ax
mov ax, videoStart
mov es, ax
xor ax, ax
clearScreen
call initAllScreen
call mainGame
to_close:
mov ah, 4ch
int 21h
;it is the end
;more macro help
;ZF = 1 - buffer is free
;AH = scan-code
CheckBuffer MACRO
mov ah, 01h
int 16h
ENDM
ReadFromBuffer MACRO
mov ah, 00h
int 16h
ENDM
;result in cx:dx
GetTimerValue MACRO
push ax
mov ax, 00h
int 1Ah
pop ax
ENDM
;end macro help
;procedure help
initAllScreen PROC
mov si, offset screen
xor di, di
mov cx, xSize*ySize
rep movsw
ret
ENDP
Sleep PROC
push ax bx cx dx
GetTimerValue
add dx, sleepTime
mov bx, dx
checkTimeLoop:
GetTimerValue
cmp dx, bx ;ax - current value, bx - needed value
jl checkTimeLoop
pop dx cx bx ax
ret
ENDP
mainGame PROC
call GenerateNewFigure
mov bx, figureBlock
call PrintCurrFigure
; Main loop
; *********
checkKeyPressing:
CheckBuffer
jz newIteration ;клавишу не нажали
ReadFromBuffer
cmp ah, KExit
je game_over
cmp ah, KLeft
je go_left
cmp ah, KRight
je go_right
cmp ah, KRotate
je go_rotate
; cmp al, KDrop
; je go_drop
; If not found key - down block & go to new iteration
newIteration:
call Down ; go down
cmp ax, 0
jne game_over
call Sleep
jmp checkKeyPressing
go_left:
call MoveLeft
jmp checkKeyPressing
go_right:
call MoveRight
jmp checkKeyPressing
go_rotate:
call Rotate
jmp checkKeyPressing
game_over:
; End Main loop
; *************
ret
ENDP
; Time random
; Input:
; ax - max value
; Result:
; ax - random number [0, max value)
Random PROC
push bx cx dx
mov bx, ax ;в bx - max value
cmp bx, 0
je quitRandom
;считываем текущее время
;ch - час, cl - минута, dh - секунда, dl - сотая доля секунды
mov ah, 2Ch
int 21h
mov al, dl
mul dh ;в ax теперь число для рандома
xor dx, dx ;чтобы не словить переполнение и получить хороший результат
div bx ;в dx - результат (случайное число);
mov ax, dx
quitRandom:
pop dx cx bx
ret
ENDP
GenerateNewFigure PROC
push ax cx dx ds es si di
mov ax, dataStart
mov ds, ax
mov es, ax
mov ax, numOfFigures
call Random
mov cx, oneFigureBigSize ;в cx - размер одной "пачки" из видов фигур
mul cx ;теперь имеем смещение фигуры относительно начала figures
mov si, offset figures
add si, ax ;получаем реальное смещение в памяти, где сгенерированная фигура
mov di, offset currentFigure ;теперь всё готово для "копирования" новой фигуры
rep movsb
;Выбираем вид фигуры
mov ax, maxViewNum
call Random
mov currViewNum, al ;сохраняем индекс текущего вида
pop di si es ds dx cx ax
ret
ENDP
; Input:
; bx - symbol how to print current figure
PrintCurrFigure PROC
push ax cx ds es si di
mov ax, videoStart
mov es, ax
mov ax, dataStart
mov ds, ax
call getCurrentFigure
mov ax, 2*(2*xSize + 2) ;пропускаем 2 первые строки + 2 певых символа третьей строки (становимся в левый верхний угол поля)
mov di, ax
mov cx, yField
loopAllRows:
push cx
mov cx, xField
loopOneRow:
mov al, [si]
cmp al, emptyBlock
je skipWriteBlock
mov word ptr es:[di], bx
skipWriteBlock:
inc si
add di, 2 ;т.к. каждый символ занимает 2 байта в видеопамяти
loop loopOneRow
add di, 2*(xSize - xField) ;для перехода в начало следующей строки
pop cx
loop loopAllRows
pop di si es ds cx ax
ret
ENDP
; Down block for one position
; If need - generate new one
; Return:
; ax = 0 - all is good
; ax = 1 - no more plase in field
Down proc
push cx si ds
call MoveDown
cmp ax, 0
je goodQuit
call copyCurrentFigureToVirtualField
call DeleteRows
call GenerateNewFigure
mov bx, figureBlock
call PrintCurrFigure
mov ax, dataStart
mov ds, ax
call getCurrentFigure
call checkFigureForCrossing
jmp DownToQuit
goodQuit:
mov ax, 0
DownToQuit:
pop ds si cx
ret
endp
; Input:
; ds:si - starting pos to compare
; Return:
; ax = 0 - all is good (not crossing)
; ax != 0 - crossing
checkFigureForCrossing PROC
push cx es di
mov ax, dataStart
mov es, ax
mov di, offset virtualField
mov cx, fieldSize
checkCrossingLoop:
mov al, [si]
and al, [di]
jnz quitCrossingProcBad
inc si
inc di
loop checkCrossingLoop
mov ax, 0
jmp quitCrossingProc
quitCrossingProcBad:
mov ax, 1
quitCrossingProc:
pop di es cx
ret
ENDP
DeleteRows proc
push ax cx ds es si di
mov ax, dataStart
mov ds, ax
mov es, ax
;save current virtual field to currentFigure
call getCurrentFigure
mov di, si
mov ax, offset virtualField
mov si, ax
rep movsb
;hide field
mov bx, emptyBlock
call PrintCurrFigure
;todo: change field in currentFigure
mov cx, yField
;get current field to check
call getCurrentFigure
mov di, si
xor dl, dl
DeleteRowsLoopAllRows:
push cx
mov ah, xField
mov al, dl
mov bl, fullBlock
call CheckRowForEmpty
cmp ax, 0
jne DeleteRowsLoopAllRowsEnd
;если попали сюда -> строку нужно удалить
mov ah, xField
mov al, dl
mov bl, emptyBlock
call DeleteOneRow
DeleteRowsLoopAllRowsEnd:
inc dl
pop cx
loop DeleteRowsLoopAllRows
;show field
mov bx, figureBlock
call PrintCurrFigure
;save field with deleted rows back
call getCurrentFigure
mov ax, offset virtualField
mov di, ax
rep movsb
pop di si es ds cx ax
ret
endp
; Input:
; es:di - start of requring block
; al - number of requring row (start indexing from 0)
; ah - length of each row
; bl - what will be empty symbol
DeleteOneRow PROC
push ax cx si di
pushf
xor ch, ch
mov cl, ah
xor ah, ah
mul cl ;теперь в ax смещение от начала поля
add di, ax ;становимся в начало строки для удаления
dec di ;теперь мы на первой неудаляемом символе
mov si, di ;это - источник
add di, cx ;становимся на последний удаляемый символ
push cx ;сохраняем размер одной строки
sub ax, cx ;отнимаем лишнюю строку
mov cx, ax ;устанавливаем количество итераций (на одну строку меньше пока что)
std ;двигаемся с конца в начало
rep movsb
;перезаписали основную часть. Теперь нужно занулить верхнюю строку
pop cx ;сколько символов нужно заменить на пустые
mov al, bl
repe movsb
;заменили и верхнюю строку
popf
pop di si cx ax
ret
ENDP
; Input:
; es:di - start of requring block
; al - number of requring row (start indexing from 0)
; ah - length of each row
; bl - what will be empty symbol
; Output:
; ax = 0 - row is empty
; ax != 0 - row is not empty
CheckRowForEmpty PROC
push cx di
pushf
xor ch, ch
mov cl, ah
xor ah, ah
mul cl ;теперь в ax смещение от начала поля
add di, ax ;становимся в начало требуемой строки
cld ;двигаемся с начала в конец
mov al, bl
repe scasb
dec di ;возврат у предыдущему символу
xor ah, ah
sub al, es:[di] ;если символы совпадут - разница будет 0
popf
pop di cx
ret
ENDP
; Input:
; es:di - start of requring block
; Output:
; ax = 0 - row is empty
; ax != 0 - row is not empty
CheckDownRowForEmpty PROC
mov al, yField - 1
mov ah, xField
mov bl, emptyBlock
call CheckRowForEmpty
ret
ENDP
; Output:
; ax = 0 - all is good (we do that)
; ax != 0 - we cannot do that
MoveDown proc
push cx ds es si di
mov ax, dataStart
mov ds, ax
mov es, ax
call getCurrentFigure
mov di, si ;для сравнения
call CheckDownRowForEmpty
cmp ax, 0 ;уточняем, пустая ли нижняя строка
jne MoveDownErrorExit
;теперь нужно опустить всю группу видов, проверяя на "пересечение" с полом (низом поля)
mov cx, maxViewNum
mov si, offset currentFigure
mov di, offset futureFigure
loopMoveDownAllBlocks:
push cx
push di
mov di, si
call CheckDownRowForEmpty
pop di
cmp ax, 0 ;уточняем, пустая ли нижняя строка
jne MoveDownWriteFullFieldView
;обнуляем верхнюю строку в futureFigure (для каждого поля, которое можем опустить)
mov cx, xField
mov al, emptyBlock
rep stosb
;теперь нужно пеерзаписать поле
mov cx, fieldSize - xField
rep movsb
add si, xField
;si и di готовы к следующей итерации
jmp MoveDownContinueLoop
MoveDownWriteFullFieldView:
mov cx, fieldSize
rep movsb
;si и di готовы к следующей итерации
MoveDownContinueLoop:
pop cx
loop loopMoveDownAllBlocks
call getCurrentFigure
add si, offset futureFigure - offset currentFigure
;теперь в si адрес новой версии фигуры
call checkFigureForCrossing
cmp ax, 0
jne MoveDownErrorExit
;дошли сюда - значит текущий вид можно спокойно опускать
;удаляем старое
mov bx, emptyBlock
call PrintCurrFigure
mov cx, oneFigureBigSize
mov si, offset futureFigure
mov di, offset currentFigure
rep movsb
;печатаем новое
mov bx, figureBlock
call PrintCurrFigure
jmp MoveDownSucceedExit
MoveDownErrorExit:
mov ax, 1
jmp MoveDownExit
MoveDownSucceedExit:
mov ax, 0
MoveDownExit:
pop di si es ds cx
ret
endp
Rotate proc
push ax bx ds si
mov ax, dataStart
mov ds, ax
mov bx, space ;delete old figure
call PrintCurrFigure
;change current figure index
inc currViewNum
mov al, currViewNum
cmp al, maxViewNum
jl skipNulling
mov currViewNum, 0 ;loop indexing
skipNulling:
call getCurrentFigure
call checkFigureForCrossing
cmp ax, 0
je SkipRevertRotate
;change current figure index (revert)
dec currViewNum
mov al, currViewNum
cmp al, 0
jge SkipRevertRotate
mov currViewNum, maxViewNum - 1 ;loop indexing
SkipRevertRotate:
mov bx, figureBlock ;print new view of figure
call PrintCurrFigure
pop si ds bx ax
ret
endp
copyCurrentFigureToVirtualField PROC
push ax cx dx ds es si di
mov ax, dataStart
mov ds, ax
mov es, ax
call getCurrentFigure
mov di, offset virtualField
;сам процесс дозаписи
loopAddFigure:
mov al, ds:[si]
or es:[di], al ;переписали, если что-то где-то было
inc si
inc di
loop loopAddFigure
pop di si es ds dx cx ax
ret
ENDP
; Return:
; si - offset of current figure
; cx - current figure size
getCurrentFigure PROC
push ax
xor ah, ah
mov al, currViewNum
mov cx, fieldSize ;в cx - размер одного вида фигур
mul cx ;теперь имеем смещение фигуры относительно начала currentFigure
mov si, offset currentFigure
add si, ax ;получаем реальное смещение в памяти, где сгенерированная фигура
pop ax
ret
ENDP
;------------------------------------------------MOVE LEFT-----------------------------
; Input:
; es:di - start of requring block
; Output:
; ax = 0 - column is empty
; ax != 0 - column is not empty
CheckLeftColumnForEmpty PROC
push cx di
pushf
cld ;двигаемся с начала в конец
mov cx, yField
mov al, emptyBlock
checkLeftColumnLoop:
cmp al, es:[di]
jne checkLeftColumnEndLoop
add di, xField
loop checkLeftColumnLoop
checkLeftColumnEndLoop:
mov ax, cx ;записываем количество несверенных символов (0 => ничего не нашли)
popf
pop di cx
ret
ENDP
; Output:
; ax = 0 - all is good (we do that)
; ax != 0 - we cannot do that
MoveLeft proc
push cx ds es si di
mov ax, dataStart
mov ds, ax
mov es, ax
call getCurrentFigure
mov di, si ;для сравнения
call CheckLeftColumnForEmpty
cmp ax, 0 ;уточняем, пустая ли нижняя строка
jne MoveLeftErrorExit
;теперь нужно подвинуть влево всю группу видов, проверяя на "пересечение" с полом (низом поля)
mov cx, maxViewNum
mov si, offset currentFigure
mov di, offset futureFigure
loopMoveLeftAllBlocks:
push cx
push di
mov di, si
call CheckLeftColumnForEmpty
pop di
cmp ax, 0 ;уточняем, пустая ли нижняя строка
jne MoveLeftWriteFullFieldView
;нужно перезаписать поле
inc si
cld ;движение слева направо (это очень важно)
mov cx, fieldSize - 1
rep movsb
;обнуляем правый нижний угол в futureFigure (для каждого поля, которое можем подвинуть)
mov al, emptyBlock
mov es:[di], al
inc di
;si и di готовы к следующей итерации
jmp MoveLeftContinueLoop
MoveLeftWriteFullFieldView:
mov cx, fieldSize
rep movsb
;si и di готовы к следующей итерации
MoveLeftContinueLoop:
pop cx
loop loopMoveLeftAllBlocks
call getCurrentFigure
add si, offset futureFigure - offset currentFigure
;теперь в si адрес новой версии фигуры
call checkFigureForCrossing
cmp ax, 0
jne MoveLeftErrorExit
;дошли сюда - значит текущий вид можно спокойно двигать влево
;удаляем старое
mov bx, emptyBlock
call PrintCurrFigure
;переписываем все поле из future в current
mov cx, oneFigureBigSize
mov si, offset futureFigure
mov di, offset currentFigure
rep movsb
;печатаем новое
mov bx, figureBlock
call PrintCurrFigure
jmp MoveLeftSucceedExit
MoveLeftErrorExit:
mov ax, 1
jmp MoveLeftExit
MoveLeftSucceedExit:
mov ax, 0
MoveLeftExit:
pop di si es ds cx
ret
endp
;------------------------------------------MOVE RIGHT------------------------
; Input:
; es:di - start of requring block
; Output:
; ax = 0 - column is empty
; ax != 0 - column is not empty
CheckRightColumnForEmpty PROC
push cx di
pushf
cld ;двигаемся с начала в конец
mov cx, yField
mov al, emptyBlock
add di, xField - 1 ;становимся в конец строки
checkRightColumnLoop:
cmp al, es:[di]
jne checkRightColumnEndLoop
add di, xField
loop checkRightColumnLoop
checkRightColumnEndLoop:
mov ax, cx ;записываем количество несверенных символов (0 => ничего не нашли)
popf
pop di cx
ret
ENDP
; Output:
; ax = 0 - all is good (we do that)
; ax != 0 - we cannot do that
MoveRight proc
push cx ds es si di
mov ax, dataStart
mov ds, ax
mov es, ax
call getCurrentFigure
mov di, si ;для сравнения
call CheckRightColumnForEmpty
cmp ax, 0 ;уточняем, пустая ли нижняя строка
jne MoveRightErrorExit
;теперь нужно подвинуть вправо всю группу видов, проверяя на "пересечение" с полом (низом поля)
mov cx, maxViewNum
mov si, offset currentFigure
mov di, offset futureFigure
loopMoveRightAllBlocks:
push cx
push di
mov di, si
call CheckRightColumnForEmpty
pop di
cmp ax, 0 ;уточняем, пустая ли нижняя строка
jne MoveRightWriteFullFieldView
;обнуляем левый верхний угол в futureFigure (для каждого поля, которое можем подвинуть)
mov al, emptyBlock
mov es:[di], al
;нужно перезаписать поле
inc di
cld ;движение слева направо (т.к. разные поля, можем себе позволить)
mov cx, fieldSize - 1
rep movsb
inc si
;si и di готовы к следующей итерации
jmp MoveRightContinueLoop
MoveRightWriteFullFieldView:
mov cx, fieldSize
rep movsb
;si и di готовы к следующей итерации
MoveRightContinueLoop:
pop cx
loop loopMoveRightAllBlocks
call getCurrentFigure
add si, offset futureFigure - offset currentFigure
;теперь в si адрес новой версии фигуры
call checkFigureForCrossing
cmp ax, 0
jne MoveRightErrorExit
;дошли сюда - значит текущий вид можно спокойно двигать влево
;удаляем старое
mov bx, emptyBlock
call PrintCurrFigure
;переписываем все поле из future в current
mov cx, oneFigureBigSize
mov si, offset futureFigure
mov di, offset currentFigure
rep movsb
;печатаем новое
mov bx, figureBlock
call PrintCurrFigure
jmp MoveRightSucceedExit
MoveRightErrorExit:
mov ax, 1
jmp MoveRightExit
MoveRightSucceedExit:
mov ax, 0
MoveRightExit:
pop di si es ds cx
ret
endp
end main