kolibrios-fun/programs/games/megamaze/trunk/megamaze.asm
Yogev Ezra 7a91a704c5 Added sources of the following games: mario2, megamaze, MSquare, pig, soko.
git-svn-id: svn://kolibrios.org@1806 a494cfbc-eb01-0410-851d-a64ba20cac60
2011-01-30 11:17:50 +00:00

856 lines
15 KiB
NASM

IDA equ 1 ; We're running debugida.exe
STRIP equ 40
LEVNUM equ 500
XFOFS equ 10
YFOFS equ 55
MSGXO equ 32
GAMES_ALL equ 12
WNDCOLOR equ 0x03c0c0c0;0x03f6f6f6;
MINCS equ 40
MAXCS equ 80
macro icall lbl
{
call [lbl+ebp*4]
}
use32
org 0x0
db 'MENUET01' ; 8 byte id
dd 0x01 ; header version
dd run ; start of code
dd I_END ; size of image
dd end_mem ; memory for app
dd stack_end ; esp
dd 0x0 , 0x0 ; I_Param , I_Icon
lang fix ru
include "MACROS.INC"
purge mov
;include "DEBUG.INC"
COLOR_ORDER equ MENUETOS
include 'gif_lite.inc'
include 'tam.inc'
include 'smz.inc'
include 'tilt.inc'
include 'tilt2.inc'
include 'fhouse.inc'
include 'loops.inc'
include 'wriggle.inc'
include 'blackbox.inc'
include 'marble.inc'
include 'cstep.inc'
include 'orient.inc'
include 'nolt.inc'
include 'colzone.inc'
run:
mov [Ces],STRIP;20
mcall 3
mov cl,16
ror eax,cl
mov [generator],eax ; random generator from Tetris
and [mpress_flag],0
and [gif_unp],0
xor ebp,ebp ; game_t
; mov ebp,10
mcall 64,1,end_mem
mov [pause_time],40
call resize
.game1:
mov [levnum],LEVNUM
.game:
and [win_flag],0
and [drag_flag],0
mov ecx,[levnum]
mov esi,[levels+ebp*4]
jecxz .skip
.nxt:
movzx eax,byte[esi]
add esi,eax
xor eax,eax
cmp al,byte[esi]
jne .noz
mov esi,LEVNUM;500
sub esi,ecx
mov [levcount],esi
and [levnum],0
jmp .game
.noz:
loop .nxt
.skip:
mcall 40,111b
mov [mouse_processed],1
xor eax,eax
icall prepare_level
wnd_size:
mov eax,[Ces]
shr eax,2
sub eax,2
mov [sq_size],eax
if ~ IDA eq 1
mov edx,[fx]
imul edx,[Ces]
add edx,XFOFS*2+20
mov esi,[fy]
imul esi,[Ces]
add esi,YFOFS+30
mov ecx,-1
mcall 67,ecx
end if
red:
call draw_window
drw:
call drwfld
still:
mcall 2
test al,al
jz still
mcall 10
cmp eax,2
je key
cmp eax,1 ; redraw request ?
je red
cmp eax,3 ; button in buffer ?
je button
cmp eax,6 ; mouse event ?
je mouse
key:
mcall 2
; movzx ebx,ah
; dpd ebx
cmp ebp,10
je .noplus
mov ebx,5
cmp ah,184
jne .nomin
cmp [Ces],MINCS
je still
.ces:
sub [Ces],ebx
call resize
jmp wnd_size
.nomin:
cmp ah,183
jne .noplus
cmp [Ces],MAXCS
je still
neg ebx
jmp .ces
.noplus:
cmp ah,'h'
jne .nohlp
; if IDA eq 1
; cmp [child],0
; jne still
; else
call kill_help
; end if
mov [pack],ebp
mcall 51,1,show_help,chs_end
; dpd eax
mov [child],eax
jmp still
.nohlp:
cmp [win_flag],10
je .levover
cmp [win_flag],2
je .no_win
cmp [win_flag],1
jne .now
.levover:
call lev_next
.no_win:
and [win_flag],al
jmp run.game
.now:
shr eax,8
mov [jump],drw;red
cmp eax,13
je run.game
icall key_handler
jmp [jump]
button:
mcall 17
cmp ah,1
je close
cmp ah,2
je .game_type
cmp ah,4
je .inclev
cmp ah,3
je .declev
jmp still
.declev:
dec [levnum]
cmp [levnum],0
jge run.game
push [levcount]
pop [levnum]
jmp run.game
.inclev:
call lev_next
jmp run.game
.game_type:
inc ebp
cmp ebp,GAMES_ALL
jbe run.game1
xor ebp,ebp
jmp run.game1
close:
if ~ IDA eq 1
call kill_help
end if
mcall -1
;if ~ IDA eq 1
kill_help:
mcall 9,prc_info2,-1
mov edx,[child]
mov ecx,eax
.lp:
mcall 9
cmp edx,[ebx+30]
jne .nochild
mcall 18,2
and [child],0
ret
.nochild:
loop .lp
ret
;end if
mouse:
cmp [mouse_processed],1
jne .ex
mcall 37,1
sub eax,XFOFS shl 16+YFOFS
xor edx,edx
mov ebx,[Ces]
mov ecx,eax
and eax,0xffff
div ebx
xor edx,edx
mov [mouse_y],eax
cmp eax,[fy]
jae .ex
mov eax,ecx
shr eax,16
div ebx
mov [mouse_x],eax
cmp eax,[fx]
jae .ex
mcall 37,2 ; get buttons
cmp [drag_flag],0
je .nodrag
mov ebx,eax
cmp eax,[mpress_flag]
mov eax,-1
je .nochg
dec eax
.nochg:
mov [mpress_flag],ebx
jmp .call_hnd
.nodrag:
test eax,eax
jz .ex1
cmp eax,[mpress_flag]
je .ex
mov [mpress_flag],eax
mov eax,-1
.call_hnd:
mov [mouse_processed],0
icall key_handler
jmp [jump]
.ex1:
mov [mpress_flag],0
.ex:
jmp still
lev_next:
push eax
inc [levnum]
mov eax,[levnum]
cmp eax,[levcount]
jbe .ex
and [levnum],0
.ex:
pop eax
ret
; *********************************************
; ******* WINDOW DEFINITIONS AND DRAW ********
; *********************************************
draw_window:
pusha
mcall 12,1
mov ebx,[fx]
imul ebx,[Ces]
push ebx
add ebx,50 shl 16+XFOFS*2+20
mov ecx,[fy]
imul ecx,[Ces]
add ecx,10 shl 16+YFOFS+30
mcall 0,,,WNDCOLOR
mov esi,edx
and esi,0xffffff
mcall 9,prc_info,-1
mov ebx,[esp]
pop ebx
add ebx,XFOFS shl 16+XFOFS*2
mcall 8,,<25,12>,2
mcall 8,<XFOFS,11>,<40,12>,3
add ebx,14 shl 16
inc edx
mcall
mcall 4,<8,8>,0x10ffffff,header,header.size
mov ecx,ebp
mov edx,game_names+4
call get_mstr
mcall ,<XFOFS+2,28>,0x8000
imul esi,6
add esi,3
shl esi,16
lea edx,[ebx+esi]
mcall 47,0x020001,levnum,,0x8000
mcall 4,<XFOFS+3,43>,0x108000,next_msg,3
mcall 12,2
popa
ret
unpack_level:
mov ecx,[cell_count]
mov edi,field
.lp:
movzx eax,byte[esi]
inc esi
shl ax,4
shr al,4
stosw
loop .lp
ret
get_xy:
; eax-coord
; out: [lx]-[x+2][CS-4],[ly]-[y+2][CS-4]
pusha
xor edx,edx
mov esi,[sq_size]
lea edi,[esi*2]
neg edi
add edi,[Ces]
mov [lx],edi
mov [ly],edi
mov ebx,[fx]
div bx
imul eax,[Ces]
imul edx,[Ces]
lea edx,[edx+XFOFS+esi]
lea eax,[eax+YFOFS+esi]
mov word[ly+2],ax
mov word[lx+2],dx
popa
ret
check_move:
; eax-coord, ebx-direction
; CF=0 if move is valid
bt dword[field+eax],ebx
ret
delay:
pusha
mcall 5,[pause_time]
popa
ret
get_mstr:
; in: edx,ecx
; out: edx,esi
mov esi,[edx-4]
jecxz .ex
lea edx,[edx+esi+4]
dec ecx
jmp get_mstr
.ex:
ret
maze_field:
mov edi,field
mov [ly],YFOFS shl 16+YFOFS
mov eax,38
mov ecx,[fy]
.lp1:
push ecx
mov [lx],XFOFS shl 16+XFOFS
mov ecx,[fx]
.lp2:
push ecx
xor esi,esi
.lp3:
mov edx,0xd0d0d0
bt dword[edi],esi
jnc .gray
mov edx,0
.gray:
mov ebx,[lx]
add ebx,[dir_ofs+esi*4]
mov ecx,[ly]
add ecx,[dir_ofs+esi*4+8]
mcall
inc esi
cmp esi,4
jb .lp3
inc edi
mov ecx,[Ces]
add word[lx],cx
add word[lx+2],cx
pop ecx
loop .lp2
mov ecx,[Ces]
add word[ly],cx
add word[ly+2],cx
pop ecx
loop .lp1
ret
grid_field:
mov edx,0xa0a0a0
mov eax,38
mov ecx,[fy]
mov ebx,[fx]
imul ebx,[Ces]
add ebx,XFOFS shl 16+XFOFS
mov esi,YFOFS shl 16+YFOFS
inc ecx
.lp1:
push ecx
mov ecx,esi
mcall
mov ecx,[Ces]
add esi,ecx
shl ecx,16
add esi,ecx
pop ecx
loop .lp1
mov ecx,[fx]
mov esi,[fy]
imul esi,[Ces]
add esi,YFOFS shl 16+YFOFS
mov ebx,XFOFS shl 16+XFOFS
inc ecx
.lp2:
push ecx
mov ecx,esi
mcall
mov ecx,[Ces]
add ebx,ecx
shl ecx,16
add ebx,ecx
pop ecx
loop .lp2
ret
get_xy_sf:
xor eax,eax
and [player],eax
mov [fx],eax
mov [fy],eax
lodsb
lodsb
mov ah,al
shr ah,4
and al,0xf
mov byte[fx],ah
mov byte[fy],al
lodsb
mov byte[player],al
lodsb
mov byte[finish],al
.count:
mov eax,[fx]
mov [dirs+4],eax
neg eax
mov [dirs+8],eax
mov eax,[fx]
imul eax,[fy]
mov [cell_count],eax
ret
get_last_mclick:
; out - eax=0 no click or outside field
; eax>0 button pressed, ebx=[xy]
mov [mouse_processed],1
mov eax,[mpress_flag]
mov ebx,[mouse_y]
imul ebx,[fx]
add ebx,[mouse_x]
ret
erase_field:
pusha
mov ecx,[cell_count]
xor eax,eax
mov edi,field
rep stosb
popa
ret
get_pxy:
; in: [pack] - cell#, out: word[pack] - packed [xy]
pusha
mov eax,[pack]
cdq
mov ebx,[fx]
div ebx
shl edx,8
add eax,edx
mov [pack],eax
popa
ret
check_bounds:
; in: eax - cell, ebx - dir
; out: ebx=-1 if bounds crossed
push eax ecx
mov ecx,eax
add ecx,[dirs+ebx*4]
mov ebx,ecx
call get_offset
mov ebx,eax
pop ecx eax
cmp ebx,-1
ret
get_offset:
; in: eax - start, ebx-end
; out: eax - dir or -1 if not straight
; ebx - distance
push ecx edx
mov ecx,-1
mov edx,[cell_count]
cmp eax,edx
jae .ex
cmp ebx,edx
jae .ex
mov [pack],eax
call get_pxy
mov eax,[pack]
mov [pack],ebx
call get_pxy
mov ebx,[pack]
cmp ah,bh ; compare X
jne .noX
mov ecx,1
sub bl,al
ja .ok
inc ecx
.ok2:
neg bl
jmp .ok
.noX:
cmp al,bl ; compare Y
jne .ex
inc ecx
sub bh,ah
mov bl,bh
jb .ok2
add ecx,3
.ok:
movzx ebx,bl
.ex:
mov eax,ecx
pop edx ecx
ret
show_help:
mov ebp,[pack]
.red:
mcall 12,1
mov ebx,[prc_info.x_start]
add ebx,[prc_info.x_size]
shl ebx,16
add ebx,310
mov ecx,[prc_info.y_start]
shl ecx,16
add ecx,220
mcall 0,,,0x03c0c0c0
mcall 4,<8,8>,0x00ffffff,help_hdr,help_hdr.size
mov ecx,ebp
mov edx,game_names+4
call get_mstr
sub esi,2
mcall 4,<6*help_hdr.size+15,8>,0x00ffffff
mov edx,[help_msg+ebp*4]
add edx,4
xor ecx,ecx
mov ebx,10 shl 16+30
.nxt:
mov esi,[edx-4]
jecxz .drw
dec ecx
lea edx,[edx+esi+4]
jmp .nxt
.drw:
cmp esi,-1
je .edraw
mcall ,,0x000000ff
mov ecx,1
add ebx,12
jmp .nxt
.edraw:
mcall 12,2
.still:
mcall 10
cmp eax,2
jne .nokey
mcall
jmp .close
.nokey:
cmp eax,1 ; redraw request ?
je .red
cmp eax,3 ; button in buffer ?
jne .still
mcall 17
cmp ah,1
jne .still
.close:
and [child],0
mcall -1
getline:
; in: esi,edi
pusha
mov eax,esi
call get_xy
mov ebx,[lx]
mov ecx,[ly]
mov eax,edi
call get_xy
mov bx,word[lx+2]
mov cx,word[ly+2]
mov eax,[Ces]
shr eax,1
sub eax,[sq_size]
add ebx,eax
add ecx,eax
shl eax,16
add ebx,eax
add ecx,eax
mov [lx],ebx
mov [ly],ecx
mcall 38
popa
ret
bold_line:
WGSPC equ 1
pusha
mov edi,WGSPC shl 16+WGSPC
add [lx],edi
add [ly],edi
mcall 38,[lx],[ly]
shl edi,1
sub ebx,edi
sub ecx,edi
mcall
popa
ret
get_rnd:
mov eax, [generator]
sub eax,0x43ab45b5 ; next random number
ror eax,1
xor eax,0x32c4324f
ror eax,1
mov [generator],eax
ret
drwfld:
pusha
mov ebx,[fx]
imul ebx,[Ces]
add ebx,XFOFS shl 16
mov ecx,[fy]
imul ecx,[Ces]
add ecx,YFOFS shl 16
mcall 13,,,WNDCOLOR
add ebx,26 shl 16-26
sub ecx,16 shl 16
mov cx,16
mcall
icall draw_field
icall draw_more
cmp [win_flag],0
jz .edraw
movzx ecx,[win_flag]
mov edx,msgs+4
call get_mstr
mcall 4,<XFOFS+MSGXO,42>,0x100000ff
.edraw:
popa
ret
resize:
mov eax,[Ces]
mov edi,dir_ofs+4
stosd
stosd
stosw
stosw
mov [edi+4],eax
ret
need_image:
; in: eax - gif pointer
cmp [gif_unp],0
jne .skip
push esi edi
mov esi,eax
mov eax,field
mov edi,raw_area
call ReadGIF
mov [gif_unp],1
pop edi esi
.skip:
ret
out_image:
; in: eax - coord, ebx - image #
STRIP2 = STRIP-2
pusha
call get_xy
mov edx,[lx]
mov dx,word[ly+2]
add edx,1 shl 16+1
imul ebx,STRIP2*STRIP2*3
add ebx,raw_area+12
mcall 7,,STRIP2 shl 16+STRIP2
popa
ret
OR_strip:
;file 'orient2.gif'
file 'orientg2.gif'
rd 2
gif_unp dd 0
; DATA AREA
help_hdr db 'MegaMaze Help -'
.size=$-help_hdr
dirs dd -1,0,0,1
dir_ofs dd 0, 1, 1, 1 shl 16+1, 0, 1
dir_rotate db 2,0,3,1,1,3,0,2
w_colors dd 0x0404CA,0xCC0404,0x00CC00
f_colors dd 0x9494FC,0xFC9494,0x99FF99,0xFFFF00
levnum dd LEVNUM
prepare_level dd TM_levelp,SMZ_levelp,TILT_levelp,TILT2_levelp,FH_levelp,\
LP_levelp,WG_levelp,BB_levelp,MAR_levelp,TM_levelp,OR_levelp,NLT_levelp,\
CZ_levelp
key_handler dd TM_key,SMZ_key,TILT_key,TILT2_key,FH_key,LP_key,WG_key,BB_key,\
MAR_key,CSTEP_key,OR_key,NLT_key,CZ_key
draw_more dd TM_drawm,SMZ_drawm,TILT_drawm,TILT2_drawm,FH_drawm,LP_drawm,\
WG_drawm,BB_drawm,MAR_drawm,CSTEP_drawm,OR_drawm,NLT_drawm,CZ_drawm
draw_field dd maze_field,maze_field,maze_field,maze_field,grid_field,\
grid_field,grid_field,grid_field,maze_field,maze_field,OR_drawf,maze_field,\
grid_field
levels dd TM_level,SMZ_level,TILT_level,TILT2_level,FH_level,LP_level,\
WG_level,BB_level,MAR_level,CSTEP_level,OR_level,NLT_level,CZ_level
help_msg dd TM_help,SMZ_help,TILT_help,TILT2_help,FH_help,LP_help,WG_help,\
BB_help,MAR_help,CSTEP_help,OR_help,NLT_help,CZ_help
if lang eq ru
header db 'Mega Maze'
else
header db 'Mega Maze'
end if
.size = $ - header
next_msg db '< >'
game_names mstr \
'Teseus & Minotaur #',\
'1-2-3 Maze #',\
'Tilt Maze #',\
'Double Tilt #',\
'Full-house #',\
'Loops #',\
'Wriggle #',\
'BlackBox #',\
'Marble #',\
'Counter Step #',\
'Orientation #',\
'No left turn #',\
'Colour-zone #'
msgs mstr ' ','You win!!!','Game over.','Start cell?','Dead end!',\
" atoms hidden.",'Ray emerged.','Ray absorbed.','Ray reflected.',\
'Mark exactly guesses','Your score is','Guess mark toggled'
I_END:
main_pid dd ?
child_stack rb 256
chs_end:
drag_flag db ?
sq_size dd ?
mouse_processed dd ?
mpress_flag dd ?
mouse_x dd ?
mouse_y dd ?
Ces dd ?
pack dd ?
fy dd ?
fx dd ?
lx dd ?
ly dd ?
generator dd ?
cell_count dd ?
levptr dd ?
levcount dd ?
score dd ?
player:
teseus dd ?
finish:
minotaur dd ?
stepptr dd ?
cur_step dd ?
win_flag db ?
jump dd ?
pause_time dd ?
child dd ?
area rb 1024
stak rb 1024
stack_end:
prc_info process_information
prc_info2 process_information
field:
rb 128*128
raw_area:
rb STRIP*STRIP*12*3+16
end_mem: