Subversion Repositories Kolibri OS

Rev

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