1
0
kolibrios/programs/games/soko/trunk/SOKO.ASM
Yogev Ezra 0b076bbe0f fix path
git-svn-id: svn://kolibrios.org@1935 a494cfbc-eb01-0410-851d-a64ba20cac60
2011-05-15 03:30:00 +00:00

1163 lines
25 KiB
NASM
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

; SOKOBAN FOR MENUET v0.1
; Written in pure assembler by Ivushkin Andrey aka Willow
;
; Last changed: July 2, 2004
;
; Main idea, art & graphics
; Sokofun for Windows 95 by Games 4 Brains
; and Sokoban 2.3 by Björn Källmark
;
; Level designers:
;
; Alberto Garcia, Aymeric du Peloux, Brian Kent, David Holland,
; David W Skinner, Erim Sever, Evgeniy Grigoriev, François Marques,
; Frantisek Pokorny, Howard Abed,J franklin Mentzer, Jaques Duthen,
; John C Davis, John Polhemus, Kobus Theron, Lee Haywood, Mario Bonenfant,
; Martin P Holland, Mic (Jan Reineke), Phil Shapiro, Richard Weston,
; Sven Egevad, Ken'ichiro Takahashi (takaken), Thinking Rabbit,
; Yoshio Murase, ZICO (Zbigniew Kornas)
;
; Special thanks to Hirohiko Nakamiya
;
; More credits:
; Masato Hiramatsu, Kazuo Fukushima, Klaus Clemens
;
; Game uses its own format of levelset files *.LEV
; with simple run-length compression
; COMPILE WITH FASM
include '../../../macros.inc' ; decrease code size (optional)
include 'CELLTYPE.INC' ; object identifiers
;include 'debug.inc'
;lang equ ru ; russian interface; english if undefined
include 'lang.inc'
CUR_DIR equ '/sys/games/' ; change it to appropriate path
SKIN_SIZE equ 11520 ; size of skin file (16x240)
; field dimensions
FLD_LEFT equ 43
FLD_LEFT2 equ FLD_LEFT shl 16
FLD_TOP equ 40
FLD_TOP2 equ FLD_TOP shl 16
IMG_SIZE equ 16 shl 16+16
SHIFT equ (16 shl 16)
WND_COLOR equ 0x03aabbcc
; level list dimensions
LEVLIST_XY equ FLD_TOP shl 16+45
LEVLIST_SPACING equ 10
LEVWND_X equ 320
LEVWND_Y equ 200
; input line dimensions
INP_X equ 10 shl 16+300
INP_Y equ 160 shl 16+16
INP_XY equ 15 shl 16+164
; load button dimensions
LOAD_X equ 130 shl 16+65
LOAD_Y equ 180 shl 16+14
LOAD_XY equ 135 shl 16+184
CHOOSE_XY equ 40 shl 16+148
WIN_XY equ 135 shl 16+25
; workmode constants, more defs in CELLTYPE.INC
WM_WINNER equ 0x10
WM_READSET equ 0
WM_LOSE equ 0x20
use32
org 0x0
db 'MENUET01'
dd 0x01
dd START
dd I_END
dd 0x100000
dd 0x7fff0
dd 0x0
dd 0x0
START:
mov eax,58 ; load skin image-it is in RAW 16x240 BGR
mov ebx,file_info ; IrfanView recommended
int 0x40
test ebx,ebx
; jmp load_level
; jz close
load_fail: ; clear input line, also if levelset load failed
mov [inp_pos],0
load_std:
mov esi,stdlev
mov edi,path_end
mov ecx,stdlev_len-stdlev
rep movsb
mov ecx,10
reset_fi:
mov dword[cnf_level],level_start
xor eax,eax
mov [levpage],eax
mov word[ll_num],'00' ; reset some counters
read_cnf:
mov eax,58
mov ebx,file_info
int 0x40
test ebx,ebx ; load standard levels SOKO-?.LEV instead of custom
jz nxt_cnf
add dword[cnf_level],ebx
nxt_cnf:
test ecx,ecx ; this check is for loading a custom levelset
jz no_increase
inc byte[file_num] ; next standard levelset
loop read_cnf
no_increase:
cmp dword[cnf_level],level_start
jne go_on
test ecx,ecx
jz load_fail
jmp close ; missing standard levels & exiting
go_on:
mov eax,[cnf_level]
mov byte[eax],0xf0 ; end-of-levels mark
call read_levelset
backto_set:
mov byte[workmode],WM_READSET
mov byte[winmode],0
jmp red
restart_level:
call decode_field ; uncompress level
red:
call draw_window
still:
mov eax,10
int 0x40
cmp byte[winmode],WM_WINNER
je backto_set
cmp byte[winmode],WM_LOSE
je backto_set
cmp eax,1
je red
cmp eax,2
je key
cmp eax,3
je button
jmp still
key:
mov eax,2
int 0x40
cmp byte[workmode],WM_READSET
jne key_move
cmp ah,32 ; Space moves focus to input line
je is_input
cmp ah,184
jne no_prev
cmp [levpage],0 ; PgUp
jz still
sub [levpage],10
cmp byte[ll_num+1],'0'
jnz _pu
dec byte[ll_num]
mov byte[ll_num+1],'9'+1
_pu:
dec byte[ll_num+1]
jmp red
no_prev:
cmp ah,183 ; PgDn
jne no_next
mov eax,[levpage]
add eax,10
cmp eax,[levelcount]
jae still
mov [levpage],eax
cmp byte[ll_num+1],'9'
jnz _pd
inc byte[ll_num]
mov byte[ll_num+1],'0'-1
_pd:
inc byte[ll_num+1]
jmp red
no_next:
sub ah,48
cmp ah,9
ja still
movzx eax,ah ; user selects a level
add eax,[levpage]
cmp eax,[levelcount]
jae still
mov eax,[levelmap+eax*4]
mov [levptr],eax ; current level pointer
mov al,byte[eax]
mov byte[workmode],al
jmp restart_level
; we're already in game
key_move:
cmp ah,180 ; Home
je backto_set
cmp ah,176
jb no_arrows
sub ah,176
cmp ah,3
ja no_arrows
movzx ecx,ah
movzx edx,[player]
inc ch
call valid_move
cmp byte[winmode],WM_WINNER
jne no_winner
mov ecx,0x20ac0000
mov edx,win_msg
mov esi,win_msg_end-win_msg ; print victory congratulations
print_msg:
mov ebx,WIN_XY
mov eax,4
int 0x40
jmp d_f
no_winner:
cmp byte[winmode],WM_LOSE
jne d_f
no_loser:
test al,al ; no move accepted
jnz still
d_f:
call draw_field ; move performed-redraw
jmp still
no_arrows:
cmp ah,27
je restart_level
jmp still
button:
mov eax,17
int 0x40
cmp ah,1
jne noclose
close:
xor eax,eax
dec eax
int 0x40 ; shutdown.
noclose:
cmp ah,2
jne no_input
is_input: ; simple input line with backspace feature
mov ebx,[entered] ; sorry - no cursor
test ebx,ebx
jnz wait_input
mov [inp_pos],ebx
inc [entered]
wait_input:
call draw_input
mov eax,10
int 0x40
cmp eax,2
jne still
mov edi,[inp_pos]
mov eax,2
int 0x40
shr eax,8
cmp eax,27
je still
cmp eax,13
je load_level
cmp eax,8
je backsp
mov [fn_input+edi],al
inc [inp_pos]
jmp wait_input
backsp:
test edi,edi
jz wait_input
dec [inp_pos]
jmp wait_input
no_input:
cmp ah,3
jne no_load
load_level:
mov ecx,[inp_pos]
test ecx,ecx
je load_std
mov esi,fn_input
mov byte[esi+ecx],0
inc ecx
mov edi,path_end
rep movsb
jmp reset_fi
no_load:
jmp still
; *********************************************
; ** FILLS LEVEL POINTER MAP ******************
; *********************************************
read_levelset:
mov dword[wnd_width],LEVWND_X
mov dword[wnd_height],LEVWND_Y
mov [levelcount],0
mov edi,level_start
mov esi,levelmap
mov al,0xff
rls_cycle:
cmp byte[edi],EOF
je end_of_levelset
mov [esi],edi
add esi,4
mov ecx,1024
inc [levelcount]
repne scasb
jecxz eol ;end_of_levelset
jmp rls_cycle
end_of_levelset:
mov eax,[levelcount]
; debug_print_dec eax
ret
eol:
; debug_print '*** '
jmp end_of_levelset
; *********************************************
; ******* DEFINE & DRAW WINDOW & OTHER STUFF *
; *********************************************
draw_window:
mov eax,12
mov ebx,1
int 0x40
mov eax,0
mov ebx,150*65536
add ebx,[wnd_width]
mov ecx,50*65536
add ecx,[wnd_height]
mov edx,WND_COLOR
mov esi,0x805080d0
mov edi,0x005080d0
int 0x40
mov eax,4
mov ebx,8*65536+8
mov ecx,0x10ddeeff
mov edx,zagolovok
mov esi,zag_konets-zagolovok
int 0x40
cmp byte[workmode],WM_READSET
je list_levels
mov edi,[levptr] ; print custom level filename
add ebx,170*65536
lea edx,[edi+4]
movzx esi,byte[edi+3]
int 0x40
call draw_field
cmp [entered],0
jz end_of_draw
mov edx,fn_input ; print input line text
mov esi,[inp_pos]
mov ebx,FLD_LEFT2+FLD_TOP-15
jmp draw_level_file
list_levels:
call draw_input
mov eax,8 ; draw load button
mov ebx,LOAD_X
mov ecx,LOAD_Y
mov edx,3
mov esi,WND_COLOR
int 0x40
mov eax,4
mov ecx,0x20107a30
mov ebx,LOAD_XY
mov edx,load_char
mov esi,loadlen-load_char
int 0x40
mov ebx,LEVLIST_XY
mov edi,0x204e00e7
xor esi,esi
mov ecx,10
ll_cycle:
push ecx esi ebx esi
lea ecx,[esi+'0']
mov [ll_num+2],cl
mov ecx,edi
mov edx,ll_num
mov esi,4
int 0x40
add ebx,25 shl 16
pop esi
add esi,[levpage]
mov edx,[levelmap+esi*4]
add edx,4
movzx esi,byte[edx-1]
int 0x40
pop ebx esi ecx
inc esi
mov edx,[levelcount]
sub edx,[levpage]
cmp edx,esi
jbe choose_print
add ebx,LEVLIST_SPACING
loop ll_cycle
choose_print:
mov edx,ll_msg
mov esi,ll_msg_end-ll_msg
mov ebx,CHOOSE_XY
draw_level_file:
mov eax,4
int 0x40
end_of_draw:
mov eax,12
mov ebx,2
int 0x40
ret
; *********************************************
; ******* DRAW CELL IMAGES WITHIN FIELD *******
; *********************************************
draw_field:
cmp byte[workmode],sSokonex
jne no_chl
call check_lasers ; Sokonex game
no_chl:
mov eax,13 ; clear field area
mov edx,WND_COLOR
mov edi,[levptr]
movzx ebx,byte[edi+1]
shl ebx,4
lea ebx, [FLD_LEFT2+ebx]
movzx ecx,byte[edi+2]
shl ecx,4
lea ecx, [FLD_TOP shl 16+ecx]
int 0x40
mov edx, FLD_LEFT2+FLD_TOP
movzx edi,byte[edi+1]
shl edi,20
add edi, FLD_LEFT2
xor eax,eax
mov ecx,[fld_size]
mov esi,field
fld_cycle:
lodsb
call draw_img
add edx,SHIFT
cmp edx,edi
jl no_nl
add edx,16
and edx,0xffff
add edx,FLD_LEFT2
no_nl:
loop fld_cycle
cmp byte[workmode],sSokonex
jne end_of_df
call draw_lasers
end_of_df:
ret
; *********************************************
; *********** DRAW CELL IMAGE *****************
; *********************************************
draw_img: ; in: eax-object index, edx-coordinates
pusha
cmp eax,tWall
jbe no_adjust
cmp [workmode],sSokolor
jne no_di_color
add eax,pm_col-pm_nex
jmp no_adjust
no_di_color:
cmp [workmode],sSokonex
jne no_adjust
inc eax
no_adjust:
movzx ebx,byte [pic_map+eax]
cmp ebx,0xf
je no_img
bl_place:
mov ecx, IMG_SIZE
imul ebx, 256*3
add ebx,strip
mov eax,7 ; draw_image sysfunc
int 0x40
no_img:
popa
ret
;****************************************
;******* DRAW CONTENTS OF INPUT LINE ****
;****************************************
draw_input:
push edi
cmp eax,4
jne highlight
mov esi,WND_COLOR
jmp di_draw
highlight:
mov esi,0xe0e0e0
di_draw:
mov eax,8
mov ebx,INP_X
mov ecx,INP_Y
mov edx,2
int 0x40
mov eax,4
mov ecx,0x00107a30 ; èà¨äâ 1 ¨ 梥â ( 0xF0RRGGBB )
mov ebx,INP_XY
mov edx,fn_input
mov esi,[inp_pos]
int 0x40
pop edi
ret
; ********************************************************
; * DECOMPRESS LEVEL & FILL SOME TABLES TO CHECK VICTORY *
; ********************************************************
decode_field:
; debug_print <13,10>
xor eax,eax
mov dword[checkpoint],eax
mov dword[checkpoint+4],eax
mov byte[checkcount],al
mov edi,[levptr]
mov dl,[edi]
mov [workmode],dl
movzx edx,byte[edi+1]
mov esi,edx
shl esi,4
add esi,FLD_LEFT*2-25
mov [wnd_width],esi
neg edx
mov [move_map+8],edx
neg edx
mov [move_map+4],edx
movzx eax,byte[edi+2]
mov esi,eax
shl esi,4
add esi,FLD_TOP*2-18
mov [wnd_height],esi
imul edx,eax
mov [fld_size],edx
lea esi,[edi+4]
movzx ecx,byte[edi+3]
add esi,ecx
cmp byte[esi],0xff
je backto_set
xor edi,edi
cld
dec_cycle:
lodsb
movzx ecx,al
and ecx,0xf ; ecx-count of objects
shr al,4 ; eax-index of object
inc ecx
sub edx,ecx
dc_cycle:
mov [field+edi],al
call chk_win_obj
jne no_register
push eax ecx esi
movzx ecx,al
shl eax,12
or eax,edi
inc byte[checkcount]
cmp [workmode],sSokolor
jne chk_sokoban
; debug_print ':'
; debug_print_dec ecx
sub ecx,tRedB
shl ecx,1
cmp word[checkpoint+ecx],0
jnz no_new_check
mov [checkpoint+ecx],ax
and eax,0xfff
; debug_print_dec eax
jmp no_new_check
chk_sokoban:
cmp [workmode],sSokonex
jne no_nex
cmp byte[checkcount],1
ja no_new_check
no_nex:
movzx ecx,byte[checkcount]
mov word[checkpoint-2+ecx*2],ax
no_new_check:
pop esi ecx eax
no_register:
inc edi
loop dc_cycle
cmp edx,0
jg dec_cycle
mov ecx,[fld_size]
xor edx,edx
fp_cycle:
mov al,[field+edx]
and al,0xfe
cmp al,tPlayer
je pl_found
inc edx
loop fp_cycle
pl_found:
mov [player],dx
movzx eax,byte[checkcount]
; debug_print_dec eax
ret
; *********************************************
; * WHETHER OBJECT IS VICTORY DEPENDENT *******
; *********************************************
chk_win_obj: ; al-object in a cell
push ecx eax
and al,0xf
mov cl,[workmode]
cmp cl,sSokoban
jne nota_sokoban
cmp al,tBlock
jmp cwo_exit
nota_sokoban:
cmp cl,sSokonex
jne nota_sokonex
cmp al,tConnect
je cwo_exit
cmp al,tStConnect
jmp cwo_exit
nota_sokonex:
push eax
and eax,tRedB
cmp eax,tRedB
pop eax
cwo_exit:
pop eax ecx
ret
; *********************************************
; ***** GET CELL AT CERTAIN DIRECTION *********
; *********************************************
get_cell_at: ; in: dx - current cell, cl - direction
mov ebx,edx ; out: al - object at direction, bx - new position
movzx eax,cl
and eax,11b
mov eax, [move_map+eax*4]
add ebx,eax
mov al,[field+ebx]
ret
; *********************************************
; *** WHETHER A MOVE CAN BE DONE, & DO IT *****
; *********************************************
valid_move: ; in: dx - current cell, cl - direction
push edx esi
call get_cell_at ; if ch>0 perform all moves
cmp al,tWall
jb result_ok
je vm_exit
cmp [workmode],sSokonex
jne n_vm_nex
cmp al,tStConnect
je vm_exit
cmp al,tHole
je vm_exit
n_vm_nex:
push edx ebx
mov edx,ebx
movzx esi,al
call get_cell_at
cmp al,tPlace
jbe push_it
cmp [workmode],sSokonex
jne no_plate
cmp al,tHole
jne no_plate
cmp esi,tBroken
jae vm_sink
cmp esi,tPlate
jne no_plate
and byte[field+ebx],0
vm_sink:
and byte[field+edx],0
jmp vm_hole
no_plate:
pop ebx edx esi edx
ret
push_it:
call do_move
vm_hole:
pop ebx edx
result_ok:
call do_move
xor al,al
vm_exit:
pop esi edx
ret
; *********************************************
; ******* ACTUALLY PERFORM MOVES **************
; *********************************************
do_move: ; in: dx - source cell
test ch,ch ; bx - target cell
jz dm_exit ; ch = 0 don't perform moves
mov al,byte[field+edx]
cmp byte[workmode],sSokoban
jne no_dm_ban
and al,0xfe
no_dm_ban:
xor byte[field+edx],al
or byte[field+ebx],al
call chk_win_obj
jne no_check_win
pusha
movzx ecx,byte[checkcount]
xor edi,edi
dm_cycle:
movzx esi,word[checkpoint+edi*2]
and esi,0xfff
and edx,0xfff
cmp esi,edx
jnz not_an_obj
movzx eax,dl
movzx eax,byte[field+ebx]
shl eax,12
or eax,ebx
mov word[checkpoint+edi*2],ax
jmp dm_ex
not_an_obj:
inc edi
loop dm_cycle
dm_ex:
popa
call check_win
jne no_check_win
mov byte[winmode],WM_WINNER
no_check_win:
cmp al,tPlayer
jne dm_exit
mov [player],bx
dm_exit:
ret
; *********************************************
; ******* CHECK VICTORY CONDITIONS ************
; *********************************************
check_win:
; debug_print <13,10>
push eax ebx ecx esi
xor eax,eax
movzx ecx,byte[checkcount]
mov esi,checkpoint
mov bl,byte[workmode]
xor bh,bh
mov [colcount],bh
cld
cw_cycle:
lodsw
cmp bl,sSokoban
jne nocw_sokoban
test ax,1 shl 12
jz cw_not_inplace
inc bh
cw_not_inplace:
loop cw_cycle
; movzx eax,bh
cmp [checkcount],bh
jmp cw_exit
nocw_sokoban:
cmp bl,sSokonex
jne nocw_sokonex
mov dx,ax
call scan_root
cmp al,[checkcount]
jmp cw_exit
nocw_sokonex:
cmp esi,checkpoint+8
ja cwlor_exit
; debug_print '*'
test ax,ax
jz cw_cycle
mov dx,ax
call scan_root
add [colcount],al
; debug_print '*->'
; debug_print_dec eax
jmp cw_cycle
cwlor_exit:
mov al,[colcount]
cmp al,[checkcount]
cw_exit:
; debug_print <13,10>
pop esi ecx ebx eax
ret
; *********************************************
; **** WHETHER LASERS DESTROY SOMETHING *******
; *********************************************
check_lasers:
pusha
xor edx,edx
mov ecx,[fld_size]
cl_loop:
push ecx edx
mov cl,[field+edx]
sub cl,tLaserW
jl cl_exit
cl_begin:
call get_cell_at
cmp al,tLaserW
jae cl_destroy
cmp al,tBroken
je cl_destroy
cmp al,tEmpty
je no_cl_destroy
cmp al,tHole
je no_cl_destroy
cmp al,tPlayer
jne cl_exit
mov ecx,0x20ac0000
mov edx,lose_msg
mov esi,lose_msg_end-lose_msg ; print loose message
mov byte[winmode],WM_LOSE
mov ebx,WIN_XY
mov eax,4
int 0x40
jmp cl_exit
cl_destroy:
mov byte[field+ebx],0
no_cl_destroy:
mov edx,ebx
jmp cl_begin
cl_exit:
pop edx ecx
inc edx
loop cl_loop
popa
ret
; *********************************************
; *** USED BY CHECK_WIN IN SOKONEX & SOKOLOR **
; *********************************************
scan_root: ; input: dx-beginning cell, ebx-what to search
push esi
mov edi,srch ; output: eax-number of win_obj found
mov eax,0xfff
movzx ecx,[checkcount]
inc ecx
cld
rep stosw ; clearing area for scan
movzx ebx,dx
and edx,eax ; dx-cell number to compare with
shr ebx,12 ; bl-obj id
mov [color],bl
mov esi,srch
mov edi,eax ; mask to extract cell
mov word[srch],dx
sr_loop:
lodsw
push esi ; saving scan pointer
movzx edx,ax ; edx-[dirs*4][cell*12]
and edx,edi
; debug_print ' >'
mov ecx,4
sr_dir_loop1:
; debug_print '.'
push ecx ; saving dir counter
lea ebx,[ecx+11]
bts word[esi-2],bx
jc sr_endloop ; this entry is already processed
; debug_print '^'
dec ecx ; cl-direction
call get_cell_at ; bx-new position, al-object
; cmp [workmode],sSokonex
; jne no_sr_nex
call chk_win_obj
jne sr_endloop ; not a win_obj there
; debug_print '@'
cmp [workmode],sSokolor
jne no_sr_lor
cmp al,[color]
jne sr_endloop
no_sr_lor:
push esi
mov esi,srch ; let us search for existing entries
sr_loop1:
lodsw
and eax,edi ; eax-cell w/o dirs
cmp eax,ebx
je sr_foundentry ; this is the entry we're seeking for
cmp word[esi],0xfff
jnz sr_loop1 ; next entry
; we reached empty area
mov [esi],bx
add esi,2
sr_foundentry:
mov eax,15
sub eax,ecx
bts [esi-2],ax ; mark entry as used
pop esi
; inc [e_fnd] ; one more obj found
sr_endloop:
pop ecx
loop sr_dir_loop1
; jmp tttt
; sr_dir_loop:
; jmp sr_dir_loop1
; tttt:
pop esi
cmp word[esi],0xfff
jne sr_loop
mov eax,esi
sub eax,srch
shr eax,1
pop esi
; debug_print_dec eax
ret
; *********************************************
; *** SPECIAL ROUTINE TO DRAW LASERS **********
; *********************************************
draw_lasers:
xor edx,edx
mov ecx,[fld_size]
dl_loop:
push ecx edx
mov cl,[field+edx]
sub cl,tLaserW
jl dl_eloop
inc ch
dl_gca:
call get_cell_at
cmp al,tEmpty
je dl_draw
cmp al,tHole
jne dl_eloop
dl_draw:
call draw_beams
mov edx,ebx
jmp dl_gca
dl_eloop:
pop edx
inc edx
pop ecx
loop dl_loop
ret
; *********************************************
; *** DRAWS LASER BEAMS IN CERTAIN DIRECTION **
; *********************************************
draw_beams:
pusha
mov esi,[levptr]
movzx esi,byte[esi+1]
mov eax,ebx
xor edx,edx
div esi
movzx esi,cl
dec esi
shr esi,1
and esi,1
shl edx,20
mov ebx,edx
shl eax,20
mov ecx,eax
add ebx,dword[beam_xy+esi*8]
add ecx,dword[beam_xy+esi*8+4]
mov edx,0xe9e25c
mov eax,13
int 0x40
popa
ret
ud:
ud2 ; debugging purposes only
; *********************************************
; *** COMPRESS LEVEL - NOT READY YET **********
; *********************************************
; push esi ebx ;ecx
; xchg ebx,edi
; mov esi,edi ; esi,edi - beginning
;; ebx - end of unpacked field
; first_enc:
; lodsb ; al - first byte
; shl ax,8 ; ah - this byte, al=0
; next_enc:
; cmp esi,ebx
; jae exit_enc
;; movzx ecx,byte[esi]
;; debug_print_dec ecx
; cmp ah,byte[esi]
; jne newchar
; inc esi
; inc al
; cmp al,15
; jb next_enc
; newchar:
; shl al,4
; shr ax,4
; stosb
; jmp first_enc
; exit_enc:
; shl al,4
; shr ax,4
; stosb
; mov al,0xff
; stosb
; pop ebx esi ecx
;
; dec ecx
; jcxz outcycle
; jmp next_lev
; outcycle:
; ‡¤¥áì ­ å®¤ïâáï ¤ ­­ë¥ ¯à®£à ¬¬ë:
; ¨­â¥àä¥©á ¯à®£à ¬¬ë ¤¢ãï§ëç­ë© - § ¤ ©â¥ ï§ëª ¢ macros.inc
load_char:
if lang eq ru
db '‡ £à㧨âì'
else
db 'Open file'
end if
loadlen:
ll_msg:
if lang eq ru
db '‚ë¡¥à¨â¥ ã஢¥­ì'
else
db 'Choose a level'
end if
db ' (0-9, PgUp, PgDn)'
ll_msg_end:
fn_input:
; db 'cnf'
; db 'soko-4.lev'
if lang eq ru
db '¨«¨ ¢¢¥¤¨â¥ ¨¬ï ä ©« '
else
db 'or enter a filename'
end if
inp_end:
rb 256-(inp_end-fn_input)
win_msg:
if lang eq ru
db '“à !!! ‚ë ¯à®è«¨ ã஢¥­ì!'
else
db "You've completed the level!"
end if
win_msg_end:
lose_msg:
if lang eq ru
db '‚ë ¯ à «¨§®¢ ­ë! <20>ந£àëè...'
else
db "You're paralized! Game over..."
end if
lose_msg_end:
zagolovok: ; áâப  § £®«®¢ª 
if lang eq ru
db 'ŽŠŽ<C5A0><EFBFBD> „‹Ÿ'
else
db 'SOKOBAN FOR'
end if
db ' MENUET'
zag_konets: ; ¨ ¥ñ ª®­¥æ
pic_map:
db 0xf,9,0,0,1,1,5,6
pm_nex:
db 2,7,8,3,4,0xa,0xa,0xa,0xa
pm_col:
db 0xb,0xc,0xd,0xe
beam_xy:
dd (FLD_LEFT+7) shl 16+2, FLD_TOP2+16
dd FLD_LEFT2+16, (FLD_TOP+7) shl 16+2
ll_num db '00x.'
move_map dd -1,+0,-0,1 ; 0 - W, 1 - S, 2 - N, 3 - E
stdlev db 'SOKO-0.LEV',0
stdlev_len:
inp_pos dd inp_end-fn_input
entered dd 0
file_info:
dd 0
dd 0
dd 0x100
cnf_level dd strip
dd workarea
file_name db CUR_DIR
path_end db 'SKIN.'
file_num db 'RAW',0
rb 256-($-file_name)
I_END: ; ª®­¥æ ¯à®£à ¬¬ë
winmode db ?
scanptr dd ?
levpage dd ?
workmode db ?
player dw ?
fld_size dd ?
levptr dd ?
wnd_height dd ?
wnd_width dd ?
color db ?
colcount db ?
levelcount dd ?
checkcount db ?
checkpoint:
times 256 dw ?
levelmap:
times 1024 dd ?
strip rb SKIN_SIZE
workarea:
srch rb 0x10000-($-workarea)
level_start rb 0x20000
field: