Subversion Repositories Kolibri OS

Rev

Rev 1934 | Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1806 yogev_ezra 1
; SOKOBAN FOR MENUET v0.1
2
; Written in pure assembler by Ivushkin Andrey aka Willow
3
;
4
; Last changed: July 2, 2004
5
;
6
; Main idea, art & graphics
7
;   Sokofun for Windows 95 by Games 4 Brains
8
;   and Sokoban 2.3 by BjЎrn Kфllmark
9
;
10
; Level designers:
11
;
12
;   Alberto Garcia, Aymeric du Peloux, Brian Kent, David Holland,
13
;   David W Skinner, Erim Sever, Evgeniy Grigoriev, Franчois Marques,
14
;   Frantisek Pokorny, Howard Abed,J franklin Mentzer, Jaques Duthen,
15
;   John C Davis, John Polhemus, Kobus Theron, Lee Haywood, Mario Bonenfant,
16
;   Martin P Holland, Mic (Jan Reineke), Phil Shapiro, Richard Weston,
17
;   Sven Egevad, Ken'ichiro Takahashi (takaken), Thinking Rabbit,
18
;   Yoshio Murase, ZICO (Zbigniew Kornas)
19
;
20
; Special thanks to Hirohiko Nakamiya
21
;
22
; More credits:
23
;   Masato Hiramatsu, Kazuo Fukushima, Klaus Clemens
24
;
25
; Game uses its own format of levelset files *.LEV
26
;   with simple run-length compression
27
 
28
; COMPILE WITH FASM
29
 
30
CUR_DIR equ '/HD/1/MENUETOS/' ; change it to appropriate path
31
 
32
SKIN_SIZE equ 11520         ; size of skin file (16x240)
33
 
34
; field dimensions
35
FLD_LEFT equ 43
36
FLD_LEFT2 equ FLD_LEFT shl 16
37
FLD_TOP equ 40
38
FLD_TOP2 equ FLD_TOP shl 16
39
IMG_SIZE equ 16 shl 16+16
40
SHIFT equ (16 shl 16)
41
WND_COLOR equ 0x03aabbcc
42
 
43
; level list dimensions
44
LEVLIST_XY equ FLD_TOP shl 16+45
45
LEVLIST_SPACING equ 10
46
LEVWND_X equ 320
47
LEVWND_Y equ 200
48
 
49
; input line dimensions
50
INP_X equ 10 shl 16+300
51
INP_Y equ 160 shl 16+16
52
INP_XY equ 15 shl 16+164
53
 
54
; load button dimensions
55
LOAD_X equ 130 shl 16+65
56
LOAD_Y equ 180 shl 16+14
57
LOAD_XY equ 135 shl 16+184
58
CHOOSE_XY equ 40 shl 16+148
59
 
60
 
61
WIN_XY equ 135 shl 16+25
62
 
63
; workmode constants, more defs in CELLTYPE.INC
64
WM_WINNER  equ 0x10
65
WM_READSET equ 0
66
WM_LOSE    equ 0x20
67
 
68
use32
69
  org    0x0
70
  db     'MENUET01'
71
  dd     0x01
72
  dd     START
73
  dd     I_END
74
  dd     0x100000
75
  dd     0x7fff0
76
  dd     0x0
77
  dd     0x0
78
 
79
include 'macros.inc'    ; decrease code size (optional)
80
include 'celltype.inc'  ; object identifiers
81
;include 'debug.inc'
82
;lang equ ru             ; russian interface; english if undefined
83
 
84
START:
85
    mov  eax,58         ; load skin image-it is in RAW 16x240 BGR
86
    mov  ebx,file_info  ; IrfanView recommended
87
    int  0x40
88
    test ebx,ebx
89
;    jmp load_level
90
;    jz   close
91
  load_fail:            ; clear input line, also if levelset load failed
92
    mov  [inp_pos],0
93
  load_std:
94
    mov  esi,stdlev
95
    mov  edi,path_end
96
    mov  ecx,stdlev_len-stdlev
97
    rep  movsb
98
    mov  ecx,10
99
  reset_fi:
100
    mov  dword[cnf_level],level_start
101
    xor  eax,eax
102
    mov  [levpage],eax
103
    mov  word[ll_num],'00'   ; reset some counters
104
  read_cnf:
105
    mov  eax,58
106
    mov  ebx,file_info
107
    int  0x40
108
    test ebx,ebx        ; load standard levels SOKO-?.LEV instead of custom
109
    jz   nxt_cnf
110
    add  dword[cnf_level],ebx
111
  nxt_cnf:
112
    test ecx,ecx        ; this check is for loading a custom levelset
113
    jz   no_increase
114
    inc  byte[file_num] ; next standard levelset
115
    loop read_cnf
116
  no_increase:
117
    cmp  dword[cnf_level],level_start
118
    jne  go_on
119
    test ecx,ecx
120
    jz   load_fail
121
    jmp  close          ; missing standard levels & exiting
122
  go_on:
123
    mov  eax,[cnf_level]
124
    mov  byte[eax],0xf0 ; end-of-levels mark
125
 
126
    call read_levelset
127
  backto_set:
128
    mov  byte[workmode],WM_READSET
129
    mov  byte[winmode],0
130
    jmp  red
131
restart_level:
132
    call decode_field   ; uncompress level
133
 
134
red:
135
    call draw_window
136
 
137
still:
138
 
139
    mov  eax,10
140
    int  0x40
141
    cmp  byte[winmode],WM_WINNER
142
    je   backto_set
143
    cmp  byte[winmode],WM_LOSE
144
    je   backto_set
145
    cmp  eax,1
146
    je   red
147
    cmp  eax,2
148
    je   key
149
    cmp  eax,3
150
    je   button
151
 
152
    jmp  still
153
 
154
  key:
155
    mov  eax,2
156
    int  0x40
157
 
158
    cmp  byte[workmode],WM_READSET
159
    jne  key_move
160
    cmp  ah,32          ; Space moves focus to input line
161
    je   is_input
162
    cmp  ah,184
163
    jne  no_prev
164
    cmp  [levpage],0    ; PgUp
165
    jz   still
166
    sub  [levpage],10
167
    cmp  byte[ll_num+1],'0'
168
    jnz  _pu
169
    dec  byte[ll_num]
170
    mov  byte[ll_num+1],'9'+1
171
  _pu:
172
    dec  byte[ll_num+1]
173
    jmp  red
174
  no_prev:
175
    cmp  ah,183         ; PgDn
176
    jne  no_next
177
    mov  eax,[levpage]
178
    add  eax,10
179
    cmp  eax,[levelcount]
180
    jae  still
181
    mov  [levpage],eax
182
    cmp  byte[ll_num+1],'9'
183
    jnz  _pd
184
    inc  byte[ll_num]
185
    mov  byte[ll_num+1],'0'-1
186
  _pd:
187
    inc  byte[ll_num+1]
188
    jmp  red
189
  no_next:
190
    sub  ah,48
191
    cmp  ah,9
192
    ja   still
193
    movzx eax,ah        ; user selects a level
194
    add  eax,[levpage]
195
    cmp  eax,[levelcount]
196
    jae  still
197
    mov  eax,[levelmap+eax*4]
198
    mov  [levptr],eax   ; current level pointer
199
    mov  al,byte[eax]
200
    mov  byte[workmode],al
201
    jmp  restart_level
202
 
203
    ; we're already in game
204
  key_move:
205
    cmp  ah,180        ; Home
206
    je   backto_set
207
    cmp  ah,176
208
    jb   no_arrows
209
    sub  ah,176
210
    cmp  ah,3
211
    ja   no_arrows
212
    movzx ecx,ah
213
    movzx edx,[player]
214
    inc  ch
215
    call valid_move
216
    cmp  byte[winmode],WM_WINNER
217
    jne  no_winner
218
    mov  ecx,0x20ac0000
219
    mov  edx,win_msg
220
    mov  esi,win_msg_end-win_msg   ; print victory congratulations
221
  print_msg:
222
    mov  ebx,WIN_XY
223
    mov  eax,4
224
    int  0x40
225
    jmp  d_f
226
  no_winner:
227
    cmp  byte[winmode],WM_LOSE
228
    jne  d_f
229
  no_loser:
230
    test  al,al         ; no move accepted
231
    jnz   still
232
  d_f:
233
    call draw_field     ; move performed-redraw
234
    jmp  still
235
  no_arrows:
236
    cmp  ah,27
237
    je   restart_level
238
 
239
    jmp  still
240
 
241
  button:
242
    mov  eax,17
243
    int  0x40
244
 
245
    cmp  ah,1
246
    jne  noclose
247
  close:
248
    xor  eax,eax
249
    dec  eax
250
    int  0x40           ; shutdown.
251
 
252
  noclose:
253
    cmp  ah,2
254
    jne  no_input
255
  is_input:             ; simple input line with backspace feature
256
    mov  ebx,[entered]  ; sorry - no cursor
257
    test ebx,ebx
258
    jnz  wait_input
259
    mov  [inp_pos],ebx
260
    inc  [entered]
261
  wait_input:
262
    call draw_input
263
    mov  eax,10
264
    int  0x40
265
    cmp  eax,2
266
    jne  still
267
    mov  edi,[inp_pos]
268
    mov  eax,2
269
    int  0x40
270
    shr  eax,8
271
    cmp  eax,27
272
    je   still
273
    cmp  eax,13
274
    je   load_level
275
    cmp  eax,8
276
    je   backsp
277
    mov  [fn_input+edi],al
278
    inc  [inp_pos]
279
    jmp  wait_input
280
  backsp:
281
    test edi,edi
282
    jz   wait_input
283
    dec  [inp_pos]
284
    jmp  wait_input
285
  no_input:
286
    cmp  ah,3
287
    jne  no_load
288
  load_level:
289
    mov  ecx,[inp_pos]
290
    test ecx,ecx
291
    je   load_std
292
    mov  esi,fn_input
293
    mov  byte[esi+ecx],0
294
    inc  ecx
295
    mov  edi,path_end
296
    rep  movsb
297
    jmp  reset_fi
298
  no_load:
299
    jmp  still
300
 
301
 
302
;   *********************************************
303
;   ** FILLS LEVEL POINTER MAP ******************
304
;   *********************************************
305
read_levelset:
306
 
307
    mov  dword[wnd_width],LEVWND_X
308
    mov  dword[wnd_height],LEVWND_Y
309
    mov  [levelcount],0
310
    mov  edi,level_start
311
    mov  esi,levelmap
312
    mov  al,0xff
313
  rls_cycle:
314
    cmp  byte[edi],EOF
315
    je   end_of_levelset
316
    mov  [esi],edi
317
    add  esi,4
318
    mov  ecx,1024
319
    inc  [levelcount]
320
    repne scasb
321
    jecxz eol  ;end_of_levelset
322
    jmp  rls_cycle
323
  end_of_levelset:
324
    mov  eax,[levelcount]
325
;    debug_print_dec eax
326
    ret
327
  eol:
328
;   debug_print '*** '
329
    jmp  end_of_levelset
330
 
331
;   *********************************************
332
;   *******  DEFINE & DRAW WINDOW & OTHER STUFF *
333
;   *********************************************
334
 
335
draw_window:
336
 
337
    mov  eax,12
338
    mov  ebx,1
339
    int  0x40
340
 
341
    mov  eax,0
342
    mov  ebx,150*65536
343
    add  ebx,[wnd_width]
344
    mov  ecx,50*65536
345
    add  ecx,[wnd_height]
346
    mov  edx,WND_COLOR
347
    mov  esi,0x805080d0
348
    mov  edi,0x005080d0
349
    int  0x40
350
 
351
    mov  eax,4
352
    mov  ebx,8*65536+8
353
    mov  ecx,0x10ddeeff
354
    mov  edx,zagolovok
355
    mov  esi,zag_konets-zagolovok
356
    int  0x40
357
 
358
    cmp  byte[workmode],WM_READSET
359
    je   list_levels
360
 
361
    mov  edi,[levptr]   ; print custom level filename
362
    add  ebx,170*65536
363
    lea  edx,[edi+4]
364
    movzx  esi,byte[edi+3]
365
    int  0x40
366
 
367
    call draw_field
368
    cmp  [entered],0
369
    jz   end_of_draw
370
    mov  edx,fn_input   ; print input line text
371
    mov  esi,[inp_pos]
372
    mov  ebx,FLD_LEFT2+FLD_TOP-15
373
    jmp  draw_level_file
374
 
375
  list_levels:
376
 
377
    call draw_input
378
 
379
    mov  eax,8          ; draw load button
380
    mov  ebx,LOAD_X
381
    mov  ecx,LOAD_Y
382
    mov  edx,3
383
    mov  esi,WND_COLOR
384
    int  0x40
385
 
386
    mov  eax,4
387
    mov  ecx,0x20107a30
388
    mov  ebx,LOAD_XY
389
    mov  edx,load_char
390
    mov  esi,loadlen-load_char
391
    int  0x40
392
 
393
    mov  ebx,LEVLIST_XY
394
    mov  edi,0x204e00e7
395
    xor  esi,esi
396
    mov  ecx,10
397
  ll_cycle:
398
    push ecx esi ebx esi
399
    lea  ecx,[esi+'0']
400
    mov  [ll_num+2],cl
401
    mov  ecx,edi
402
    mov  edx,ll_num
403
    mov  esi,4
404
    int  0x40
405
    add  ebx,25 shl 16
406
    pop  esi
407
    add  esi,[levpage]
408
    mov  edx,[levelmap+esi*4]
409
    add  edx,4
410
    movzx esi,byte[edx-1]
411
    int  0x40
412
    pop  ebx esi ecx
413
    inc  esi
414
    mov  edx,[levelcount]
415
    sub  edx,[levpage]
416
    cmp  edx,esi
417
    jbe  choose_print
418
    add  ebx,LEVLIST_SPACING
419
    loop ll_cycle
420
  choose_print:
421
    mov  edx,ll_msg
422
    mov  esi,ll_msg_end-ll_msg
423
    mov  ebx,CHOOSE_XY
424
  draw_level_file:
425
    mov  eax,4
426
    int  0x40
427
 
428
  end_of_draw:
429
    mov  eax,12
430
    mov  ebx,2
431
    int  0x40
432
 
433
    ret
434
 
435
;   *********************************************
436
;   ******* DRAW CELL IMAGES WITHIN FIELD *******
437
;   *********************************************
438
 
439
draw_field:
440
    cmp  byte[workmode],sSokonex
441
    jne  no_chl
442
    call check_lasers   ; Sokonex game
443
  no_chl:
444
    mov  eax,13         ; clear field area
445
    mov  edx,WND_COLOR
446
    mov  edi,[levptr]
447
    movzx ebx,byte[edi+1]
448
    shl  ebx,4
449
    lea  ebx, [FLD_LEFT2+ebx]
450
    movzx ecx,byte[edi+2]
451
    shl  ecx,4
452
    lea  ecx, [FLD_TOP shl 16+ecx]
453
    int  0x40
454
 
455
    mov  edx, FLD_LEFT2+FLD_TOP
456
    movzx edi,byte[edi+1]
457
    shl  edi,20
458
    add  edi, FLD_LEFT2
459
 
460
    xor  eax,eax
461
    mov  ecx,[fld_size]
462
    mov  esi,field
463
  fld_cycle:
464
    lodsb
465
    call draw_img
466
    add  edx,SHIFT
467
    cmp  edx,edi
468
    jl  no_nl
469
    add  edx,16
470
    and  edx,0xffff
471
    add  edx,FLD_LEFT2
472
  no_nl:
473
    loop fld_cycle
474
    cmp  byte[workmode],sSokonex
475
    jne  end_of_df
476
    call draw_lasers
477
  end_of_df:
478
    ret
479
 
480
;   *********************************************
481
;   *********** DRAW CELL IMAGE *****************
482
;   *********************************************
483
 
484
draw_img:               ; in: eax-object index, edx-coordinates
485
    pusha
486
    cmp  eax,tWall
487
    jbe  no_adjust
488
    cmp  [workmode],sSokolor
489
    jne  no_di_color
490
    add  eax,pm_col-pm_nex
491
    jmp  no_adjust
492
  no_di_color:
493
    cmp  [workmode],sSokonex
494
    jne  no_adjust
495
    inc  eax
496
  no_adjust:
497
    movzx  ebx,byte [pic_map+eax]
498
    cmp  ebx,0xf
499
    je   no_img
500
  bl_place:
501
    mov  ecx, IMG_SIZE
502
    imul ebx, 256*3
503
    add  ebx,strip
504
    mov  eax,7          ; draw_image sysfunc
505
    int  0x40
506
  no_img:
507
    popa
508
    ret
509
 
510
;****************************************
511
;******* DRAW CONTENTS OF INPUT LINE ****
512
;****************************************
513
draw_input:
514
    push edi
515
    cmp  eax,4
516
    jne  highlight
517
    mov  esi,WND_COLOR
518
    jmp  di_draw
519
  highlight:
520
    mov  esi,0xe0e0e0
521
  di_draw:
522
    mov  eax,8
523
    mov  ebx,INP_X
524
    mov  ecx,INP_Y
525
    mov  edx,2
526
    int  0x40
527
    mov  eax,4
528
    mov  ecx,0x00107a30            ; шрифт 1 и цвет ( 0xF0RRGGBB )
529
    mov  ebx,INP_XY
530
    mov  edx,fn_input
531
    mov  esi,[inp_pos]
532
    int  0x40
533
    pop  edi
534
    ret
535
 
536
;   ********************************************************
537
;   * DECOMPRESS LEVEL & FILL SOME TABLES TO CHECK VICTORY *
538
;   ********************************************************
539
 
540
decode_field:
541
;    debug_print <13,10>
542
    xor  eax,eax
543
    mov  dword[checkpoint],eax
544
    mov  dword[checkpoint+4],eax
545
    mov  byte[checkcount],al
546
    mov  edi,[levptr]
547
    mov  dl,[edi]
548
    mov  [workmode],dl
549
    movzx  edx,byte[edi+1]
550
    mov  esi,edx
551
    shl  esi,4
552
    add  esi,FLD_LEFT*2-25
553
    mov  [wnd_width],esi
554
    neg  edx
555
    mov  [move_map+8],edx
556
    neg  edx
557
    mov  [move_map+4],edx
558
    movzx eax,byte[edi+2]
559
    mov  esi,eax
560
    shl  esi,4
561
    add  esi,FLD_TOP*2-18
562
    mov  [wnd_height],esi
563
    imul edx,eax
564
    mov  [fld_size],edx
565
    lea  esi,[edi+4]
566
    movzx ecx,byte[edi+3]
567
    add  esi,ecx
568
    cmp  byte[esi],0xff
569
    je   backto_set
570
    xor  edi,edi
571
    cld
572
 dec_cycle:
573
    lodsb
574
    movzx ecx,al
575
    and  ecx,0xf                   ; ecx-count of objects
576
    shr  al,4                      ; eax-index of object
577
    inc  ecx
578
    sub  edx,ecx
579
  dc_cycle:
580
    mov  [field+edi],al
581
    call chk_win_obj
582
    jne  no_register
583
    push eax ecx esi
584
    movzx ecx,al
585
    shl  eax,12
586
    or   eax,edi
587
    inc  byte[checkcount]
588
    cmp  [workmode],sSokolor
589
    jne  chk_sokoban
590
;    debug_print ':'
591
;    debug_print_dec ecx
592
    sub  ecx,tRedB
593
    shl  ecx,1
594
    cmp  word[checkpoint+ecx],0
595
    jnz  no_new_check
596
    mov  [checkpoint+ecx],ax
597
    and  eax,0xfff
598
;    debug_print_dec eax
599
    jmp  no_new_check
600
  chk_sokoban:
601
    cmp  [workmode],sSokonex
602
    jne  no_nex
603
    cmp  byte[checkcount],1
604
    ja   no_new_check
605
  no_nex:
606
    movzx ecx,byte[checkcount]
607
    mov  word[checkpoint-2+ecx*2],ax
608
  no_new_check:
609
    pop  esi ecx eax
610
  no_register:
611
    inc  edi
612
    loop dc_cycle
613
    cmp  edx,0
614
    jg   dec_cycle
615
    mov  ecx,[fld_size]
616
    xor  edx,edx
617
  fp_cycle:
618
    mov  al,[field+edx]
619
    and  al,0xfe
620
    cmp  al,tPlayer
621
    je   pl_found
622
    inc  edx
623
    loop fp_cycle
624
  pl_found:
625
    mov  [player],dx
626
    movzx eax,byte[checkcount]
627
;    debug_print_dec eax
628
    ret
629
 
630
;   *********************************************
631
;   * WHETHER OBJECT IS VICTORY DEPENDENT *******
632
;   *********************************************
633
 
634
chk_win_obj:             ; al-object in a cell
635
    push ecx eax
636
    and  al,0xf
637
    mov  cl,[workmode]
638
    cmp  cl,sSokoban
639
    jne  nota_sokoban
640
    cmp  al,tBlock
641
    jmp  cwo_exit
642
  nota_sokoban:
643
    cmp  cl,sSokonex
644
    jne  nota_sokonex
645
    cmp  al,tConnect
646
    je   cwo_exit
647
    cmp  al,tStConnect
648
    jmp  cwo_exit
649
  nota_sokonex:
650
    push eax
651
    and  eax,tRedB
652
    cmp  eax,tRedB
653
    pop  eax
654
  cwo_exit:
655
    pop  eax ecx
656
    ret
657
 
658
;   *********************************************
659
;   ***** GET CELL AT CERTAIN DIRECTION *********
660
;   *********************************************
661
 
662
get_cell_at:            ; in:  dx - current cell, cl - direction
663
    mov  ebx,edx        ; out: al - object at direction, bx - new position
664
    movzx eax,cl
665
    and  eax,11b
666
    mov  eax, [move_map+eax*4]
667
    add  ebx,eax
668
    mov  al,[field+ebx]
669
    ret
670
 
671
;   *********************************************
672
;   *** WHETHER A MOVE CAN BE DONE, & DO IT *****
673
;   *********************************************
674
 
675
valid_move:                         ; in:  dx - current cell, cl - direction
676
    push edx esi
677
    call get_cell_at                ; if ch>0 perform all moves
678
    cmp  al,tWall
679
    jb   result_ok
680
    je   vm_exit
681
    cmp  [workmode],sSokonex
682
    jne  n_vm_nex
683
    cmp  al,tStConnect
684
    je   vm_exit
685
    cmp  al,tHole
686
    je   vm_exit
687
  n_vm_nex:
688
    push edx ebx
689
    mov  edx,ebx
690
    movzx esi,al
691
    call get_cell_at
692
    cmp  al,tPlace
693
    jbe  push_it
694
    cmp  [workmode],sSokonex
695
    jne  no_plate
696
    cmp  al,tHole
697
    jne  no_plate
698
    cmp  esi,tBroken
699
    jae  vm_sink
700
    cmp  esi,tPlate
701
    jne  no_plate
702
    and  byte[field+ebx],0
703
  vm_sink:
704
    and  byte[field+edx],0
705
    jmp  vm_hole
706
  no_plate:
707
    pop  ebx edx esi edx
708
    ret
709
  push_it:
710
    call do_move
711
  vm_hole:
712
    pop  ebx edx
713
  result_ok:
714
    call do_move
715
    xor  al,al
716
  vm_exit:
717
    pop  esi edx
718
    ret
719
 
720
;   *********************************************
721
;   ******* ACTUALLY PERFORM MOVES **************
722
;   *********************************************
723
 
724
do_move:                            ; in: dx - source cell
725
    test ch,ch                      ;     bx - target cell
726
    jz   dm_exit                    ;     ch = 0 don't perform moves
727
    mov  al,byte[field+edx]
728
    cmp  byte[workmode],sSokoban
729
    jne  no_dm_ban
730
    and  al,0xfe
731
  no_dm_ban:
732
    xor  byte[field+edx],al
733
    or   byte[field+ebx],al
734
    call chk_win_obj
735
    jne  no_check_win
736
    pusha
737
    movzx ecx,byte[checkcount]
738
    xor  edi,edi
739
  dm_cycle:
740
    movzx esi,word[checkpoint+edi*2]
741
    and  esi,0xfff
742
    and  edx,0xfff
743
    cmp  esi,edx
744
    jnz  not_an_obj
745
    movzx eax,dl
746
    movzx eax,byte[field+ebx]
747
    shl  eax,12
748
    or   eax,ebx
749
    mov  word[checkpoint+edi*2],ax
750
    jmp  dm_ex
751
  not_an_obj:
752
    inc  edi
753
    loop dm_cycle
754
  dm_ex:
755
    popa
756
    call check_win
757
    jne  no_check_win
758
    mov  byte[winmode],WM_WINNER
759
  no_check_win:
760
    cmp  al,tPlayer
761
    jne  dm_exit
762
    mov  [player],bx
763
  dm_exit:
764
    ret
765
 
766
;   *********************************************
767
;   ******* CHECK VICTORY CONDITIONS ************
768
;   *********************************************
769
 
770
check_win:
771
;    debug_print <13,10>
772
    push eax ebx ecx esi
773
    xor  eax,eax
774
    movzx ecx,byte[checkcount]
775
    mov  esi,checkpoint
776
    mov  bl,byte[workmode]
777
    xor  bh,bh
778
    mov  [colcount],bh
779
    cld
780
  cw_cycle:
781
    lodsw
782
    cmp  bl,sSokoban
783
    jne  nocw_sokoban
784
    test ax,1 shl 12
785
    jz   cw_not_inplace
786
    inc  bh
787
  cw_not_inplace:
788
    loop cw_cycle
789
;    movzx eax,bh
790
    cmp  [checkcount],bh
791
    jmp  cw_exit
792
  nocw_sokoban:
793
    cmp  bl,sSokonex
794
    jne  nocw_sokonex
795
    mov  dx,ax
796
    call scan_root
797
    cmp  al,[checkcount]
798
    jmp  cw_exit
799
 
800
  nocw_sokonex:
801
    cmp  esi,checkpoint+8
802
    ja   cwlor_exit
803
;    debug_print '*'
804
    test ax,ax
805
    jz   cw_cycle
806
    mov  dx,ax
807
    call scan_root
808
    add  [colcount],al
809
;    debug_print '*->'
810
;    debug_print_dec eax
811
    jmp  cw_cycle
812
  cwlor_exit:
813
    mov  al,[colcount]
814
    cmp  al,[checkcount]
815
  cw_exit:
816
;    debug_print <13,10>
817
    pop esi ecx ebx eax
818
    ret
819
 
820
;   *********************************************
821
;   **** WHETHER LASERS DESTROY SOMETHING *******
822
;   *********************************************
823
 
824
check_lasers:
825
    pusha
826
    xor  edx,edx
827
    mov  ecx,[fld_size]
828
  cl_loop:
829
    push ecx edx
830
    mov  cl,[field+edx]
831
    sub  cl,tLaserW
832
    jl   cl_exit
833
  cl_begin:
834
    call get_cell_at
835
    cmp  al,tLaserW
836
    jae  cl_destroy
837
    cmp  al,tBroken
838
    je   cl_destroy
839
    cmp  al,tEmpty
840
    je   no_cl_destroy
841
    cmp  al,tHole
842
    je   no_cl_destroy
843
    cmp  al,tPlayer
844
    jne  cl_exit
845
    mov  ecx,0x20ac0000
846
    mov  edx,lose_msg
847
    mov  esi,lose_msg_end-lose_msg  ; print loose message
848
    mov  byte[winmode],WM_LOSE
849
    mov  ebx,WIN_XY
850
    mov  eax,4
851
    int  0x40
852
    jmp  cl_exit
853
  cl_destroy:
854
    mov  byte[field+ebx],0
855
  no_cl_destroy:
856
    mov  edx,ebx
857
    jmp  cl_begin
858
  cl_exit:
859
    pop  edx ecx
860
    inc  edx
861
    loop cl_loop
862
    popa
863
    ret
864
 
865
;   *********************************************
866
;   *** USED BY CHECK_WIN IN SOKONEX & SOKOLOR **
867
;   *********************************************
868
 
869
scan_root:                ; input:   dx-beginning cell, ebx-what to search
870
    push esi
871
    mov  edi,srch         ; output:  eax-number of win_obj found
872
    mov  eax,0xfff
873
    movzx ecx,[checkcount]
874
    inc  ecx
875
    cld
876
    rep  stosw            ; clearing area for scan
877
    movzx ebx,dx
878
    and  edx,eax          ; dx-cell number to compare with
879
    shr  ebx,12           ; bl-obj id
880
    mov  [color],bl
881
    mov  esi,srch
882
    mov  edi,eax          ; mask to extract cell
883
    mov  word[srch],dx
884
  sr_loop:
885
    lodsw
886
    push esi              ; saving scan pointer
887
       movzx edx,ax       ; edx-[dirs*4][cell*12]
888
       and  edx,edi
889
;       debug_print ' >'
890
       mov  ecx,4
891
  sr_dir_loop1:
892
;       debug_print '.'
893
       push ecx           ; saving dir counter
894
         lea  ebx,[ecx+11]
895
         bts  word[esi-2],bx
896
         jc   sr_endloop      ; this entry is already processed
897
;         debug_print '^'
898
         dec  ecx             ; cl-direction
899
         call get_cell_at     ; bx-new position, al-object
900
;         cmp  [workmode],sSokonex
901
;         jne  no_sr_nex
902
         call chk_win_obj
903
         jne  sr_endloop      ; not a win_obj there
904
;         debug_print '@'
905
         cmp  [workmode],sSokolor
906
         jne  no_sr_lor
907
         cmp  al,[color]
908
         jne  sr_endloop
909
       no_sr_lor:
910
         push esi
911
         mov  esi,srch        ; let us search for existing entries
912
       sr_loop1:
913
         lodsw
914
         and  eax,edi         ; eax-cell w/o dirs
915
         cmp  eax,ebx
916
         je   sr_foundentry   ; this is the entry we're seeking for
917
         cmp  word[esi],0xfff
918
         jnz  sr_loop1        ; next entry
919
    ; we reached empty area
920
         mov  [esi],bx
921
         add  esi,2
922
       sr_foundentry:
923
         mov  eax,15
924
         sub  eax,ecx
925
         bts  [esi-2],ax      ; mark entry as used
926
         pop  esi
927
;         inc  [e_fnd]         ; one more obj found
928
     sr_endloop:
929
       pop  ecx
930
       loop sr_dir_loop1
931
;       jmp  tttt
932
;     sr_dir_loop:
933
;       jmp  sr_dir_loop1
934
;     tttt:
935
    pop esi
936
    cmp  word[esi],0xfff
937
    jne  sr_loop
938
    mov  eax,esi
939
    sub  eax,srch
940
    shr  eax,1
941
    pop  esi
942
;    debug_print_dec eax
943
    ret
944
 
945
;   *********************************************
946
;   *** SPECIAL ROUTINE TO DRAW LASERS **********
947
;   *********************************************
948
 
949
draw_lasers:
950
    xor  edx,edx
951
    mov  ecx,[fld_size]
952
  dl_loop:
953
    push ecx edx
954
    mov  cl,[field+edx]
955
    sub  cl,tLaserW
956
    jl   dl_eloop
957
    inc  ch
958
  dl_gca:
959
    call get_cell_at
960
    cmp  al,tEmpty
961
    je   dl_draw
962
    cmp  al,tHole
963
    jne  dl_eloop
964
  dl_draw:
965
    call draw_beams
966
    mov  edx,ebx
967
    jmp  dl_gca
968
  dl_eloop:
969
    pop  edx
970
    inc  edx
971
    pop  ecx
972
    loop dl_loop
973
    ret
974
 
975
;   *********************************************
976
;   *** DRAWS LASER BEAMS IN CERTAIN DIRECTION **
977
;   *********************************************
978
 
979
draw_beams:
980
    pusha
981
    mov esi,[levptr]
982
    movzx esi,byte[esi+1]
983
    mov  eax,ebx
984
    xor  edx,edx
985
    div  esi
986
    movzx esi,cl
987
    dec  esi
988
    shr  esi,1
989
    and  esi,1
990
    shl  edx,20
991
    mov  ebx,edx
992
    shl  eax,20
993
    mov  ecx,eax
994
    add  ebx,dword[beam_xy+esi*8]
995
    add  ecx,dword[beam_xy+esi*8+4]
996
    mov  edx,0xe9e25c
997
    mov  eax,13
998
    int  0x40
999
    popa
1000
    ret
1001
 
1002
ud:
1003
   ud2  ; debugging purposes only
1004
 
1005
 
1006
;   *********************************************
1007
;   *** COMPRESS LEVEL - NOT READY YET **********
1008
;   *********************************************
1009
 
1010
;    push    esi ebx ;ecx
1011
;    xchg    ebx,edi
1012
;    mov     esi,edi                 ; esi,edi - beginning
1013
;; ebx - end of unpacked field
1014
;  first_enc:
1015
;    lodsb                           ; al - first byte
1016
;    shl     ax,8                    ; ah - this byte, al=0
1017
;  next_enc:
1018
;    cmp     esi,ebx
1019
;    jae     exit_enc
1020
;;    movzx   ecx,byte[esi]
1021
;;    debug_print_dec ecx
1022
;    cmp     ah,byte[esi]
1023
;    jne     newchar
1024
;    inc     esi
1025
;    inc     al
1026
;    cmp     al,15
1027
;    jb      next_enc
1028
;  newchar:
1029
;    shl     al,4
1030
;    shr     ax,4
1031
;    stosb
1032
;    jmp     first_enc
1033
;  exit_enc:
1034
;    shl     al,4
1035
;    shr     ax,4
1036
;    stosb
1037
;    mov     al,0xff
1038
;    stosb
1039
;    pop     ebx esi ecx
1040
;
1041
;    dec     ecx
1042
;    jcxz    outcycle
1043
;    jmp     next_lev
1044
;  outcycle:
1045
 
1046
 
1047
; Здесь находятся данные программы:
1048
 
1049
; интерфейс программы двуязычный - задайте язык в macros.inc
1050
load_char:
1051
if lang eq ru
1052
     db 'Загрузить'
1053
else
1054
     db 'Open file'
1055
end if
1056
loadlen:
1057
 
1058
ll_msg:
1059
if lang eq ru
1060
     db 'Выберите уровень'
1061
else
1062
     db 'Choose a level'
1063
end if
1064
     db ' (0-9, PgUp, PgDn)'
1065
ll_msg_end:
1066
 
1067
fn_input:
1068
;   db 'cnf'
1069
;    db 'soko-4.lev'
1070
if lang eq ru
1071
     db 'или введите имя файла'
1072
else
1073
     db 'or enter a filename'
1074
end if
1075
inp_end:
1076
     rb 256-(inp_end-fn_input)
1077
 
1078
win_msg:
1079
if lang eq ru
1080
     db 'Ура!!! Вы прошли уровень!'
1081
else
1082
     db "You've completed the level!"
1083
end if
1084
win_msg_end:
1085
 
1086
lose_msg:
1087
if lang eq ru
1088
     db 'Вы парализованы! Проигрыш...'
1089
else
1090
     db "You're paralized! Game over..."
1091
end if
1092
lose_msg_end:
1093
 
1094
zagolovok:               ; строка заголовка
1095
if lang eq ru
1096
     db   'СОКОБАН ДЛЯ'
1097
else
1098
     db   'SOKOBAN FOR'
1099
end if
1100
     db   ' MENUET'
1101
zag_konets:              ; и её конец
1102
 
1103
pic_map:
1104
    db 0xf,9,0,0,1,1,5,6
1105
pm_nex:
1106
    db 2,7,8,3,4,0xa,0xa,0xa,0xa
1107
pm_col:
1108
    db 0xb,0xc,0xd,0xe
1109
 
1110
beam_xy:
1111
    dd (FLD_LEFT+7) shl 16+2, FLD_TOP2+16
1112
    dd FLD_LEFT2+16, (FLD_TOP+7) shl 16+2
1113
 
1114
ll_num db '00x.'
1115
 
1116
move_map dd -1,+0,-0,1      ; 0 - W, 1 - S, 2 - N, 3 - E
1117
 
1118
stdlev     db 'SOKO-0.LEV',0
1119
stdlev_len:
1120
 
1121
inp_pos    dd inp_end-fn_input
1122
entered    dd 0
1123
 
1124
file_info:
1125
           dd 0
1126
           dd 0
1127
           dd 0x100
1128
cnf_level  dd strip
1129
           dd workarea
1130
file_name  db CUR_DIR
1131
path_end   db 'SKIN.'
1132
file_num   db 'RAW',0
1133
 
1134
           rb 256-($-file_name)
1135
 
1136
I_END:  ; конец программы
1137
 
1138
winmode db ?
1139
scanptr dd ?
1140
levpage dd ?
1141
workmode db ?
1142
player dw ?
1143
fld_size dd ?
1144
levptr dd ?
1145
wnd_height dd ?
1146
wnd_width dd ?
1147
color  db ?
1148
colcount db ?
1149
levelcount dd ?
1150
checkcount db ?
1151
checkpoint:
1152
    times 256 dw ?
1153
levelmap:
1154
    times 1024 dd ?
1155
strip rb SKIN_SIZE
1156
 
1157
workarea:
1158
  srch  rb 0x10000-($-workarea)
1159
 
1160
level_start rb 0x20000
1161
field: