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