Subversion Repositories Kolibri OS

Rev

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