0,0 → 1,1161 |
; 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 |
|
CUR_DIR equ '/HD/1/MENUETOS/' ; 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 |
|
include 'macros.inc' ; decrease code size (optional) |
include 'celltype.inc' ; object identifiers |
;include 'debug.inc' |
;lang equ ru ; russian interface; english if undefined |
|
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 'ë ¯ à «¨§®¢ ë! ந£àëè...' |
else |
db "You're paralized! Game over..." |
end if |
lose_msg_end: |
|
zagolovok: ; áâப § £®«®¢ª |
if lang eq ru |
db ' ' |
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: |