Subversion Repositories Kolibri OS

Rev

Rev 6184 | 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.  
  36. CUR_DIR equ '/sys/games/'       ; change it to appropriate path
  37.  
  38. SKIN_SIZE       = 11520         ; size of skin file (16x240)
  39.  
  40. ; field dimensions
  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
  48.  
  49. ; level list dimensions
  50. LEVLIST_XY      = FLD_TOP shl 16+45
  51. LEVLIST_SPACING = 10
  52. LEVWND_X        = 320
  53. LEVWND_Y        = 200
  54.  
  55. ; input line dimensions
  56. INP_X           = 10 shl 16+300
  57. INP_Y           = 160 shl 16+16
  58. INP_XY          = 15 shl 16+164
  59.  
  60. ; load button dimensions
  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
  65.  
  66.  
  67. WIN_XY          = 135 shl 16+25
  68.  
  69. ; workmode constants, more defs in CELLTYPE.INC
  70. WM_WINNER       = 0x10
  71. WM_READSET      = 0
  72. WM_LOSE         = 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,70         ; 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,70
  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,0x00ac0000
  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,0x13000000 + WND_COLOR
  348.     mov  esi,0x005080d0
  349.     mov  edi,zagolovok
  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
  381.     mov  ecx,0x00107a30
  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
  388.     mov  edi,0x004e00e7
  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
  839.     mov  ecx,0x00ac0000
  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.  
  1088. zagolovok:
  1089.      db   'Sokoban', 0
  1090.  
  1091.  
  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:
  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
  1119. path_end   db 'SKIN.'
  1120. file_num   db 'RAW',0
  1121.  
  1122.            rb 256-($-file_name)
  1123.  
  1124. I_END:  ; конец программы
  1125.  
  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
  1142.  
  1143. workarea:
  1144.   srch  rb 0x10000-($-workarea)
  1145.  
  1146. level_start rb 0x20000
  1147. field:
  1148.