Subversion Repositories Kolibri OS

Rev

Rev 1806 | Rev 1935 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  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. include '../../../macros.inc'    ; decrease code size (optional)
  31. include 'CELLTYPE.INC'  ; object identifiers
  32. ;include 'debug.inc'
  33. ;lang equ ru             ; russian interface; english if undefined
  34. include 'lang.inc'
  35.  
  36. ;CUR_DIR equ '/HD/1/MENUETOS/' ; change it to appropriate path
  37.  
  38. SKIN_SIZE equ 11520         ; size of skin file (16x240)
  39.  
  40. ; field dimensions
  41. FLD_LEFT equ 43
  42. FLD_LEFT2 equ FLD_LEFT shl 16
  43. FLD_TOP equ 40
  44. FLD_TOP2 equ FLD_TOP shl 16
  45. IMG_SIZE equ 16 shl 16+16
  46. SHIFT equ (16 shl 16)
  47. WND_COLOR equ 0x03aabbcc
  48.  
  49. ; level list dimensions
  50. LEVLIST_XY equ FLD_TOP shl 16+45
  51. LEVLIST_SPACING equ 10
  52. LEVWND_X equ 320
  53. LEVWND_Y equ 200
  54.  
  55. ; input line dimensions
  56. INP_X equ 10 shl 16+300
  57. INP_Y equ 160 shl 16+16
  58. INP_XY equ 15 shl 16+164
  59.  
  60. ; load button dimensions
  61. LOAD_X equ 130 shl 16+65
  62. LOAD_Y equ 180 shl 16+14
  63. LOAD_XY equ 135 shl 16+184
  64. CHOOSE_XY equ 40 shl 16+148
  65.  
  66.  
  67. WIN_XY equ 135 shl 16+25
  68.  
  69. ; workmode constants, more defs in CELLTYPE.INC
  70. WM_WINNER  equ 0x10
  71. WM_READSET equ 0
  72. WM_LOSE    equ 0x20
  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:
  86.     mov  eax,58         ; load skin image-it is in RAW 16x240 BGR
  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:
  106.     mov  eax,58
  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
  219.     mov  ecx,0x20ac0000
  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]
  347.     mov  edx,WND_COLOR
  348.     mov  esi,0x805080d0
  349.     mov  edi,0x005080d0
  350.     int  0x40
  351.  
  352.     mov  eax,4
  353.     mov  ebx,8*65536+8
  354.     mov  ecx,0x10ddeeff
  355.     mov  edx,zagolovok
  356.     mov  esi,zag_konets-zagolovok
  357.     int  0x40
  358.  
  359.     cmp  byte[workmode],WM_READSET
  360.     je   list_levels
  361.  
  362.     mov  edi,[levptr]   ; print custom level filename
  363.     add  ebx,170*65536
  364.     lea  edx,[edi+4]
  365.     movzx  esi,byte[edi+3]
  366.     int  0x40
  367.  
  368.     call draw_field
  369.     cmp  [entered],0
  370.     jz   end_of_draw
  371.     mov  edx,fn_input   ; print input line text
  372.     mov  esi,[inp_pos]
  373.     mov  ebx,FLD_LEFT2+FLD_TOP-15
  374.     jmp  draw_level_file
  375.  
  376.   list_levels:
  377.  
  378.     call draw_input
  379.  
  380.     mov  eax,8          ; draw load button
  381.     mov  ebx,LOAD_X
  382.     mov  ecx,LOAD_Y
  383.     mov  edx,3
  384.     mov  esi,WND_COLOR
  385.     int  0x40
  386.  
  387.     mov  eax,4
  388.     mov  ecx,0x20107a30
  389.     mov  ebx,LOAD_XY
  390.     mov  edx,load_char
  391.     mov  esi,loadlen-load_char
  392.     int  0x40
  393.  
  394.     mov  ebx,LEVLIST_XY
  395.     mov  edi,0x204e00e7
  396.     xor  esi,esi
  397.     mov  ecx,10
  398.   ll_cycle:
  399.     push ecx esi ebx esi
  400.     lea  ecx,[esi+'0']
  401.     mov  [ll_num+2],cl
  402.     mov  ecx,edi
  403.     mov  edx,ll_num
  404.     mov  esi,4
  405.     int  0x40
  406.     add  ebx,25 shl 16
  407.     pop  esi
  408.     add  esi,[levpage]
  409.     mov  edx,[levelmap+esi*4]
  410.     add  edx,4
  411.     movzx esi,byte[edx-1]
  412.     int  0x40
  413.     pop  ebx esi ecx
  414.     inc  esi
  415.     mov  edx,[levelcount]
  416.     sub  edx,[levpage]
  417.     cmp  edx,esi
  418.     jbe  choose_print
  419.     add  ebx,LEVLIST_SPACING
  420.     loop ll_cycle
  421.   choose_print:
  422.     mov  edx,ll_msg
  423.     mov  esi,ll_msg_end-ll_msg
  424.     mov  ebx,CHOOSE_XY
  425.   draw_level_file:
  426.     mov  eax,4
  427.     int  0x40
  428.  
  429.   end_of_draw:
  430.     mov  eax,12
  431.     mov  ebx,2
  432.     int  0x40
  433.  
  434.     ret
  435.  
  436. ;   *********************************************
  437. ;   ******* DRAW CELL IMAGES WITHIN FIELD *******
  438. ;   *********************************************
  439.  
  440. draw_field:
  441.     cmp  byte[workmode],sSokonex
  442.     jne  no_chl
  443.     call check_lasers   ; Sokonex game
  444.   no_chl:
  445.     mov  eax,13         ; clear field area
  446.     mov  edx,WND_COLOR
  447.     mov  edi,[levptr]
  448.     movzx ebx,byte[edi+1]
  449.     shl  ebx,4
  450.     lea  ebx, [FLD_LEFT2+ebx]
  451.     movzx ecx,byte[edi+2]
  452.     shl  ecx,4
  453.     lea  ecx, [FLD_TOP shl 16+ecx]
  454.     int  0x40
  455.  
  456.     mov  edx, FLD_LEFT2+FLD_TOP
  457.     movzx edi,byte[edi+1]
  458.     shl  edi,20
  459.     add  edi, FLD_LEFT2
  460.  
  461.     xor  eax,eax
  462.     mov  ecx,[fld_size]
  463.     mov  esi,field
  464.   fld_cycle:
  465.     lodsb
  466.     call draw_img
  467.     add  edx,SHIFT
  468.     cmp  edx,edi
  469.     jl  no_nl
  470.     add  edx,16
  471.     and  edx,0xffff
  472.     add  edx,FLD_LEFT2
  473.   no_nl:
  474.     loop fld_cycle
  475.     cmp  byte[workmode],sSokonex
  476.     jne  end_of_df
  477.     call draw_lasers
  478.   end_of_df:
  479.     ret
  480.  
  481. ;   *********************************************
  482. ;   *********** DRAW CELL IMAGE *****************
  483. ;   *********************************************
  484.  
  485. draw_img:               ; in: eax-object index, edx-coordinates
  486.     pusha
  487.     cmp  eax,tWall
  488.     jbe  no_adjust
  489.     cmp  [workmode],sSokolor
  490.     jne  no_di_color
  491.     add  eax,pm_col-pm_nex
  492.     jmp  no_adjust
  493.   no_di_color:
  494.     cmp  [workmode],sSokonex
  495.     jne  no_adjust
  496.     inc  eax
  497.   no_adjust:
  498.     movzx  ebx,byte [pic_map+eax]
  499.     cmp  ebx,0xf
  500.     je   no_img
  501.   bl_place:
  502.     mov  ecx, IMG_SIZE
  503.     imul ebx, 256*3
  504.     add  ebx,strip
  505.     mov  eax,7          ; draw_image sysfunc
  506.     int  0x40
  507.   no_img:
  508.     popa
  509.     ret
  510.  
  511. ;****************************************
  512. ;******* DRAW CONTENTS OF INPUT LINE ****
  513. ;****************************************
  514. draw_input:
  515.     push edi
  516.     cmp  eax,4
  517.     jne  highlight
  518.     mov  esi,WND_COLOR
  519.     jmp  di_draw
  520.   highlight:
  521.     mov  esi,0xe0e0e0
  522.   di_draw:
  523.     mov  eax,8
  524.     mov  ebx,INP_X
  525.     mov  ecx,INP_Y
  526.     mov  edx,2
  527.     int  0x40
  528.     mov  eax,4
  529.     mov  ecx,0x00107a30            ; èà¨äâ 1 ¨ 梥â ( 0xF0RRGGBB )
  530.     mov  ebx,INP_XY
  531.     mov  edx,fn_input
  532.     mov  esi,[inp_pos]
  533.     int  0x40
  534.     pop  edi
  535.     ret
  536.  
  537. ;   ********************************************************
  538. ;   * DECOMPRESS LEVEL & FILL SOME TABLES TO CHECK VICTORY *
  539. ;   ********************************************************
  540.  
  541. decode_field:
  542. ;    debug_print <13,10>
  543.     xor  eax,eax
  544.     mov  dword[checkpoint],eax
  545.     mov  dword[checkpoint+4],eax
  546.     mov  byte[checkcount],al
  547.     mov  edi,[levptr]
  548.     mov  dl,[edi]
  549.     mov  [workmode],dl
  550.     movzx  edx,byte[edi+1]
  551.     mov  esi,edx
  552.     shl  esi,4
  553.     add  esi,FLD_LEFT*2-25
  554.     mov  [wnd_width],esi
  555.     neg  edx
  556.     mov  [move_map+8],edx
  557.     neg  edx
  558.     mov  [move_map+4],edx
  559.     movzx eax,byte[edi+2]
  560.     mov  esi,eax
  561.     shl  esi,4
  562.     add  esi,FLD_TOP*2-18
  563.     mov  [wnd_height],esi
  564.     imul edx,eax
  565.     mov  [fld_size],edx
  566.     lea  esi,[edi+4]
  567.     movzx ecx,byte[edi+3]
  568.     add  esi,ecx
  569.     cmp  byte[esi],0xff
  570.     je   backto_set
  571.     xor  edi,edi
  572.     cld
  573.  dec_cycle:
  574.     lodsb
  575.     movzx ecx,al
  576.     and  ecx,0xf                   ; ecx-count of objects
  577.     shr  al,4                      ; eax-index of object
  578.     inc  ecx
  579.     sub  edx,ecx
  580.   dc_cycle:
  581.     mov  [field+edi],al
  582.     call chk_win_obj
  583.     jne  no_register
  584.     push eax ecx esi
  585.     movzx ecx,al
  586.     shl  eax,12
  587.     or   eax,edi
  588.     inc  byte[checkcount]
  589.     cmp  [workmode],sSokolor
  590.     jne  chk_sokoban
  591. ;    debug_print ':'
  592. ;    debug_print_dec ecx
  593.     sub  ecx,tRedB
  594.     shl  ecx,1
  595.     cmp  word[checkpoint+ecx],0
  596.     jnz  no_new_check
  597.     mov  [checkpoint+ecx],ax
  598.     and  eax,0xfff
  599. ;    debug_print_dec eax
  600.     jmp  no_new_check
  601.   chk_sokoban:
  602.     cmp  [workmode],sSokonex
  603.     jne  no_nex
  604.     cmp  byte[checkcount],1
  605.     ja   no_new_check
  606.   no_nex:
  607.     movzx ecx,byte[checkcount]
  608.     mov  word[checkpoint-2+ecx*2],ax
  609.   no_new_check:
  610.     pop  esi ecx eax
  611.   no_register:
  612.     inc  edi
  613.     loop dc_cycle
  614.     cmp  edx,0
  615.     jg   dec_cycle
  616.     mov  ecx,[fld_size]
  617.     xor  edx,edx
  618.   fp_cycle:
  619.     mov  al,[field+edx]
  620.     and  al,0xfe
  621.     cmp  al,tPlayer
  622.     je   pl_found
  623.     inc  edx
  624.     loop fp_cycle
  625.   pl_found:
  626.     mov  [player],dx
  627.     movzx eax,byte[checkcount]
  628. ;    debug_print_dec eax
  629.     ret
  630.  
  631. ;   *********************************************
  632. ;   * WHETHER OBJECT IS VICTORY DEPENDENT *******
  633. ;   *********************************************
  634.  
  635. chk_win_obj:             ; al-object in a cell
  636.     push ecx eax
  637.     and  al,0xf
  638.     mov  cl,[workmode]
  639.     cmp  cl,sSokoban
  640.     jne  nota_sokoban
  641.     cmp  al,tBlock
  642.     jmp  cwo_exit
  643.   nota_sokoban:
  644.     cmp  cl,sSokonex
  645.     jne  nota_sokonex
  646.     cmp  al,tConnect
  647.     je   cwo_exit
  648.     cmp  al,tStConnect
  649.     jmp  cwo_exit
  650.   nota_sokonex:
  651.     push eax
  652.     and  eax,tRedB
  653.     cmp  eax,tRedB
  654.     pop  eax
  655.   cwo_exit:
  656.     pop  eax ecx
  657.     ret
  658.  
  659. ;   *********************************************
  660. ;   ***** GET CELL AT CERTAIN DIRECTION *********
  661. ;   *********************************************
  662.  
  663. get_cell_at:            ; in:  dx - current cell, cl - direction
  664.     mov  ebx,edx        ; out: al - object at direction, bx - new position
  665.     movzx eax,cl
  666.     and  eax,11b
  667.     mov  eax, [move_map+eax*4]
  668.     add  ebx,eax
  669.     mov  al,[field+ebx]
  670.     ret
  671.  
  672. ;   *********************************************
  673. ;   *** WHETHER A MOVE CAN BE DONE, & DO IT *****
  674. ;   *********************************************
  675.  
  676. valid_move:                         ; in:  dx - current cell, cl - direction
  677.     push edx esi
  678.     call get_cell_at                ; if ch>0 perform all moves
  679.     cmp  al,tWall
  680.     jb   result_ok
  681.     je   vm_exit
  682.     cmp  [workmode],sSokonex
  683.     jne  n_vm_nex
  684.     cmp  al,tStConnect
  685.     je   vm_exit
  686.     cmp  al,tHole
  687.     je   vm_exit
  688.   n_vm_nex:
  689.     push edx ebx
  690.     mov  edx,ebx
  691.     movzx esi,al
  692.     call get_cell_at
  693.     cmp  al,tPlace
  694.     jbe  push_it
  695.     cmp  [workmode],sSokonex
  696.     jne  no_plate
  697.     cmp  al,tHole
  698.     jne  no_plate
  699.     cmp  esi,tBroken
  700.     jae  vm_sink
  701.     cmp  esi,tPlate
  702.     jne  no_plate
  703.     and  byte[field+ebx],0
  704.   vm_sink:
  705.     and  byte[field+edx],0
  706.     jmp  vm_hole
  707.   no_plate:
  708.     pop  ebx edx esi edx
  709.     ret
  710.   push_it:
  711.     call do_move
  712.   vm_hole:
  713.     pop  ebx edx
  714.   result_ok:
  715.     call do_move
  716.     xor  al,al
  717.   vm_exit:
  718.     pop  esi edx
  719.     ret
  720.  
  721. ;   *********************************************
  722. ;   ******* ACTUALLY PERFORM MOVES **************
  723. ;   *********************************************
  724.  
  725. do_move:                            ; in: dx - source cell
  726.     test ch,ch                      ;     bx - target cell
  727.     jz   dm_exit                    ;     ch = 0 don't perform moves
  728.     mov  al,byte[field+edx]
  729.     cmp  byte[workmode],sSokoban
  730.     jne  no_dm_ban
  731.     and  al,0xfe
  732.   no_dm_ban:
  733.     xor  byte[field+edx],al
  734.     or   byte[field+ebx],al
  735.     call chk_win_obj
  736.     jne  no_check_win
  737.     pusha
  738.     movzx ecx,byte[checkcount]
  739.     xor  edi,edi
  740.   dm_cycle:
  741.     movzx esi,word[checkpoint+edi*2]
  742.     and  esi,0xfff
  743.     and  edx,0xfff
  744.     cmp  esi,edx
  745.     jnz  not_an_obj
  746.     movzx eax,dl
  747.     movzx eax,byte[field+ebx]
  748.     shl  eax,12
  749.     or   eax,ebx
  750.     mov  word[checkpoint+edi*2],ax
  751.     jmp  dm_ex
  752.   not_an_obj:
  753.     inc  edi
  754.     loop dm_cycle
  755.   dm_ex:
  756.     popa
  757.     call check_win
  758.     jne  no_check_win
  759.     mov  byte[winmode],WM_WINNER
  760.   no_check_win:
  761.     cmp  al,tPlayer
  762.     jne  dm_exit
  763.     mov  [player],bx
  764.   dm_exit:
  765.     ret
  766.  
  767. ;   *********************************************
  768. ;   ******* CHECK VICTORY CONDITIONS ************
  769. ;   *********************************************
  770.  
  771. check_win:
  772. ;    debug_print <13,10>
  773.     push eax ebx ecx esi
  774.     xor  eax,eax
  775.     movzx ecx,byte[checkcount]
  776.     mov  esi,checkpoint
  777.     mov  bl,byte[workmode]
  778.     xor  bh,bh
  779.     mov  [colcount],bh
  780.     cld
  781.   cw_cycle:
  782.     lodsw
  783.     cmp  bl,sSokoban
  784.     jne  nocw_sokoban
  785.     test ax,1 shl 12
  786.     jz   cw_not_inplace
  787.     inc  bh
  788.   cw_not_inplace:
  789.     loop cw_cycle
  790. ;    movzx eax,bh
  791.     cmp  [checkcount],bh
  792.     jmp  cw_exit
  793.   nocw_sokoban:
  794.     cmp  bl,sSokonex
  795.     jne  nocw_sokonex
  796.     mov  dx,ax
  797.     call scan_root
  798.     cmp  al,[checkcount]
  799.     jmp  cw_exit
  800.  
  801.   nocw_sokonex:
  802.     cmp  esi,checkpoint+8
  803.     ja   cwlor_exit
  804. ;    debug_print '*'
  805.     test ax,ax
  806.     jz   cw_cycle
  807.     mov  dx,ax
  808.     call scan_root
  809.     add  [colcount],al
  810. ;    debug_print '*->'
  811. ;    debug_print_dec eax
  812.     jmp  cw_cycle
  813.   cwlor_exit:
  814.     mov  al,[colcount]
  815.     cmp  al,[checkcount]
  816.   cw_exit:
  817. ;    debug_print <13,10>
  818.     pop esi ecx ebx eax
  819.     ret
  820.  
  821. ;   *********************************************
  822. ;   **** WHETHER LASERS DESTROY SOMETHING *******
  823. ;   *********************************************
  824.  
  825. check_lasers:
  826.     pusha
  827.     xor  edx,edx
  828.     mov  ecx,[fld_size]
  829.   cl_loop:
  830.     push ecx edx
  831.     mov  cl,[field+edx]
  832.     sub  cl,tLaserW
  833.     jl   cl_exit
  834.   cl_begin:
  835.     call get_cell_at
  836.     cmp  al,tLaserW
  837.     jae  cl_destroy
  838.     cmp  al,tBroken
  839.     je   cl_destroy
  840.     cmp  al,tEmpty
  841.     je   no_cl_destroy
  842.     cmp  al,tHole
  843.     je   no_cl_destroy
  844.     cmp  al,tPlayer
  845.     jne  cl_exit
  846.     mov  ecx,0x20ac0000
  847.     mov  edx,lose_msg
  848.     mov  esi,lose_msg_end-lose_msg  ; print loose message
  849.     mov  byte[winmode],WM_LOSE
  850.     mov  ebx,WIN_XY
  851.     mov  eax,4
  852.     int  0x40
  853.     jmp  cl_exit
  854.   cl_destroy:
  855.     mov  byte[field+ebx],0
  856.   no_cl_destroy:
  857.     mov  edx,ebx
  858.     jmp  cl_begin
  859.   cl_exit:
  860.     pop  edx ecx
  861.     inc  edx
  862.     loop cl_loop
  863.     popa
  864.     ret
  865.  
  866. ;   *********************************************
  867. ;   *** USED BY CHECK_WIN IN SOKONEX & SOKOLOR **
  868. ;   *********************************************
  869.  
  870. scan_root:                ; input:   dx-beginning cell, ebx-what to search
  871.     push esi
  872.     mov  edi,srch         ; output:  eax-number of win_obj found
  873.     mov  eax,0xfff
  874.     movzx ecx,[checkcount]
  875.     inc  ecx
  876.     cld
  877.     rep  stosw            ; clearing area for scan
  878.     movzx ebx,dx
  879.     and  edx,eax          ; dx-cell number to compare with
  880.     shr  ebx,12           ; bl-obj id
  881.     mov  [color],bl
  882.     mov  esi,srch
  883.     mov  edi,eax          ; mask to extract cell
  884.     mov  word[srch],dx
  885.   sr_loop:
  886.     lodsw
  887.     push esi              ; saving scan pointer
  888.        movzx edx,ax       ; edx-[dirs*4][cell*12]
  889.        and  edx,edi
  890. ;       debug_print ' >'
  891.        mov  ecx,4
  892.   sr_dir_loop1:
  893. ;       debug_print '.'
  894.        push ecx           ; saving dir counter
  895.          lea  ebx,[ecx+11]
  896.          bts  word[esi-2],bx
  897.          jc   sr_endloop      ; this entry is already processed
  898. ;         debug_print '^'
  899.          dec  ecx             ; cl-direction
  900.          call get_cell_at     ; bx-new position, al-object
  901. ;         cmp  [workmode],sSokonex
  902. ;         jne  no_sr_nex
  903.          call chk_win_obj
  904.          jne  sr_endloop      ; not a win_obj there
  905. ;         debug_print '@'
  906.          cmp  [workmode],sSokolor
  907.          jne  no_sr_lor
  908.          cmp  al,[color]
  909.          jne  sr_endloop
  910.        no_sr_lor:
  911.          push esi
  912.          mov  esi,srch        ; let us search for existing entries
  913.        sr_loop1:
  914.          lodsw
  915.          and  eax,edi         ; eax-cell w/o dirs
  916.          cmp  eax,ebx
  917.          je   sr_foundentry   ; this is the entry we're seeking for
  918.          cmp  word[esi],0xfff
  919.          jnz  sr_loop1        ; next entry
  920.     ; we reached empty area
  921.          mov  [esi],bx
  922.          add  esi,2
  923.        sr_foundentry:
  924.          mov  eax,15
  925.          sub  eax,ecx
  926.          bts  [esi-2],ax      ; mark entry as used
  927.          pop  esi
  928. ;         inc  [e_fnd]         ; one more obj found
  929.      sr_endloop:
  930.        pop  ecx
  931.        loop sr_dir_loop1
  932. ;       jmp  tttt
  933. ;     sr_dir_loop:
  934. ;       jmp  sr_dir_loop1
  935. ;     tttt:
  936.     pop esi
  937.     cmp  word[esi],0xfff
  938.     jne  sr_loop
  939.     mov  eax,esi
  940.     sub  eax,srch
  941.     shr  eax,1
  942.     pop  esi
  943. ;    debug_print_dec eax
  944.     ret
  945.  
  946. ;   *********************************************
  947. ;   *** SPECIAL ROUTINE TO DRAW LASERS **********
  948. ;   *********************************************
  949.  
  950. draw_lasers:
  951.     xor  edx,edx
  952.     mov  ecx,[fld_size]
  953.   dl_loop:
  954.     push ecx edx
  955.     mov  cl,[field+edx]
  956.     sub  cl,tLaserW
  957.     jl   dl_eloop
  958.     inc  ch
  959.   dl_gca:
  960.     call get_cell_at
  961.     cmp  al,tEmpty
  962.     je   dl_draw
  963.     cmp  al,tHole
  964.     jne  dl_eloop
  965.   dl_draw:
  966.     call draw_beams
  967.     mov  edx,ebx
  968.     jmp  dl_gca
  969.   dl_eloop:
  970.     pop  edx
  971.     inc  edx
  972.     pop  ecx
  973.     loop dl_loop
  974.     ret
  975.  
  976. ;   *********************************************
  977. ;   *** DRAWS LASER BEAMS IN CERTAIN DIRECTION **
  978. ;   *********************************************
  979.  
  980. draw_beams:
  981.     pusha
  982.     mov esi,[levptr]
  983.     movzx esi,byte[esi+1]
  984.     mov  eax,ebx
  985.     xor  edx,edx
  986.     div  esi
  987.     movzx esi,cl
  988.     dec  esi
  989.     shr  esi,1
  990.     and  esi,1
  991.     shl  edx,20
  992.     mov  ebx,edx
  993.     shl  eax,20
  994.     mov  ecx,eax
  995.     add  ebx,dword[beam_xy+esi*8]
  996.     add  ecx,dword[beam_xy+esi*8+4]
  997.     mov  edx,0xe9e25c
  998.     mov  eax,13
  999.     int  0x40
  1000.     popa
  1001.     ret
  1002.  
  1003. ud:
  1004.    ud2  ; debugging purposes only
  1005.  
  1006.  
  1007. ;   *********************************************
  1008. ;   *** COMPRESS LEVEL - NOT READY YET **********
  1009. ;   *********************************************
  1010.  
  1011. ;    push    esi ebx ;ecx
  1012. ;    xchg    ebx,edi
  1013. ;    mov     esi,edi                 ; esi,edi - beginning
  1014. ;; ebx - end of unpacked field
  1015. ;  first_enc:
  1016. ;    lodsb                           ; al - first byte
  1017. ;    shl     ax,8                    ; ah - this byte, al=0
  1018. ;  next_enc:
  1019. ;    cmp     esi,ebx
  1020. ;    jae     exit_enc
  1021. ;;    movzx   ecx,byte[esi]
  1022. ;;    debug_print_dec ecx
  1023. ;    cmp     ah,byte[esi]
  1024. ;    jne     newchar
  1025. ;    inc     esi
  1026. ;    inc     al
  1027. ;    cmp     al,15
  1028. ;    jb      next_enc
  1029. ;  newchar:
  1030. ;    shl     al,4
  1031. ;    shr     ax,4
  1032. ;    stosb
  1033. ;    jmp     first_enc
  1034. ;  exit_enc:
  1035. ;    shl     al,4
  1036. ;    shr     ax,4
  1037. ;    stosb
  1038. ;    mov     al,0xff
  1039. ;    stosb
  1040. ;    pop     ebx esi ecx
  1041. ;
  1042. ;    dec     ecx
  1043. ;    jcxz    outcycle
  1044. ;    jmp     next_lev
  1045. ;  outcycle:
  1046.  
  1047.  
  1048. ; ‡¤¥áì ­ å®¤ïâáï ¤ ­­ë¥ ¯à®£à ¬¬ë:
  1049.  
  1050. ; ¨­â¥àä¥©á ¯à®£à ¬¬ë ¤¢ãï§ëç­ë© - § ¤ ©â¥ ï§ëª ¢ macros.inc
  1051. load_char:
  1052. if lang eq ru
  1053.      db '‡ £à㧨âì'
  1054. else
  1055.      db 'Open file'
  1056. end if
  1057. loadlen:
  1058.  
  1059. ll_msg:
  1060. if lang eq ru
  1061.      db '‚ë¡¥à¨â¥ ã஢¥­ì'
  1062. else
  1063.      db 'Choose a level'
  1064. end if
  1065.      db ' (0-9, PgUp, PgDn)'
  1066. ll_msg_end:
  1067.  
  1068. fn_input:
  1069. ;   db 'cnf'
  1070. ;    db 'soko-4.lev'
  1071. if lang eq ru
  1072.      db '¨«¨ ¢¢¥¤¨â¥ ¨¬ï ä ©« '
  1073. else
  1074.      db 'or enter a filename'
  1075. end if
  1076. inp_end:
  1077.      rb 256-(inp_end-fn_input)
  1078.  
  1079. win_msg:
  1080. if lang eq ru
  1081.      db '“à !!! ‚ë ¯à®è«¨ ã஢¥­ì!'
  1082. else
  1083.      db "You've completed the level!"
  1084. end if
  1085. win_msg_end:
  1086.  
  1087. lose_msg:
  1088. if lang eq ru
  1089.      db '‚ë ¯ à «¨§®¢ ­ë! à®¨£àëè...'
  1090. else
  1091.      db "You're paralized! Game over..."
  1092. end if
  1093. lose_msg_end:
  1094.  
  1095. zagolovok:               ; áâப  § £®«®¢ª 
  1096. if lang eq ru
  1097.      db   '‘ŽŠŽ€ „‹Ÿ'
  1098. else
  1099.      db   'SOKOBAN FOR'
  1100. end if
  1101.      db   ' MENUET'
  1102. zag_konets:              ; ¨ ¥ñ ª®­¥æ
  1103.  
  1104. pic_map:
  1105.     db 0xf,9,0,0,1,1,5,6
  1106. pm_nex:
  1107.     db 2,7,8,3,4,0xa,0xa,0xa,0xa
  1108. pm_col:
  1109.     db 0xb,0xc,0xd,0xe
  1110.  
  1111. beam_xy:
  1112.     dd (FLD_LEFT+7) shl 16+2, FLD_TOP2+16
  1113.     dd FLD_LEFT2+16, (FLD_TOP+7) shl 16+2
  1114.  
  1115. ll_num db '00x.'
  1116.  
  1117. move_map dd -1,+0,-0,1      ; 0 - W, 1 - S, 2 - N, 3 - E
  1118.  
  1119. stdlev     db 'SOKO-0.LEV',0
  1120. stdlev_len:
  1121.  
  1122. inp_pos    dd inp_end-fn_input
  1123. entered    dd 0
  1124.  
  1125. file_info:
  1126.            dd 0
  1127.            dd 0
  1128.            dd 0x100
  1129. cnf_level  dd strip
  1130.            dd workarea
  1131. file_name  db CUR_DIR
  1132. path_end   db 'SKIN.'
  1133. file_num   db 'RAW',0
  1134.  
  1135.            rb 256-($-file_name)
  1136.  
  1137. I_END:  ; ª®­¥æ ¯à®£à ¬¬ë
  1138.  
  1139. winmode db ?
  1140. scanptr dd ?
  1141. levpage dd ?
  1142. workmode db ?
  1143. player dw ?
  1144. fld_size dd ?
  1145. levptr dd ?
  1146. wnd_height dd ?
  1147. wnd_width dd ?
  1148. color  db ?
  1149. colcount db ?
  1150. levelcount dd ?
  1151. checkcount db ?
  1152. checkpoint:
  1153.     times 256 dw ?
  1154. levelmap:
  1155.     times 1024 dd ?
  1156. strip rb SKIN_SIZE
  1157.  
  1158. workarea:
  1159.   srch  rb 0x10000-($-workarea)
  1160.  
  1161. level_start rb 0x20000
  1162. field:
  1163.