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