Subversion Repositories Kolibri OS

Rev

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