; ; pipes kolibri ; v1.21 ; 2006 by Mario Birkner ; ; l.mod. 27.08.06/15:11 ; ; Compile with FASM ; bgcolor equ 0x0074744A ;thx fgcolor equ 0x00E7C750 ;to fg2color equ 0x00E0B0A0 ;colorref fg3color equ 0x007F7F55 btcolor equ 0x005B6200 include '..\..\macros.inc' include 'lang.inc' ; fetch the UTF-8 character in string+offs to char ; common part for all encodings: translate pseudographics ; Pseudographics for the boot screen: ; 0x2500 -> 0xC4, 0x2502 -> 0xB3, 0x250C -> 0xDA, 0x2510 -> 0xBF, ; 0x2514 -> 0xC0, 0x2518 -> 0xD9, 0x252C -> 0xC2, 0x2534 -> 0xC1, 0x2551 -> 0xBA macro fetch_utf8_char string, offs, char, graph { local first_byte, b virtual at 0 db string if offs >= $ char = -1 else ; fetch first byte load first_byte byte from offs if first_byte < 0x80 char = first_byte offs = offs + 1 else if first_byte < 0xC0 .err Invalid UTF-8 string else if first_byte < 0xE0 char = first_byte and 0x1F load b byte from offs + 1 char = (char shl 6) + (b and 0x3F) offs = offs + 2 else if first_byte < 0xF0 char = first_byte and 0xF load b byte from offs + 1 char = (char shl 6) + (b and 0x3F) load b byte from offs + 2 char = (char shl 6) + (b and 0x3F) offs = offs + 3 else if first_byte < 0xF8 char = first_byte and 0x7 load b byte from offs + 1 char = (char shl 6) + (b and 0x3F) load b byte from offs + 2 char = (char shl 6) + (b and 0x3F) load b byte from offs + 3 char = (char shl 6) + (b and 0x3F) offs = offs + 4 else .err Invalid UTF-8 string end if end if end virtual if char = 0x2500 graph = 0xC4 else if char = 0x2502 graph = 0xB3 else if char = 0x250C graph = 0xDA else if char = 0x2510 graph = 0xBF else if char = 0x2514 graph = 0xC0 else if char = 0x2518 graph = 0xD9 else if char = 0x252C graph = 0xC2 else if char = 0x2534 graph = 0xC1 else if char = 0x2551 graph = 0xBA else graph = 0 end if } ; Latin-1 encoding ; 0x00-0xFF - trivial map macro latin1 [arg] { local offs, char, graph offs = 0 while 1 fetch_utf8_char arg, offs, char, graph if char = -1 break end if if graph db graph else if char < 0x100 db char else .err Failed to convert to Latin-1 end if end while } use32 org 0x0 db 'MENUET01' ; 8 byte id dd 0x01 ; header version dd START ; start of code dd I_END ; size of image dd 0x100000 ; memory for app dd 0x7fff0 ; esp dd 0x0 , 0x0 ; I_Param , I_Icon START: ; start of execution jmp red still: mcall 10 ; wait here for event cmp eax,1 ; redraw request ? je red cmp eax,2 ; key in buffer ? je key cmp eax,3 ; button in buffer ? je button jmp still red: ; redraw call draw_window call draw_board call draw_message jmp still key: ; key mcall 2 ; just read it and ignore jmp still button: ; button call get_input jmp still get_input: pusha mcall 17 ; get id cmp ah,1 ; button id=1 ? jne .noclose mcall -1 ; close this program .noclose: cmp ah,4 jne .moderate mov [diffic],1 jmp .enddiffic .moderate: cmp ah,3 jne .easy mov [diffic],3 jmp .enddiffic .easy: cmp ah,2 jne .board mov [diffic],5 .enddiffic: mov [score],0 mov [speed],40 mov [level],1 mov [stat],0 mov [time],0 call draw_window call scramble_board call draw_board call countdown call wassermarsch jmp .getno .board: cmp [stat],2 jge .getno shr eax,8 ; -> 24bit id cmp eax,10 jle .getno cmp eax,150 jg .getno sub eax,10 mov edi,eax add edi,map cmp [edi], byte 1 jg .nogerade xor byte [edi], 1 call draw_board jmp .getno .nogerade: cmp [edi], byte 6 jge .getno cmp [edi], byte 5 jne .rota sub byte [edi],4 .rota: inc byte [edi] call draw_board .getno: popa ret ;//// end of event detection get_direction: ;Setzt Richtungs-Konstanten pusha ;IN: mov eax,[esp+28] ;eax - Richtung IN mov ebx,[esp+16] ;ebx - Teilchen (Map-Wert) cmp ebx,0 ;OUT: jne .no0 ;eax - Richtung OUT cmp eax,14 jne .o0 jmp .setout .o0: cmp eax,-14 jne .col jmp .setout .no0: cmp ebx,1 jne .no1 cmp eax,1 jne .o1 jmp .setout .o1: cmp eax,-1 jne .col jmp .setout .no1: cmp ebx,2 jne .no2 cmp eax,14 jne .o2 sub eax,13 jmp .setout .o2: cmp eax,-1 jne .col sub eax,13 jmp .setout .no2: cmp ebx,3 jne .no3 cmp eax,-14 jne .o3 add eax,15 jmp .setout .o3: cmp eax,-1 jne .col add eax,15 jmp .setout .no3: cmp ebx,4 jne .no4 cmp eax,-14 jne .o4 add eax,13 jmp .setout .o4: cmp eax,1 jne .col add eax,13 jmp .setout .no4: cmp ebx,5 jne .no5 cmp eax,14 jne .o5 sub eax,15 jmp .setout .o5: cmp eax,1 jne .col sub eax,15 jmp .setout .no5: cmp ebx,6 jne .no6 jmp .setout .no6: cmp ebx,7 jne .no7 mov eax,14 jmp .setout .no7: cmp ebx,8 jne .no8 cmp eax,14 jne .col mov [stat],1 jmp .setout .no8: cmp ebx,16 ; cross 2x jne .col add [score],10 ; + 10 bonus points jmp .setout .col: xor eax,eax .setout: xor ebx,ebx mov [esp+28],eax mov [esp+16],ebx popa ret countdown: pusha xor eax,eax mov al,[diffic] imul eax,10 mov [time],eax .udown: call show_score mov ecx,10 .down: mov eax,5 mov ebx,10 mcall mov eax,11 mcall cmp eax,1 jne .nored call draw_window call draw_board jmp .nothing .nored: cmp eax,3 jne .nothing call get_input .nothing: cmp [stat],0 ;bugfix 210806 jnz .exitsub ;bugfix 210806 dec ecx jnz .down dec [time] jnz .udown .exitsub: ;bugfix 210806 popa ret wassermarsch: pusha .restart: mov esi,map+16 ;start position mov eax, 14 ;start-richtung .findway: movzx ebx, byte [esi] call get_direction test eax,eax jz .collision push eax xor eax,eax mov al,6 sub al,[diffic] add [score],eax ;points/item = 6 - difficulty mov ecx,dword [speed] add byte [esi],10 .down: mov eax,5 mov ebx,2 mcall mov eax,11 mcall cmp eax,1 jne .nored call draw_window .nored: cmp eax,3 jne .noevnt call get_input .noevnt: dec ecx jnz .down pop eax add esi,eax call draw_board call show_score jmp .findway .collision: cmp [stat],1 jne .loose call draw_message mov eax,5 mov ebx,500 mcall mov [stat],0 inc [level] cmp [speed],6 ;waterflowdelay < 6 ? jle .skipsub sub [speed],2 .skipsub: call draw_window call scramble_board call draw_board call countdown jmp .restart .loose: mov [stat],2 call draw_message popa ret show_score: pusha mov eax,13 ;clear time and score area mov ebx,50 shl 16 +15 mov ecx,395 shl 16 +15 mov edx,bgcolor mcall if lang eq et add ebx,60 shl 16 + 30 else add ebx,60 shl 16 + 20 end if mcall add ebx,80 shl 16 mcall mov eax,47 mov ebx,0x20000 mov ecx,[time] mov edx,50*65536+398 mov esi,fg2color mcall mov ebx,0x50000 mov ecx,[score] if lang eq et add edx,70 shl 16 else add edx,60 shl 16 end if mcall mov ebx,0x20000 mov ecx,[level] add edx,80 shl 16 mcall popa ret scramble_board: pusha mov edi,map+16 ;startpunkt mov eax,7 ;wieder- stosb ;herstellen mov ebx, 0x00000007 ;modul m max-wert .loop_through: mov esi,edi lodsb cmp eax, 9 je .skip inc eax xor edx, edx div ebx ;modulo -> edx mov eax, edx cmp eax,6 jne .skip dec [half] movzx eax, byte [half] jnz .skip mov [half], byte 7 .skip: stosb cmp edi,map+125 ;endpunkt erhalten jge .exit jmp .loop_through .exit: mov eax,8 stosb popa ret gen_image: pusha xor ebx,ebx ;default: kein wasser movzx eax,byte [map] ;erstes byte der map lesen (position) inc byte [map] ;position inkrementieren add eax,map ;zur position die map-adresse addieren movzx esi,byte [eax] cmp esi,10 jl .nowater sub esi,10 ;map-werte+10 sind mit wasser gefuellt mov ebx,1 cmp esi,16 jne .nowater sub esi,10 .nowater: imul esi,3072 ;mapwert * 32*32*3 = image-adresse add esi,images mov edi,0x10000 mov ecx,32*32*3 .gendd: ;RGB-Image im Speicher generieren mov eax,dword [esi] ;byte aus imagemap lesen shl eax,8 shr eax,8 cmp ebx,0 jz .nowcolor mov ebx,eax cmp ebx,0x00B0B5B0 jne .nog1 jmp .wcolor .nog1: cmp ebx,0x00A0A5A0 jne .nog2 jmp .wcolor .nog2: cmp ebx,0x00909590 jne .nog3 jmp .wcolor .nog3: cmp ebx,0x00808580 jne .nog4 jmp .wcolor .nog4: cmp ebx,0x00707570 jne .nowcolor jmp .wcolor .wcolor: add eax,0x40 .nowcolor: add esi,3 stosd dec edi loop .gendd popa ret ; ********************************************* ; ******* WINDOW DEFINITIONS AND DRAW ******** ; ********************************************* draw_message: pusha cmp [stat],0 je .nomessage mov eax,13 mov ebx,146 shl 16 + 200 mov ecx,190 shl 16 + 40 mov edx,0x0 mcall add ebx,2 shl 16 - 4 add ecx,2 shl 16 - 4 mov edx,fgcolor mcall cmp [stat],3 jne .stat1 mov eax,4 mov ebx,174 shl 16 +206 mov edx,lbl_start_a_new_game+1 movzx esi,byte [lbl_start_a_new_game] mov ecx,btcolor add ecx,0x10000000 mcall jmp .nomessage .stat1: cmp [stat],1 je .winmessage mov eax,4 mov ebx,186 shl 16 +200 mov edx,lbl_gameover+1 movzx esi,byte [lbl_gameover] mov ecx,btcolor add ecx,0x10000000 mcall add ebx,8 shl 16 +17 mov edx,lbl_yscore+1 movzx esi,byte [lbl_yscore] mov ecx,btcolor mcall mov esi,ecx ;color mov edx,ebx ;pos add edx,80 shl 16 mov ebx,0x50000 ;type mov ecx,[score] ;inp mov eax,47 mcall jmp .nomessage .winmessage: mov eax,4 mov ebx,152 shl 16 +200 mov edx,lbl_win+1 movzx esi,byte [lbl_win] mov ecx,btcolor add ecx,0x10000000 mcall mov ebx,152 shl 16 +217 add edx,esi mov ecx,btcolor mcall .nomessage: popa ret draw_board: pusha mov ebx,15*65536+32 mov ecx,50*65536+32 mov edx,15*65536+50 ;Spielfeldposition mov esi,10 ;Spielfeldgroesse Y .vloop: mov edi,14 ;Spielfeldgroesse X .hloop: call gen_image push edx mov eax,8 movsx edx, byte [map] add edx,9 ;button-id = map-pos + 10;gen_image inkrements add edx,0x80000000 ;first delete previous button mcall sub edx,0x30000000 ;first delete previous button mcall pop edx push ebx push ecx mov eax,7 mov ebx,0x10000 mov ecx,32 shl 16 +32 mcall pop ecx pop ebx add edx,33 shl 16 add ebx,33 shl 16 dec edi jnz .hloop sub edx,14*(33 shl 16) ;Spielfeldgroesse X sub ebx,14*(33 shl 16) add edx,33 add ecx,33 shl 16 dec esi jnz .vloop mov [map], byte 1 ;Map-Position zuruecksetzen popa ret draw_window: pusha mcall 12,1 mov eax,0 ; function 0 : define and draw window mov ebx,100*65536+492 ; [x start] *65536 + [x size] mov ecx,100*65536+420 ; [y start] *65536 + [y size] mov edx,bgcolor ; color of work area RRGGBB,8->color gl or edx,0x14000000 mov edi,title mcall mov eax,8 mov ebx,84*65536+72 mov ecx,28*65536+15 mov edx,2 mov esi,btcolor mcall add ebx,76 shl 16 inc edx mcall add ebx,76 shl 16 inc edx mcall mov eax,4 mov ebx,26 shl 16 +32 mov ecx,fgcolor mov edx,lbl_toolbar+1 movsx esi, byte [lbl_toolbar] mcall mov ebx,18 shl 16 +398 mov edx,lbl_score+1 movsx esi, byte [lbl_score] mcall mov ebx,340 shl 16 +405 mov ecx,fg3color mov edx,lbl_copy+1 movsx esi,byte [lbl_copy] mcall mcall 12,2 popa ret ; DATA AREA if lang eq et title db 'Torud',0 lbl_gameover: db 19 latin1 'M ä n g L ä b i !' lbl_start_a_new_game: db 21 latin1 'Alusta enne uut mängu' lbl_win: db 32 latin1 ' T u b l i ! ' latin1 ' Lähme edasi! ' lbl_yscore: db 12 latin1 'Sinu tulemus:' lbl_toolbar: db 43 latin1 'Uus mäng: Lihtne Keskmine Raske' lbl_copy: db 24 latin1 'v1.21 2006,Mario Birkner' lbl_score: db 28 latin1 'Aeg: Tulemus: Tase:' else title db 'Pipes',0 lbl_gameover: db 19 db 'G a m e O v e r !' lbl_start_a_new_game: db 22 db 'Start a new game first' lbl_win: db 32 db ' G r e a t ! ' db " Let's goin'on! " lbl_yscore: db 11 db 'Your Score:' lbl_toolbar: db 43 db 'New Game: Easy Moderate Hard' lbl_copy: db 24 db 'v1.21 2006,Mario Birkner' lbl_score: db 28 db 'Time: Score: Level:' end if stat db 3 ;0=gameplay 1=won 2-lost 3=stopped speed db 0 time dd 0 diffic db 0 ;1=hard 3=moderate 5=easy 8=dedicated to Wildwest - try it out! score dd 0 level dd 1 half db 1 ;reduces the random-crosses map: ;14*10 blocks + position db 1 ;<- act. position db 9,9,9,9,9,9,9,9,9,9,9,9,9,9 db 9,7,1,3,2,0,1,1,0,3,4,4,3,9 db 9,5,0,2,2,1,3,0,3,1,1,6,4,9 db 9,4,0,4,6,0,3,3,2,6,0,1,2,9 db 9,3,0,1,2,4,6,4,5,1,2,4,1,9 db 9,5,3,2,6,3,2,1,2,1,2,6,0,9 db 9,4,0,2,3,0,4,1,2,3,2,3,4,9 db 9,2,0,4,5,6,3,1,3,0,4,1,0,9 db 9,1,0,3,5,4,2,2,4,1,6,0,8,9 db 9,9,9,9,9,9,9,9,9,9,9,9,9,9 images: file 'pipes.raw' I_END: