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