Subversion Repositories Kolibri OS

Rev

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