Subversion Repositories Kolibri OS

Rev

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