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