flat assembler
Message board for the users of flat assembler.
Index
> Macroinstructions > Ultimate High-Level Features |
Author |
|
uart777 12 Nov 2012, 16:53
TEXT.INC
Code: ; $$$$$$$$$$$$$$ Z77 ASM LIBRARY $$$$$$$$$$$$$$$$$ ; ************** SUNGOD SOFTWARE ***************** ; ????????????????? TEXT.INC ????????????????????? ; set.case c ; set case sensitivity ; text.n t ; get # characters (size-1) ; text.write a, b ; copy but no 0 after ; text.write.x... ; write starting at i/ndex ; text.copy a, b ; standard copy with 0 after ; text.copy.n... ; copy with maximum size ; text.attach a, b ; attach b to a; "concencate" ; text.attach.c... ; attach character ; text.attach.n... ; attach number with alignment ; text.equal a, b ; equal? return 0 if not ; text.equal.c t, c ; equals character? ; text.compare a, b ; compare alphabetic. return <0> ; text.search a, b ; search for text. return &/0 ; text.find t, c ; search for character. return &/0 ; text.find.last... ; search for c reverse ; text.count.c t, c ; count # c characters ; text.find.p t, c ; find previous occurance before t ; text.begins a, b ; begins with b? ; text.ends a, b ; ends with b? ; text.lower t ; convert to lowercase ; text.upper t ; convert to uppercase ; text.reverse t ; reverse ; text.expand t, n ; expand; shift right at t ; text.expand.x... ; expand at index ; text.prefix t, s ; expand then insert prefix ; text.insert... ; insert text at index ; text.insert.c... ; insert character ; text.delete.c... ; delete c at index ; text.delete t, n ; delete # characters at t ; text.delete.x... ; delete # characters at index ; text.enclose... ; enclose with 'c' 'c' ; text.align... ; align. example: '0000FFh' ; text.limit... ; end with '...' ; text.array.equal... ; see definitions ; text.array.search... ; set.base b ; set conversion mode: 'd', 'h', 'b' ; n2t n, $t ; convert 32BIT number to text ; t2n $t ; convert text to 32BIT number ; convert.n2t n, $t, b ; see definitions ; convert.t2n $t, b ; ns2t n, $t ; print t, f, ... ; print formatted text ;;;;;;;;;;;;;;; CHARACTER TABLES ;;;;;;;;;;;;;;;;; ; IT - insensitive lookup table. A-Z/a-z are ; the same. this increases processing speed by ; many times. example: if (tt[a]=tt[b]) instead ; of multiple false comparisons per character: ; if ((a>='a'&a<='z')&(b>='a'&b<='z')) | ; ((a>='A'&a<='Z')&(b>='Z'&b<='Z')) ; TT - type lookup table. each byte contains ; C_X BITs to determine its type fast in one ; comparison. example: if tt[c]&SYMBOL IT db \ ; BYTE IT[128]= 00h,01h,02h,03h,04h,05h,06h,07h,08h,09h,0Ah,0Bh,0Ch,0Dh,0Eh,0Fh,\ 10h,11h,12h,13h,14h,15h,16h,17h,18h,19h,1Ah,1Bh,1Ch,1Dh,1Eh,1Fh,\ 20h,21h,22h,23h,24h,25h,26h,27h,28h,29h,2Ah,2Bh,2Ch,2Dh,2Eh,2Fh,\ 30h,31h,32h,33h,34h,35h,36h,37h,38h,39h,3Ah,3Bh,3Ch,3Dh,3Eh,3Fh,\ 40h,41h,42h,43h,44h,45h,46h,47h,48h,49h,4Ah,4Bh,4Ch,4Dh,4Eh,4Fh,\ 50h,51h,52h,53h,54h,55h,56h,57h,58h,59h,5Ah,5Bh,5Ch,5Dh,5Eh,5Fh,\ 60h,41h,42h,43h,44h,45h,46h,47h,48h,49h,4Ah,4Bh,4Ch,4Dh,4Eh,4Fh,\ 50h,51h,52h,53h,54h,55h,56h,57h,58h,59h,5Ah,7Bh,7Ch,7Dh,7Eh,7Fh TT db \ ; BYTE TT[128]= 00h,80h,80h,80h,80h,80h,80h,80h,80h,80h,40h,80h,80h,40h,80h,80h,\ 80h,80h,80h,80h,80h,80h,80h,80h,80h,80h,80h,80h,80h,80h,80h,80h,\ 20h,10h,04h,04h,10h,04h,04h,04h,04h,04h,04h,04h,04h,04h,10h,04h,\ 01h,01h,01h,01h,01h,01h,01h,01h,01h,01h,04h,04h,04h,04h,04h,10h,\ 10h,0Ah,0Ah,0Ah,0Ah,0Ah,0Ah,02h,0Ah,02h,02h,0Ah,02h,0Ah,02h,02h,\ 02h,02h,02h,02h,02h,02h,02h,02h,02h,02h,02h,04h,04h,04h,04h,10h,\ 04h,0Ah,0Ah,0Ah,0Ah,0Ah,0Ah,02h,0Ah,02h,02h,0Ah,02h,0Ah,02h,02h,\ 02h,02h,02h,02h,02h,02h,02h,02h,02h,02h,02h,04h,04h,04h,04h,80h ; 76543210b C_NULL = 00000000b ; 0 C_NUMBER = 00000001b ; 0-9 C_ALPHA = 00000010b ; A-Z, a-z C_SYMBOL = 00000100b ; all symbols except _.?!@$ C_NUMERIC = 00001000b ; A-F/a-f, h,b,k,m/H,B,K,M C_SYMBOLIC = 00010000b ; _.?!@$ C_SPACE = 00100000b ; ' ', '/t' C_RETURN = 01000000b ; 0Dh, 0Ah C_IGNORE = 10000000b ; extended: 1.XXXXXXXb C_KEYWORD = 11111111b C_DIGIT = C_NUMBER or C_NUMERIC C_NAME = C_ALPHA or C_NUMBER or C_SYMBOLIC C_SYMBOLS = C_SYMBOL or C_SYMBOLIC C_ALPHAN = C_ALPHA or C_NUMBER C_VISIBLE = C_ALPHAN or C_SYMBOLS C_WHITE = C_SPACE or C_RETURN C_BLANK = C_WHITE or C_IGNORE C_END = C_SYMBOL or C_WHITE C_0 = 0 ; is c of type? macro .if.is c, t { let ecx=c, ecx&0FFh,\ eax=>[TT+ecx], eax&C_#t .if true } ; is cl character type? macro .if.c c { .if byte [TT+ecx]&C_##c } macro .if.not.c c { .if.n byte [TT+ecx]&C_##c } macro .else.if.c c { .else.if byte [TT+ecx]&C_##c } macro .if.text.equal a, b { !if text.equal, a, b } macro .if.not.text.equal a, b { !if.n text.equal, a, b } macro .if.text.find a, b { !if text.find, a, b } macro .if.text.find.last a, b { !if text.find.last, a, b } macro .if.text.search a, b { !if text.search, a, b } macro .if.not.text.search a, b { !if.n text.search, a, b } C_TEXT=27h R equ ,0Dh,0Ah, NL db 0Dh, 0Ah, 0 NO.TEXT db '0', 0 ; alternative C names strlen fix text.n strcpy fix text.copy strcmp fix text.compare strcat fix text.attach strchr fix text.find strstr fix text.search ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; set case sensitivity. c=-1 to export case ; and c table addresses align 4 NUMBER CASE=YES ; sensitive by default function set.case, c let eax=[CASE] .if [c]=-1 let edx=IT, ecx=TT .else let [CASE]=[c] .end endf ; get # characters function text.n, t let eax=[t] .while byte [eax] let eax++ .endw let eax-[t] endf ; copy a=b with no 0 after function text.write, a, b let eax=[a], edx=[b] .while byte [edx] let cl=[edx], [eax]=cl,\ eax++, edx++ .endw endf ; write starting at index. no 0 after function text.write.x, a, b, i let eax=[a], eax+[i] text.write eax, [b] endf ; standard copy with 0. return advanced & function text.copy, a, b let eax=[a], edx=[b] .while byte [edx] let cl=[edx], [eax]=cl,\ eax++, edx++ .endw let byte [eax]=0 endf ; copy with maximum size specified function text.copy.n, a, b, n text.n [b] inc eax .if eax<=[n] text.copy [a], [b] .else let eax=[a], edx=[b], [n]-- @@: let cl=[edx], [eax]=cl,\ eax++, edx++, [n]-- jnz @b let byte [eax]=0 .end endf ; attach b to a. return advanced & function text.attach, a, b text.n [a] let eax+[a] text.copy eax, [b] endf function text.attach.c, t, c text.n [t] let eax+[t], ecx=>[c],\ byte [eax]=cl, byte [eax+1]=0 endf ; attach number with optional alignment or 0 function text.attach.n, t, n, a locale p, b(256) let eax=&[b], [p]=eax calla !n2t, [n], [p] .if [a] calla !text.align, [p], '0', [a] .end calla !text.attach, [t], [p] endf ; equal? return 0 if not function text.equal, a, b push esi edi let eax=[a],\ edx=[b] .if [CASE] ; sensitive @@: let \ cl=[eax],\ ch=[edx],\ eax++, edx++ cmp cl, ch ; while *a++=*b++ jne .r0 or cl, ch ; and both nonzero jnz @b or cl, ch ; both must=0 at end jnz .r0 jmp .e .else ; insensitive @@: let \ esi=>[eax],\ edi=>[edx],\ cl=[IT+esi],\ ch=[IT+edi],\ eax++, edx++ cmp cl, ch ; while it[*a++]=it[*b++] jne .r0 or esi, edi ; and both nonzero jnz @b or esi, edi ; both must=0 at end jz .e .end .r0: let eax=0 .e: pop edi esi endf ; 'text' equals 'c'haracter? function text.equal.c, t, c let eax=[t], ecx=>[c] cmp byte [eax], cl jne .r0 let eax++, cl=[eax] test cl, cl jz .! .r0: let eax=0 endf ; lexical comparison. return <0> function text.compare, a, b let eax=[a], edx=[b] @@: let cl=[eax],\ ch=[edx],\ eax++, edx++ cmp cl, ch ; while equal jne @f or cl, ch ; and both nonzero jnz @b @@: sub cl, ch ; return *a-*b movsx eax, cl endf ; search for character. return &/0 function text.find, t, c let eax=[t], edx=[c] @@: let cl=[eax] cmp cl, dl ; if *t=c je .! ; return address inc eax test cl, cl ; while *t++ not 0 jnz @b let eax=0 endf ; search for c reverse function text.find.last, t, c locals p let [p]=[t] text.n [t] ; start at end-1 let eax+[t],\ eax-1, edx=[c] @@: let cl=[eax] test cl, cl jz .r0 cmp [p], eax ; beginning? je .r0 cmp cl, dl ; found je .! dec eax jmp @b .r0: let eax=NO endf ; count # of characters in text function text.count.c, t, c locals p, n let [p]=[t], [n]=0 @@: get [p]=text.find [p], [c] .if true let [p]++, [n]++ jmp @b .end let eax=[n] endf ; find previous occurance of c before t function text.find.p, t, c let eax=[t], eax--, edx=[c] .while byte [eax] let cl=[eax], eax-- cmp cl, dl je .! .endw let eax=0 endf ; search for text. if a contains b. return ; address of first/next appearance or 0 ; if none function text.search, a, b locals s push ebx esi edi let eax=[a], edx=[b] .if [CASE] ; sensitive push esi let esi=edx .sl: let ch=[edx] @@: let cl=[eax],\ eax++ test cl, cl ; if *a=0 jz .r0 cmp cl, ch ; while *a++!=*b jne @b let eax--,\ ; save start address [s]=eax @@: let cl=[eax],\ ch=[edx],\ eax++, edx++ test ch, ch ; if *b=0 jz .r1 cmp cl, ch ; while *a++=*b++ je @b @@: let eax--,\ edx=esi jmp .sl .else ; insensitive let ebx=edx,\ esi=eax, edi=edx .il: let edi=>[edx],\ ch=[IT+edi] @@: let esi=>[eax],\ cl=[IT+esi],\ eax++ or esi, esi ; if *a=0 jz .r0 cmp cl, ch ; while it[*a++]!=it[*b] jne @b let eax--, [s]=eax ; save start address @@: let esi=>[eax],\ edi=>[edx],\ cl=[IT+esi],\ ch=[IT+edi],\ eax++, edx++ test edi, edi ; if *b=0 jz .r1 cmp cl, ch ; while it[*a++]=it[*b++] je @b let eax--, edx=ebx jmp .il .end .r0: let eax=NO jmp @f .r1: let eax=[s] @@: pop edi esi ebx endf ; begins with? return 0 if not function text.begins, a, b locals an push esi edi get [an]=text.n [a] text.n [b] cmp [an], eax ; an<bn? can't contain jl .r0 let eax=[a],\ edx=[b] .if [CASE] ; sensitive @@: let cl=[eax],\ ch=[edx],\ eax++, edx++ test cl, ch ; if either=0 jz @f cmp cl, ch ; while *a++=*b++ je @b @@: ; end test ch, ch ; *b must=0 jnz .r0 jmp .e .else ; insensitive @@: let esi=>[eax],\ edi=>[edx],\ cl=[IT+esi],\ ch=[IT+edi],\ eax++, edx++ test esi, edi ; if either=0 jz @f cmp cl, ch ; while it[*a++]=it[*b++] je @b @@: ; end test edi, edi ; *b must=0 jz .e .end .r0: let eax=0 .e: pop edi esi endf ; ends with? return 0 if not function text.ends, a, b locals an, bn get [an]=text.n [a] get [bn]=text.n [b] let eax=[a],\ ; eax=&(a+an-bn) eax+[an], eax-[bn] text.equal eax, [b] ; equal? endf ; convert to lowercase function text.lower, t let eax=[t] @@: let cl=[eax] cmp cl, 'A' jl .a cmp cl, 'Z' jg .a add byte [eax], 32 .a: inc eax test cl, cl jnz @b endf ; convert to uppercase function text.upper, t let eax=[t] @@: let cl=[eax] cmp cl, 'a' jl .a cmp cl, 'z' jg .a sub byte [eax], 32 .a: inc eax test cl, cl jnz @b endf ; reverse text function text.reverse, t let eax=[t],\ cl=[eax] ; eax=start test cl, cl jz .! text.n [t] let edx=[t],\ edx+eax,\ edx--, eax=[t] @@: ; exchange *eax++/*edx-- let cl=[eax],\ ch=[edx],\ [eax]=ch,\ [edx]=cl,\ eax++, edx-- cmp eax, edx ; while not end jb @b let eax=[t], eax++ endf ; expand; shift all characters right. ; example: 'abc123' becomes 'XXXabc123' ; after expand 3 function text.expand, t, n locals tn get [tn]=text.n [t] let eax+[t], eax--,\ edx=eax, eax+[n] @@: let cl=[edx], [eax]=cl,\ eax--, edx--, [tn]-- jnz @b endf ; expand starting at index function text.expand.x, t, i, n let eax=[t], eax+[i] text.expand eax, [n] endf ; insert text at beginning function text.prefix, a, b text.n [b] text.expand [a], eax text.write [a], [b] endf ; insert text at index function text.insert, a, b, i text.n [b] text.expand.x [a], [i], eax text.write.x [a], [b], [i] endf ; insert character at index function text.insert.c, t, c, i locals n get [n]=text.n [t] .if [i]>=eax text.attach.c [t], [c] .else text.expand.x [t], [i], 1 let eax=[t], edx=eax, eax+[n],\ eax++, byte [eax]=0, edx+[i],\ ecx=[c], byte [edx]=cl .end endf ; delete character at index function text.delete.c, t, i let eax=[t], eax+[i],\ edx=eax, eax++ .if not byte [eax] ; ending c let byte [eax-1]=0 .else ; beginning/middle text.copy edx, eax .end endf ; delete # characters at t. if n>=tn, ; delete all. else, shift all characters to ; the left function text.delete, t, n locals tn get [tn]=text.n [t] let eax=[t] .if [n]>=eax let byte [eax]=0 .else let edx=eax, edx+[n] text.copy eax, edx .end let eax=[t], eax+[n] endf ; delete # characters starting at index function text.delete.x, t, i, n locals tn .if [i]=0 ; delete beginning text.delete [t], [n] escape .end get [tn]=text.n [t] let ecx=[i], ecx+[n] .if ecx>=eax ; delete ending let eax=[t],\ ecx=[i],\ byte [eax+ecx]=0 .else ; delete middle let eax=[t],\ edx=eax, ecx=[i],\ eax+ecx, edx+ecx,\ edx+[n] text.copy eax, edx .end endf ; enclose t in 'c'. insert prefix and attach ; b/egin and e/nd characters. example: ; text.enclose t, '(', ')' function text.enclose, t, b, e locals n get [n]=text.n [t] text.expand [t], 1 let eax=[t], ecx=[b], byte [eax]=cl,\ eax=[t], eax+[n], eax++, ecx=[e],\ byte [eax]=cl, byte [eax+1]=0 endf ; prefix text with c's ('0', ' ', ; etc) or ensure maximum n. example: ; before: TEXT t='7FAB' ; text.align t, '0', 8 ; after: t='00007FAB', aligned to hex32 function text.align, t, c, n locals tn get [tn]=text.n [t] let ecx=[n] .if eax=ecx ; same size escape ; do nothing .end .if eax>ecx ; tn>n? exceeds maximum let eax=[t],\ ; end at t+n byte [eax+ecx]=0 escape .end let ecx-eax, [n]=ecx ; n>tn? expand t text.expand [t], ecx let eax=[t], ecx=[n] @@: let edx=>[c],\ [eax]=dl, eax++, ecx-- jnz @b let ecx=[tn], byte [eax+ecx]=0 endf ; end text with ... but do not exceed maximum _dots: db '...', 0 function text.limit, t, max locals n get [n]=text.n [t] let eax=[t], ecx=[max], edx=[_dots] .if [n]<4 jmp .copy ; only ... .end .if ecx<4 ; max let ecx=4 .end let eax=[t], eax+ecx, eax-4 .copy: let [eax]=edx endf ; search text array ta for t using text.equal ; and text.search. case is considered. ; return index or -1/INVALID if not found. ; ta is an array of text addresses (TEXTA) function text.array.equal, ta, t, n locals i .loop [i]=0 to [n] let eax=[i], eax<<2, eax+[ta] .if.text.equal [t], [eax] return [i] .end .endl let eax=-1 endf function text.array.search, ta, t, n locals i .loop [i]=0 to [n] let eax=[i], eax<<2, eax+[ta] .if.text.search [t], [eax] return [i] .end .endl let eax=-1 endf ; $$$$$$$$$$$$$$ Z77 ASM LIBRARY $$$$$$$$$$$$$$$$$ ; ************** SUNGOD SOFTWARE ***************** ; ???????????????? CONVERT.INC ??????????????????? ; text/number conversions ; n2t n, $t ; convert 32BIT number to text ; t2n $t ; convert text to 32BIT number ; set.base b ; set current base ; 'n' - signed integer; default ; 'u' - unsigned decimal ; 'h' - hexadecimal ; 'b' - binary ; n2t.n/u/h/b must return advanced address (*t=0) ; for "print" ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; align 4 NUMBER BASE='n' _hex: db '0123456789ABCDEF' ; set base for n2t/t2n. b=-1 to get current function set.base, b let eax=[BASE] .if [b] not -1 let [BASE]=[b] .end endf macro get.base { set.base -1 } set.mode fix set.base ; n2t(n, $t) - convert 32BIT number to text function n2t, n, t .if [n]=0 ; 0 value? most common let eax=[t],\ byte [eax]='0',\ eax++,\ byte [eax]=0 ; convert and return escape .end let eax=[BASE],\ ; select conversion mode... ecx=[n], edx=[t] test eax, eax ; 0=default jz .default cmp eax, 'n' ; signed decimal je .default .if eax='u' ; unsigned decimal let eax=!n2t.u .else.if eax='h' ; hexadecimal let eax=!n2t.h .else.if eax='b' ; binary let eax=!n2t.b .else .default: let eax=!n2t.n .end calla eax, ecx, edx endf ; signed number to text function n2t.n, n, t push ebx esi edi let eax=[n], edi=[t] test eax, eax jnz .sign .zero: let byte [edi]='0',\ edi+2, byte [edi]=0, eax=edi jmp .e .sign: jns @f let byte [edi]='-', edi++, [t]++ neg eax @@: let ecx=0CCCCCCCDh, esi=edi .while eax>0 let ebx=eax mul ecx let edx>>>3, eax=edx,\ edx=&[edx+edx*4], edx+edx,\ ebx-edx, bl+'0',\ [edi]=bl, edi++ .endw let byte [edi]=0 push edi text.reverse [t] pop eax .e: pop edi esi ebx endf ; unsigned number to text function n2t.u, n, t push ebx esi edi let eax=[n], edi=[t],\ esi=edi, ecx=1999999Ah @@: let ebx=eax mul ecx let eax=edx,\ edx=&[edx*4+edx],\ edx+edx, ebx-edx,\ bl+'0', [edi]=bl, edi++ test eax, eax jnz @b let byte [edi]=0 push edi text.reverse [t] pop eax pop edi esi ebx endf function n2t.h, n, t ; number to hexadecimal text let eax=[n], edx=[t] @@: let ecx=>al, ecx&15,\ ; *t++=*(_hex+(n&(16-1))) ecx=>[_hex+ecx],\ [edx]=cl, edx++,\ eax>>>4 ; n/16 jnz @b let byte [edx]=0 push edx text.reverse [t] pop eax endf function n2t.b, n, t ; number to binary text let eax=[n], edx=[t] @@: let cl=al, cl&1, cl+'0',\ ; *t++=n&(2-1)+'0' [edx]=cl, edx++,\ ; n/2 eax>>>1 jnz @b let byte [edx]=0 push edx text.reverse [t] pop eax endf ; t2n($t) - convert text to 32BIT number function t2n, t let edx=[t] .while byte [edx]='0' ; skip preceding '0's... let edx++ .endw .if not byte [edx] ; 0 value? most common let eax=0 escape .end let eax=[BASE] ; select conversion mode... test eax, eax ; 0=default jz .default cmp eax, 'n' ; signed decimal je .default .if eax='u' ; unsigned decimal let eax=!t2n.u .else.if eax='h' ; hexadecimal let eax=!t2n.h .else.if eax='b' ; binary let eax=!t2n.b .else .default: let eax=!t2n.n .end calla eax, edx endf function t2n.n, t ; text to signed number locals negate let edx=[t],\ [negate]=0 cmp byte [edx], '-' ; negative? jne @f let edx++, [negate]=1 ; skip @@: calla !t2n.u, edx .if [negate] neg eax .end endf function t2n.u, t ; text to unsigned number let edx=[t], eax=0 @@: let ecx=>[edx], edx++ test ecx, ecx jz @f let \ eax=&[eax+eax*4],\ ; n=n*10+*t++-'0' eax=&[eax+eax-'0'],\ eax+ecx jmp @b @@: endf function t2n.h, t ; hexadecimal text to number let edx=[t], eax=0 @@: let ecx=>[edx], edx++ test ecx, ecx jz .e shl eax, 4 ; n=n*16+c2h(*t++) cmp ecx, '9' ; 0-9 jle .n cmp ecx, 'a' ; A-F jl .a sub ecx, 'a'-10 ; a-f jmp .next .a: sub ecx, 'A'-10 jmp .next .n: sub ecx, '0' .next: add eax, ecx jmp @b .e: endf function t2n.b, t ; binary text to number let edx=[t], eax=0 @@: let ecx=>[edx], edx++ test ecx, ecx jz @f let eax<<1,\ eax=&[eax+ecx-'0'] ; n=n*2+*t++-'0' jmp @b @@: endf macro convert.n2t n, t, b { push [BASE] let [BASE]=b n2t n, t pop [BASE] } macro convert.t2n t, b { push [BASE] let [BASE]=b t2n t pop [BASE] } ; convert numeric size to compact text ; to display in file viewers, progress ; indicators, etc. examples: 4096='4k', ; 16777216='16m', 2147483648='2g'. ; note: unsigned 32BIT arithmetic TEXT max.size.t='>4GB' function ns2t, n, t locals suffix let eax=[n] cmp eax, KB jae @f let ecx='b' jmp .e @@: cmp eax, MB jae @f let eax>>>10, ecx='k' jmp .e @@: cmp eax, GB jae @f let eax>>>20, ecx='m' jmp .e @@: cmp eax, ((4*GB)-1) jbe @f text.copy [t], max.size.t escape @@: let eax>>>30, ecx='g' .e: let [n]=eax, [suffix]=ecx convert.n2t [n], [t], 'u' text.attach.c [t], [suffix] endf ; $$$$$$$$$$$$$$$ Z77 ASM LIBRARY $$$$$$$$$$$$$$$$ ; *************** SUNGOD SOFTWARE **************** ; ?????????????????? PRINT.INC ??????????????????? ; print t, f, ... - print formatted text to buffer. ; a fast alternative to "wsprintfA" that supports ; binary and is easily portable with minimal ; editing. only about 100 lines! ; %t %s - 'text'; "string" ; %c - character ; %n %i %d - 32BIT decimal signed ; %u - 32BIT decimal unsigned ; %b - 32BIT binary ; %h %x - 32BIT hexadecimal ; %r - return. insert 0Dh, 0Ah ; %0 - 0/NULL ; %% - % macro print t, f, [p] { common callv !print, t, f, p } ; see SYNTAX.INC for callv (with variable ; arguments). it will push invisible n ; (# parameters) then adjust esp after ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; !print: ; !print(n, $t, $f, ...) va.n equ esp+4 ; # va va.i equ edx+ecx*4 ; current va let \ eax=[esp+8],\ ; text buffer ecx=[esp+12],\ ; format edx=&[esp+16] ; &va[...] start push esi edi let edi=eax,\ esi=ecx, ecx=0 ; index=0 test edi, esi ; if either address=0 jz .r0 ; return 0 .get: ; while *text { let al=[esi] ; get character test al, al ; if *text=0, end jz .e let esi++ cmp al, '%' ; if *text=% je .key ; format .1: ; else, copy 1 char let [edi]=al,\ ; to *buffer++ edi++ jmp .get ; } .key: ; % format key let eax=>[esi],\ ; get character esi++ cmp eax, '%' ; %% for one % je .1 cmp eax, '0' ; %0=NULL? jz .0 cmp eax, 'a' ; must be lowercase jl .x cmp eax, 'z' jg .x ; fast a-z jmp table! sub eax, 97 jmp dword [.jt+eax*4] align 8 .jt: dd \ .x,.b,.c,.n,.x,.x,.x,.h,.n,\ ; a-i .x,.x,.x,.x,.n,.x,.x,.x,.r,\ ; j-r .t,.t,.u,.x,.x,.h,.x,.x ; s-z .a: dd 0 .x: ; unrecognized %? let byte \ [edi]='?', edi++ ; replace with ? jmp .get .0: ; 0=NULL let byte \ [edi]=0, edi++ jmp .get .r: let word \ ; return: CR=0Dh, LF=0Ah [edi]=0A0Dh, edi+2 ; low endian jmp .get .c: ; %c let al=[va.i],\ ; get va[i++] ecx++, [edi]=al,\ edi++ jmp .get .t: ; %t %s - text let eax=[va.i],\ ; get va[i++] ecx++ test eax, eax ; if text=0? error jz .r0 pusha text.copy edi, eax ; copy text let [.a]=eax ; save end address popa let edi=[.a] ; advance text buffer jmp .get .n: let eax='n' ; %n %i %d - number jmp .number .u: let eax='u' ; %u jmp .number .h: let eax='h' ; %h %x jmp .number .b: let eax='b' ; %b .number: push [BASE] let [BASE]=eax,\ ; get va[i++] eax=[va.i], ecx++ pusha n2t eax, edi ; copy/convert number to text let [.a]=eax ; save end address popa pop [BASE] let edi=[.a] ; advance text buffer jmp .get .r0: let eax=0 jmp @f .e: let eax=edi,\ ; return end address byte [eax]=0 ; terminate @@: pop edi esi ret ; callv will adjust esp after |
|||
12 Nov 2012, 16:53 |
|
uart777 12 Nov 2012, 16:53
FILE.INC
Code: ; $$$$$$$$$$$$$$ Z77 ASM LIBRARY $$$$$$$$$$$$$$$$$ ; ************** SUNGOD SOFTWARE ***************** ; ?????????????????? FILE.INC ???????????????????? ; open $file ; attempt open, fail if non-existent ; create $file ; create, replace if exists ; exists $file ; does file exist? ; close ; close current file ; tell ; get location ; seek n ; set location ; seek.r n, r ; seek relative. r=0/1/2=b/c/e ; read/write to/from current file ; read &p, n ; read/write memory ; write &p, n ; read.bit ; read/write 1BIT ; write.bit b ; read.nibble ; read/write 4BIT ; write.nibble n ; read.c ; read/write 8BIT byte ; write.c c ; read.n ; read/write 32BIT number ; write.n n ; read.text $t, n ; until 0 or max ; read.line $t, n ; until NL or max ; write.text $t ; not including 0 ; write.string $t ; including 0 ; write.line $t ; insert NL after ; write.x ... ; formatted text ; * load.file $file - open, allocate file.p, ; read then close ; * save.file $file, &p, n - create, write p ; then close ; * append.file $file, &p, n - open, attach p ; to file then close ; * flush - deallocate file.p ; array.load &a, $file ; ARRAY.INC ; array.save &a, $file ; copy.file $a, $b, replace ; move.file $a, $b ; delete.file $file ; rename.file $old, $new ; execute $file ; execute.file $file, $action, $ps, show ; execute.program $file, $ps, show, time ; b='C:\FILE.EXT' ; extract.path $a, $b ; a='C:\' ; extract.file $a, $b ; a='FILE.EXT' ; extract.ext $a, $b ; a='.EXT' ; remove.ext $a ; change.ext $a, $b ; replace or attach new ; get.directory ; update [directory] ; up.directory ; ... ; set.directory $t ; 'C:\MY\ART\' ; set.folder $t ; 'IMAGE\' ; reset.directory ; original ; create.directory $t ; 'C:\MY\VIDEOS\' ; create.folder $t ; 'FONT\' ; note: in Z77 terminology, a "folder" is ; a simple \NAME\ in the current directory ; or relative path ; find.first $ext ; example: '*.bmp' ; find.next ; find.end ; $found.file ; result ; where.is folder ; search for folder ; get.file.attributes file ; get.modified.date file, t ; get.modified.time file, t ; log $t ; append message to log.txt ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; current file structure align 8 VOID file.p ; pointer for load/save NUMBER file.h,\ ; handle file.n64, file.n ; size 64:32 function _file_ let eax=file.p endf ;;;;;;;;;; OPEN, CREATE, CLOSE, EXISTS ;;;;;;;;;;; function close os.close let [file.h]=-1, eax=YES endf function open, file os.open [file] .if eax=-1 return 0 .end os.get.file.size let [file.n]=eax, eax=[file.h] endf function create, file os.create [file] .if eax=-1 return 0 .end let [file.n]=0 endf function exists, file open [file] push eax close pop eax endf macro .if.exists f { !if exists, f } ;;;;;;;;;;;;;;; GET/SET LOCATION ;;;;;;;;;;;;;;;;; function seek.r, n, r os.seek [n], [r] endf macro seek n { seek.r n, 0 } macro tell { seek.r 0, 1 } ;;;;;;;;;;;;; READ/WRITE DATA/TEXT ;;;;;;;;;;;;;;; function read, p, n os.read [p], [n] endf function write, p, n os.write [p], [n] endf function read.c locals c let eax=&[c], dword [eax]=0 read eax, 1 let eax=[c] endf function write.c, c let eax=&[c] write eax, 1 endf function read.n locals n let eax=&[n], dword [eax]=0 read eax, 4 let eax=[n] endf function write.n, n let eax=&[n] write eax, 4 endf ; read.text/line have not been tested... function read.text, t, max push esi edi let edi=[t], esi=[max] @@: read edi, 1 cmp byte [edi], 0 je @f let edi++, esi-- jnz @b @@: let byte [edi]=0 pop edi esi endf function read.line, t, max push esi edi let edi=[t],\ esi=[max] @@: read edi, 1 ; read until 0 or 0Dh or max let cl=[edi] test cl, cl ; 0 jz @f cmp cl, 0Dh ; 0Dh je @f let edi++, esi-- jnz @b ; max? @@: let byte [edi]=0 .if cl=0Dh readc .end let byte [edi]=0 ; replace with 0 pop edi esi endf function write.text, t text.n [t] write [t], eax endf function write.string, t text.n [t] inc eax ; +0 write [t], eax endf function write.line, t write.text [t] write.text NL endf macro write.texts [t] { forward write.text t } macro write.lines [t] { forward write.line t } macro write.text.x f, [p] { common print [?t], f, p ; alters ?t write.text [?t] } ; read/write individual bit from left (7) ; to right (0): 76543210. file # BITs must be ; aligned to byte (&7). example: if 17 BITs, ; write 3 bytes. get/set/zero bit are macros ; defined in MEMORY.INC align 4 NUMBER c.bit, c.byte, next.byte function read.bit dec [c.bit] .if [c.bit]<0 ; read first/next byte get [c.byte]=read.c let [c.bit]=7 .end get.bit [c.byte], [c.bit] ; first/next bit and eax, 1 endf function write.bit, b locals n let eax=7, eax-[c.bit], [n]=eax .if [b] set.bit [c.byte], [n] .else zero.bit [c.byte], [n] .end inc [c.bit] .if [c.bit]>7 write.c [c.byte] let [c.bit]=0 .end endf ; read/write 4BITs. next.byte must = 0 ; on first call function read.nibble xor [next.byte], 1 .if [next.byte] get [c.byte]=read.c let eax>>4, eax&1111b .else let eax=[c.byte], eax&1111b .end endf function write.nibble, b let eax=[c.byte], ecx=[b], ecx&1111b .if [next.byte] let eax|ecx write.c eax .else let ecx<<4, eax|ecx, [c.byte]=eax .end endf ;;;;;;;;;;;;;;;; LOAD/SAVE MEMORY ;;;;;;;;;;;;;;;; function load.file, file open [file] fail .r0 get [file.p]=allocate [file.n] fail .r0 read [file.p], [file.n] fail .r0 close let eax=[file.p], ecx=[file.n] return .r0: close let eax=0 endf function save.file, file, p, n create [file] fail .r0 write [p], [n] fail .r0 close let eax=YES return .r0: close let eax=0 endf function load.text, file open [file] fail .r0 let eax=[file.n], eax+1 get [file.p]=allocate eax fail .r0 read [file.p], [file.n] fail .r0 close let eax=[file.p],\ ecx=[file.n], byte [eax+ecx]=0 return .r0: close let eax=0 endf function save.text, file, text text.n [text] save.file [file], [text], eax endf function append.file, file, p, n !if open, [file] seek.r 0, SEEK_END .else create [file] fail .e .end write [p], [n] fail .e close let eax=[file] return .e: close let eax=0 endf ; load/save dynamic array. size=file.n/a.s function array.load, a, file locals i, n, s, p try open [file] let eax=[file.n], edx=[a],\ ecx=[?array.s+edx], [s]=ecx,\ eax/ecx, [n]=eax array.size [a], [n] array.erase [a] .loop [i]=0 to [n] get [p]=array.index [a], [i] read [p], [s] fail .r0 .endl close return 1 .r0: close let eax=0 endf function array.save, a, file locals i, n, s, p try create [file] let eax=[a], [s]=[?array.s+eax],\ [n]=[?array.n+eax] .loop [i]=0 to [n] get [p]=array.index [a], [i] write [p], [s] fail .r0 .endl close return 1 .r0: close let eax=0 endf macro flush { destroy [file.p] } ;;;;;;;;;;; COPY, MOVE, DELETE, RENAME ;;;;;;;;;;; function copy.file, a, b, r os.copy.file [a], [b], [r] endf function move.file, a, b os.move.file [a], [b] endf function delete.file, file os.delete.file [file] endf function rename.file, file os.rename.file [file] endf ;;;;;;;;;;;;;;;;;;;; EXECUTE ;;;;;;;;;;;;;;;;;;;;; function execute, file os.execute [file] endf function execute.file, file, ps, action, show os.execute.file [file], [ps], [action], [show] endf function execute.program, file, ps, show, time os.execute.program [file], [ps], [action], [time] endf ;;;;;;;;;;;;;;;; PARSE FILENAME ;;;;;;;;;;;;;;;;;; function extract.path, a, b text.copy [a], [b] .if.text.find.last [a], '\' let eax++, byte [eax]=0 .end endf function extract.file, a, b .if.text.find.last [b], '\' let eax++ text.copy [a], eax .end endf function extract.ext, a, b .if.text.find.last [b], '.' text.copy [a], eax .end endf function remove.ext, t .if.text.find.last [t], '.' let byte [eax]=0 .end endf function change.ext, a, b .if.text.find.last [a], '.' text.copy eax, [b] .else text.attach [a], [b] .end endf ;;;;;;;;;;; DIRECTORY: GET/SET/CREATE ;;;;;;;;;;;; function get.directory os.get.directory let eax=[directory] endf function set.directory, t text.copy [directory], [t] os.set.directory [t] endf function up.directory get.directory extract.path [directory], [directory] set.directory [directory] endf function set.folder, name get.directory text.attach.c [directory], '\' text.attach [directory], [name] set.directory [directory] endf function reset.directory os.get.file.name extract.path [directory], [directory] set.directory [directory] endf function create.directory, path os.create.directory [path] endf function create.folder, name get.directory text.attach.c [directory], '\' text.attach [directory], [name] os.create.directory [directory] endf ;;;;;;;;;;;;;;;;;; FIND FILES ;;;;;;;;;;;;;;;;;;;; NUMBER find.data.h found.file equ os.found.file function find.first, file jmp @f os.find.data @@: os.find.first [file] let [find.data.h]=eax, eax++ endf function find.next os.find.next endf function find.end os.find.end endf ; create dynamic text array containing all ; filenames of *.EXT in current directory ; or return 0 if there are none function find.files, a, ext try find.first [ext] @@: array.expand [a] text.copy eax, os.found.file find.next success @b find.end endf ;;;;;;;;;;;;;;;;;;;;; LOCATE ;;;;;;;;;;;;;;;;;;;;; ; set directory containing \FOLDER\ (relative ; path). it may be located in the current ; directory or 1-2 higher directories (for ; \PROJECTS\NAME\). return 0 if not found ; anywhere. example: where.is font.folder function where.is, folder set.folder [folder] ; \FOLDER\ success .! up.directory set.folder [folder] ; \..\FOLDER\ success .! up.directory set.folder [folder] ; \..\..\FOLDER\ endf ; locate folder, search for files of *.EXT ; then reset current directory function find.files.in, folder, files, ext where.is [folder] fail @f find.files [files], [ext] @@: reset.directory endf ;;;;;;;;;;;;;;; FILE ATTRIBUTES ;;;;;;;;;;;;;;;;; os.file.attribute.data function get.file.attributes, file os.get.file.attributes [file] endf function get.file.time, file os.get.file.time [file] endf function get.modified.time, file, t os.get.modified.time [file], [t] endf function get.modified.date, file, t os.get.modified.date [file], [t] endf ;;;;;;;;;;;;;;;;;;; FILE TYPES ;;;;;;;;;;;;;;;;;;; ; most common file types for custom file dialog/ ; explorer. uncommon types will have a generic ; "File" icon macro define.file.types { TEXT \ file.type.text='txt',\ file.type.document='rtf,doc,pub,pdf',\ file.type.source='asm,inc,c,cpp,h,7',\ file.type.program='exe,scr',\ file.type.system='dll,ini,sys',\ file.type.image=\ 'bmp,jpg,jpeg,gif,png,tga,tif,pcx',\ file.type.sound='wav,mp3,mid,wma',\ file.type.movie=\ 'avi,mp4,mpeg,mpg,wmv,flv,mov',\ file.type.site='htm,html' } ;;;;;;;;;;;;;;;;;;;;; LOG ;;;;;;;;;;;;;;;;;;;;;;;; ; log t - append 'text' to log file BOOLEAN create.log?=YES,\ log.star?=YES, log.nl?=YES TEXT log.file(16)='LOG.TXT', log.star='* ' function log, t pusha .if [create.log?]=YES create log.file close let [create.log?]=NO .end .if.text.equal [t], NL ; just NL? 0Dh, 0Ah append.file log.file, NL, 2 .else .if [log.star?]=YES ; * prefix? append.file log.file, log.star, 2 .end text.n [t] ; append message append.file log.file, [t], eax .if [log.nl?]=YES ; NL after? append.file log.file, NL, 2 .end .end popa endf function log.n, n ; log number localt t pusha let ecx=&[t] calla !n2t, [n], ecx let ecx=&[t] log ecx popa endf macro logs [t] { forward log t } macro show.log { execute log.file } function erase.log create log.file close let [create.log?]=NO endf |
|||
12 Nov 2012, 16:53 |
|
uart777 12 Nov 2012, 16:54
DRAW.INC
Code: ; $$$$$$$$$$$$$$$ Z77 ASM LIBRARY $$$$$$$$$$$$$$$$ ; *************** SUNGOD SOFTWARE **************** ; ?????????????????? DRAW.INC ???????????????????? include 'color.inc' include 'clip.inc' include 'box.inc' ; set.screen w, h, c ; set.screen.color c ; set.screen.size w, h ; clear.screen ; xy x, y ; ((screen.w<<2)*y)+(x<<2) ; vga.xy x, y ; &vga[xy(x,y)] ; get.color x, y ; vga[xy(x,y)] ; drawing functions. all draw to current screen ; (vga) and perform "clipping" ; draw.pixel x, y, color ; draw.line orient, x, y, n, color ; draw.line.x x1, y1, x2, y2, color ; draw.box x, y, w, h, color, solid ; draw.box.b box, c, s ; draw.box.s box, c ; draw.box.o box, c ; draw.scanline &pixels, x, y, w, key, alpha ; draw.bitmap &pixels, x, y, w, h, key, alpha ; draw.line.dash orient, x, y, n, c1, c2, w1, w2 ; draw.bound box, c1, c2, w1, w2 ; draw.bound.x box, b ; draw.arrow way, box, c ; draw.arrow.star box, n, c ; draw.arrow.box way, box, i, n, a, b, c ; draw.lever box, n, d, a, b, c ; draw.panel box, lt, l, c, d, dk ; draw.fade o, box, a, b, n ; draw.chrome o, box, a, b, n TYPE POINT = NUMBER x, y TYPE SIZE = NUMBER w, h TYPE LINE = POINT a, b STRUCTURE POLYGON VOID vertices NUMBER n, style COLOR color ENDS ASSUME ?point=POINT, ?size=SIZE,\ ?line=LINE, ?polygon=POLYGON ; graphic styles powers G_STATIC, G_DYNAMIC,\ G_VERTICAL, G_INVERT, G_COLOR, G_LINE,\ G_TEXT, G_FADE, G_CHROME, G_GRADIENT,\ G_IMAGE, G_BRUSH, G_TEXTURE, G_KEY, G_ALPHA G_DEFAULT = G_DYNAMIC+G_COLOR+G_LINE G_DEFAULT_TEXT = G_DEFAULT+G_TEXT G_TEXT_ONLY = G_DYNAMIC+G_TEXT G_ALPHA_FADE = G_DYNAMIC+G_COLOR+G_ALPHA+G_FADE ;;;;;;;;;;;;;;;;;;; RESOLUTION ;;;;;;;;;;;;;;;;;;; STRUCTURE RESOLUTION TEXT name(16) NUMBER w, h, bpp ENDS macro resolution [p] { common resolutions: forward match name==w*h, p \{ TEXT name\#.name(16)=\`name NUMBER name\#.w=w,\ name\#.h=h, name\#.bpp=32 \} } macro define.resolutions { resolution \ QQVGA = 160*120,\ HQVGA = 240*160,\ QVGA = 320*240,\ WQVGA = 480*272,\ VGA = 640*480,\ NTSC = 720*480,\ WVGA = 800*480,\ SVGA = 800*600,\ WSVGA = 1024*600,\ XGA = 1024*768,\ SXGA = 1280*1024,\ HD720 = 1280*720,\ WXGA = 1280*800,\ WSXGA = 1440*900,\ HD1080 = 1920*1080 } ;;;;;;;;;;;;;;;;;;;; SCREEN ;;;;;;;;;;;;;;;;;;;;;; ; "Video Graphics Array" and screen structure. ; everything is drawn to this then copied to ; primary display align 8 VOID vga NUMBER screen.x, screen.y,\ screen.w=DETECT, screen.h=DETECT,\ screen.bpp=32, screen.key, screen.alpha COLOR screen.color=BLACK BOOLEAN clear.screen?=YES NUMBER screen.delay ; in MS ; current graphics color, box, etc COLOR g.color, g.line.color BOX g.box NUMBER g.style, g.orient, g.solid ; set screen size and color variables. ; return &&[vga] address in eax and ; graphics box & in edx function set.screen, w, h, c cmp [w], 0 je @f let [screen.w]=[w], [screen.h]=[h],\ [screen.color]=[c] @@: eax=vga, edx=g.box endf macro set.screen.color c { let [screen.color]=c } macro set.screen.size w, h { let [screen.w]=w, [screen.h]=h } ; calculate &vga[((screen.w<<2)*y)+(x<<2)] ; convert x/y to linear index. warning: ; eax/ecx/edx cannot be sent as parameters ; to macros xy/vga.xy, but registers can ; always be sent to functions macro xy x, y { let ecx=[screen.w], ecx<<2, ecx*y,\ edx=x, eax=&[ecx+edx*4] } macro vga.xy x, y { ; &vga[xy(x,y)] xy x, y add eax, [vga] } function vga_xy, x, y ; callable version vga.xy [x], [y] endf ; get color/[value] at x/y function get.color, x, y vga.xy [x], [y] let eax=[eax] endf ; set current graphics color macro set.color c { let [g.color]=c } macro set.line.color c { let [g.line.color]=c } ; get/set graphics box. w/h are optional macro locate x, y, w, h { let [g.box.x]=x, [g.box.y]=y if w eq let [g.box.w]=w, [g.box.h]=h end if } macro get.g.box b { copy.box b, g.box } macro set.g.box b { copy.box g.box, b } ; set orientation macro set.orient o { let g.orient=o } ;;;;;;;;;;;;;;;;;;; DRAWING ;;;;;;;;;;;;;;;;;;;;;; ; clear screen. copy w*h # dwords function clear.screen push edi let edi=[vga], eax=[screen.color],\ ecx=[screen.w], ecx*[screen.h] rep stosd pop edi endf ; draw pixel at x/y with c/olor. this is only ; provided for testing algorithms. none of the ; drawing functions use it, they copy directly ; to [vga]. when drawing lines, shapes, images, ; etc, it's best to get the x/y offset once ; before loops then just increment/add/etc ; inside and not re-evaluate the expression ; each iteration function draw.pixel, x, y, c try clip.pixel \ ; visible? [x], [y] vga.xy [x], [y] ; &vga[((screen.w<<2)*y)+(x<<2)] let ecx=[c],\ dword [eax]=ecx ; copy pixel: *vga=c endf ; draw straight line fast. o/rient='h'/'v'. ; n=w/h. return if 100% invisible function draw.line, o, x, y, n, c push edi let eax=&[x], edx=&[y], ecx=&[n] clip.line [o], eax, edx, ecx fail .e vga.xy [x], [y] ; &vga[((screen.w<<2)*y)+(x<<2)] let edi=eax,\ eax=[c], ecx=[n] cmp [o], 'v' je .vertical .horizontal: rep stosd ; memory.set jmp .e .vertical: .loop ecx=0 to [n] ; loop y to h let [edi]=eax,\ ; draw pixel edx=[screen.w],\ edi=&[edi+edx*4] ; advance vga+(screen.w*4) .endl .e: pop edi endf macro draw.line.h x, y, n, c { draw.line 'h', x, y, n, c } macro draw.line.v x, y, n, c { draw.line 'v', x, y, n, c } ; draw H/V line using current graphics box function draw.line.z .if [g.way]='v' let eax=[g.box.h] .else let eax=[g.box.w] .end draw.line [g.orient],\ [g.box.x], [g.box.y], eax, [g.color] endf ; draw arbitrary line from x1/y1 to x2/y2. ; not fully optimized yet function draw.line.a, x1, y1, x2, y2, c locals i, x, y, px, py, dx, dy let eax=[x2], eax-[x1], [dx]=eax,\ ecx=[y2], ecx-[y1], [dy]=ecx,\ eax>>1, [x]=eax, ecx>>1, [y]=ecx,\ [px]=[x1], [py]=[y1] vga.xy [px], [py] let [eax]=[c], ecx=[dy] .if [dx]>ecx .loop [i]=0 to [dx] let eax=[y], eax+[dy], [y]=eax .if eax>=[dx] let eax=[dx], [y]-eax, [py]++ .end let [px]++ draw.pixel [px], [py], [c] .endl .else .loop [i]=0 to [dy] let eax=[x], eax+[dx], [x]=eax .if eax>=[dy] let eax=[dy], [x]-eax, [px]++ .end let [py]++ draw.pixel [px], [py], [c] .endl .end endf ; draw box/square/rectangle. s/olid? 1=yes, ; 0=outline. return if 100% invisible function draw.box, x, y, w, h, c, s locals i, b try visible [x], [y], [w], [h] .if [s]=YES ; solid? let ecx=[y], ecx+[h], [b]=ecx .loop [i]=[y] to [b] draw.line 'h', [x], [i], [w], [c] .endl .else ; outline draw.line 'h', [x], [y], [w], [c] ; top let eax=[y], eax+[h], eax-1 draw.line 'h', [x], eax, [w], [c] ; bottom let eax=[y], eax+1, ecx=[h], ecx-2 draw.line 'v', [x], eax, ecx, [c] ; left let eax=[x], eax+[w], eax-1,\ edx=[y], edx+1, ecx=[h], ecx-2 draw.line 'v', eax, edx, ecx, [c] ; right .end endf ; draw via BOX (x/y/w/h) structure with ; c/olor. s/olid? 1=yes or 0=outline function draw.box.b, box, c, s let eax=[box] draw.box [?box.x+eax], [?box.y+eax],\ [?box.w+eax], [?box.h+eax], [c], [s] endf ; draw solid or outline macro draw.box.s box, c { draw.box.b box, c, 1 } macro draw.box.o box, c { draw.box.b box, c, 0 } ; draw with fill color and outline function draw.box.bo, box, c1, c2 draw.box.s [box], [c1] draw.box.o [box], [c2] endf ; draw with current graphics box function draw.box.z draw.box [g.box.x], [g.box.y],\ [g.box.w], [g.box.h], [g.color], [g.solid] endf ; draw arrow. o/rient='l/u/r/d/ul/ur/dr/dl'. ; for measures, switches, scroll bars. ; w/h must be same size. unfinished... function draw.arrow, o, box, c locals i, x, y, w, h, first, last get.s eax, ?box, box, x, y, w, h .if [o]='l' let eax=[x], [first]=eax, eax+[w], [last]=eax,\ ecx=[h], ecx>>1, ecx+[y], [y]=ecx, [h]=1 .else.if [o]='u' let eax=[y], [first]=eax, eax+[h], [last]=eax,\ ecx=[w], ecx>>1, ecx+[x], [x]=ecx, [w]=1 .else.if [o]='r' let eax=[x], [first]=eax, eax+[w], [last]=eax .else.if [o]='d' let eax=[y], [first]=eax, eax+[h], [last]=eax .else.if [o]='ul' let ecx=[y], [first]=ecx, ecx+[h], [last]=ecx .else.if [o]='ur' let ecx=[y], [first]=ecx, ecx+[h], [last]=ecx .else.if [o]='dr' let ecx=[x], ecx+[w], [x]=ecx, ecx=[y],\ [first]=ecx, ecx+[h], [last]=ecx, [w]=1 .else.if [o]='dl' let ecx=[y], [first]=ecx, ecx+[h],\ [last]=ecx, [w]=1 .end .loop [i]=[first] to [last] .if [o]='l' draw.line 'v', [i], [y], [h], [c] .else.if [o]='u' draw.line 'h', [x], [i], [w], [c] .else.if [o]='r' draw.line 'v', [i], [y], [h], [c] .else.if [o]='d' draw.line 'h', [x], [i], [w], [c] .else.if [o]='ul' draw.line 'h', [x], [i], [w], [c] .else.if [o]='ur' draw.line 'h', [x], [i], [w], [c] .else.if [o]='dr' draw.line 'h', [x], [i], [w], [c] .else.if [o]='dl' draw.line 'h', [x], [i], [w], [c] .end .if [i]&1 .if [o]='l' let [y]--, [h]+2 .else.if [o]='u' let [x]--, [w]+2 .else.if [o]='r' let [x]++, [y]++, [h]-2 .else.if [o]='d' let [x]++, [w]-2 .end .end .if [o]='ul' let [w]-- .else.if [o]='ur' let [x]++, [w]-- .else.if [o]='dr' let [x]--, [w]++ .else.if [o]='dl' let [w]++ .end .endl endf ; draw arrows in 8 directions. ; not customizable yet function draw.arrow.star, box, n, c draw.arrow 'ul', [box], [c] move.box.r [box] draw.arrow 'u', [box], [c] move.box.r [box] draw.arrow 'ur', [box], [c] move.box.d [box] move.box.l [box] move.box.l [box] draw.arrow 'l', [box], [c] move.box.r [box] ; <center> move.box.r [box] draw.arrow 'r', [box], [c] move.box.d [box] move.box.l [box] move.box.l [box] draw.arrow 'dl', [box], [c] move.box.r [box] draw.arrow 'd', [box], [c] move.box.r [box] draw.arrow 'dr', [box], [c] endf ; draw [<] or [>] or both. unfinished... function draw.arrow.box, way, box, i, n, a, b, c calla !draw.chrome, 'v', [box], [a], [b], [n] create.box.inside g.box, [box], [i], [i] draw.arrow [way], g.box, [c] endf function draw.lever, box, n, d, a, b, c draw.arrow.box 'l', [box], [n], [d], [a], [b], [c] move.box.r [box] move.box.right [box], 1 draw.arrow.box 'r', [box], [n], [d], [a], [b], [c] endf ; draw line with dashes in 2 colors, w1 pixels ; of c1 then w2 pixels of c2 function draw.line.dash, o, x, y, n, c1, c2, w1, w2 locals i, w, dash, count push esi edi let eax=&[x], edx=&[y], ecx=&[n] clip.line [o], eax, edx, ecx fail .e vga.xy [x], [y] let edi=eax,\ eax=[c1], [dash]=YES .if [o] not 'v' let [w]=1 .else let [w]=[screen.w] .end let [count]=0 .loop [i]=0 to [n] ; loop x/y to w/h let [count]++ .if [dash]=YES let eax=[c1],\ ecx=[w1] .if [count]=ecx let [dash]=NO,\ [count]=0 .end .else let eax=[c2],\ ecx=[w2] .if [count]=ecx let [dash]=YES,\ [count]=0 .end .end let [edi]=eax,\ ; draw pixel ecx=[w],\ edi=&[edi+ecx*4] ; advance vga+(w*4) .endl .e: pop edi esi endf ; draw bound/band; a box with lines that ; have dashes. for selections and boundaries ; on any color background. example: ; draw.bound box, WHITE, BLACK, 4, 4 function draw.bound, box, c1, c2, w1, w2 locals x, y, w, h let eax=[box],\ [x]=[?box.x+eax], [y]=[?box.y+eax],\ [w]=[?box.w+eax], [h]=[?box.h+eax] try visible [x], [y], [w], [h] draw.line.dash 'h',\ [x], [y], [w], [c1], [c2], [w1], [w2] let eax=[y], eax+[h], eax-1 draw.line.dash 'h',\ [x], eax, [w], [c1], [c2], [w1], [w2] let eax=[y], eax+1, ecx=[h], ecx-2 draw.line.dash 'v',\ [x], eax, ecx, [c1], [c2], [w1], [w2] let eax=[x], eax+[w], eax-1,\ edx=[y], edx+1, ecx=[h], ecx-2 draw.line.dash 'v',\ eax, edx, ecx, [c1], [c2], [w1], [w2] endf ; draw resizeable bounding box with 8 ; small 8x8 squares on each corner and side function draw.bound.x, box locals wd2, hd2, b draw.bound [box], WHITE, BLACK, 4, 4 let eax=[box],\ ecx=[?box.w+eax], ecx>>1, [wd2]=ecx,\ edx=[?box.h+eax], edx>>1, [hd2]=edx copy.box g.box, [box] nudge.box g.box, -4, -4 size.box g.box, 8, 8 let [b]=g.box draw.box.bo [b], WHITE, BLACK move.box.right [b], [wd2] draw.box.bo [b], WHITE, BLACK move.box.right [b], [wd2] draw.box.bo [b], WHITE, BLACK move.box.down [b], [hd2] draw.box.bo [b], WHITE, BLACK move.box.down [b], [hd2] draw.box.bo [b], WHITE, BLACK move.box.left [b], [wd2] draw.box.bo [b], WHITE, BLACK move.box.left [b], [wd2] draw.box.bo [b], WHITE, BLACK move.box.up [b], [hd2] draw.box.bo [b], WHITE, BLACK move.box.up [b], [hd2] endf ; draw box with frame/window edge ; lt - lightest ; l - light ; c - medium. main color ; d - dark ; dk - darkest function draw.panel, box, lt, l, c, d, dk locals x, y, w, h, r, b let eax=[box],\ [x]=[?box.x+eax], [y]=[?box.y+eax],\ [w]=[?box.w+eax], [h]=[?box.h+eax] try visible [x], [y], [w], [h] let eax=[w], edx=[h],\ ecx=[x], ecx+eax, [r]=ecx,\ ecx=[y], ecx+edx, [b]=ecx draw.box [x], [y], [w], [h], [c], 1 ; draw main outline let eax=[w], eax-1 draw.line 'h', [x], [y], eax, [l] let eax=[h], eax-1 draw.line 'v', [x], [y], eax, [l] let eax=[b], eax-1 draw.line 'h', [x], eax, [w], [l] let eax=[r], eax-1 draw.line 'v', eax, [y], [h], [l] ; draw inner outline let eax=[x], eax+1, ecx=[y], ecx+1,\ edx=[w], edx-3 draw.line 'h', eax, ecx, edx, [lt] let eax=[x], eax+1, ecx=[y], ecx+1,\ edx=[h], edx-3 draw.line 'v', eax, ecx, edx, [lt] let eax=[x], eax+1, ecx=[b], ecx-2,\ edx=[w], edx-3 draw.line 'h', eax, ecx, edx, [dk] let eax=[r], eax-2, ecx=[y], ecx+1,\ edx=[h], edx-2 draw.line 'v', eax, ecx, edx, [dk] ; draw 2 inner shadow lines let eax=[x], eax+2, ecx=[b], ecx-3,\ edx=[w], edx-5 draw.line 'h', eax, ecx, edx, [l] let eax=[r], eax-3, ecx=[y], ecx+2,\ edx=[h], edx-4 draw.line 'v', eax, ecx, edx, [l] endf function draw.panel.c, box, c locals lt, l, d, dk get [lt]=lightness [c], 128 get [l]=lightness [c], 64 get [d]=lightness [c], -64 get [dk]=lightness [c], -128 draw.panel [box],\ [lt], [l], [c], [d], [dk] endf ; draw standard gray panel macro draw.panel.g box { draw.panel box,\ WHITE, 808080h, 0E7E7E7h, 808080h, 404040h } ; draw fade from color a to b by n/delta. ; o/rient: 'h'=horizontal, 'v'=vertical function draw.fade, o, box, a, b, n locals i, x, y, w, h, c, first, last let eax=[box],\ [x]=[?box.x+eax], [y]=[?box.y+eax],\ [w]=[?box.w+eax], [h]=[?box.h+eax] .if [o]='v' let eax=[y], [first]=eax,\ eax+[h], [last]=eax .else let eax=[x], [first]=eax,\ eax+[w], [last]=eax .end let [c]=[a] .loop [i]=[first] to [last] .if [o]='v' ; vertical fade, horizontal lines draw.line 'h', [x], [i], [w], [c] .else ; horizontal fade, vertical lines draw.line 'v', [i], [y], [h], [c] .end get [c]=mix [b], [c], [n] .endl endf function draw.chrome, o, box, a, b, n locals l copy.box g.box, [box] let [g.box.h]>>1 draw.fade 'v', g.box, [a], [b], [n] move.box.down g.box, [g.box.h] get [l]=lightness [b], 32 draw.fade 'v', g.box, [a], [l], [n] draw.box.o [box], [l] endf macro draw.black.chrome box { draw.chrome 'v', box, BLACK, GRAY25, 16 } macro draw.blue.chrome box { draw.chrome 'v', box, ROYAL.BLUE, BEACH.BLUE, 16 } macro draw.red.chrome box { draw.chrome 'v', box, 0FF02010h, FIRE.RED, 16 } macro draw.violet.chrome box { draw.chrome 'v', box, DARK.VIOLET, LILAC, 16 } macro draw.alien.chrome box { draw.chrome 'v', box, 3D5310h, 0E4F737h, 16 } ; draw "scanline"; a multi-color horizontal line ; with optional transparent color key to exclude ; (or 0/none) and alpha (=0/opaque or 1-255). ; pixels parameter is the address of 32BPP pixel ; array. remaining parameters are integer by value. ; "alpha" applies to the entire image. for ; scanlines with alpha encoded in each pixel, ; see draw.scanline.a function draw.scanline,\ pixels, x, y, w, key, alpha locals i push esi edi let eax=&[i], esi=&[x], edi=&[y], ecx=&[w] clip.scanline eax, esi, edi, ecx fail .r vga.xy [esi], [edi] let edi=eax, esi=[pixels], esi+[i], ecx=[w] cmp [key], 0 ; if no key or alpha... jnz .t cmp [alpha], 0 jnz .t rep movsd ; use fast instruction jmp .r .t: ; else, loop copy .loop [i]=0 to [w] ; w # times let eax=[esi] ; get pixel cmp eax, [key] ; transparent? je .next ; skip .if [alpha] ; alpha? .if [alpha]=127 ; 50%? optimize let \ edx=[edi],\ edx&0FEFEFEh,\ edx>>1,\ eax=[esi],\ eax&0FEFEFEh,\ eax>>1, eax+edx .else mix eax, [edi],\ ; see COLOR>mix [alpha] .end .end let [edi]=eax ; *vga++=*p++ .next: let esi+4, edi+4 .endl .r: pop edi esi endf ; draw "bitmap"; 2D pixel array. for key/alpha ; parameters, see draw.scanline. if image is ; completely invisible, this will return. ; if partially visible, draw.scanline will ; "clip"/exclude invisible sections (CLIP.INC) function draw.bitmap, pixels,\ x, y, w, h, key, alpha locals p, i, iw, b try visible [x], [y], [w], [h] ; visible? let eax=[pixels], [p]=eax,\ ; p=pixels ecx=[w], ecx<<2, [iw]=ecx,\ ; image w in bytes ecx=[y], ecx+[h], [b]=ecx ; bottom=y+h .loop [i]=[y] to [b] ; draw h # scanlines draw.scanline [p],\ ; from y to b [x], [i], [w],\ [key], [alpha] let eax=[iw], [p]+eax ; increment p by iw .endl endf ; draw 32BPP scanline with alpha (AA.RR.GG.BBh). ; * 0 - 100% visible/opaque ; * 1-254 - transparent ; * 255 - 100% invisible (a&0FF000000h=0) function draw.scanline.a, pixels, x, y, w locals i push esi edi let eax=&[i], esi=&[x], edi=&[y], ecx=&[w] clip.scanline eax, esi, edi, ecx fail .e vga.xy [esi], [edi] let edi=eax, esi=[pixels], esi+[i] .loop [x]=0 to [w] ; draw pixels let eax=[esi] ; get pixel .if eax&0FF000000h ; alpha? let ecx=eax shr ecx, 24 .if ecx=0FFh ; invisible jmp .next .end mix [edi], eax, ecx ; result in eax .end let [edi]=eax ; *vga++=*p++ .next: let esi+4, edi+4 .endl .e: pop edi esi endf ; draw 32BPP bitmap with alpha (AA.RR.GG.BBh) function draw.bitmap.a, pixels, x, y, w, h locals p, i, iw, b try visible \ ; visible? [x], [y], [w], [h] let [p]=[pixels],\ ; p=pixels ecx=[w], ecx<<2, [iw]=ecx,\ ; image w in bytes ecx=[y], ecx+[h], [b]=ecx ; bottom=y+h .loop [i]=[y] to [b] ; draw h # scanlines draw.scanline.a [p],\ [x], [i], [w] let eax=[iw], [p]+eax ; increment p by iw .endl endf ; draw a "variant scanline" that combines alpha ; intensity with a color ; p: pixel array, shades of black/gray/white. ; c=color. useful for drawing custom bitmap fonts ; with antialiased edges (FONT>draw.c) and ; artistic brushes function draw.scanline.v, pixels, x, y, w, c locals i push esi edi let eax=&[i], esi=&[x], edi=&[y], ecx=&[w] clip.scanline eax, esi, edi, ecx fail .e vga.xy [esi], [edi] let edi=eax,\ esi=[pixels],\ esi+[i] .loop [i]=0 to [w] ; process pixels let eax=[c],\ ecx=[esi],\ ; current pixel ecx&0FFh ; alpha (R=G=B in grayscale) cmp ecx, 0 ; 100% invisible? (black) je .skip cmp ecx, 0FFh ; 100% visible? (white) je .copy mix \ ; partially visible? (gray) eax, [edi], ecx .copy: stosd add esi, 4 jmp .el .skip: let esi+4, edi+4 .el: .endl .e: pop edi esi endf ; draw bitmap using variant scanline function draw.bitmap.v, pixels, x, y, w, h, c locals p, i, iw, b try visible \ ; visible? [x], [y], [w], [h] let eax=[pixels], [p]=eax,\ ; p=pixels ecx=[w], ecx<<2, [iw]=ecx,\ ; image w in bytes ecx=[y], ecx+[h], [b]=ecx ; bottom=y+h .loop [i]=[y] to [b] ; draw h # scanlines draw.scanline.v [p],\ [x], [i], [w], [c] let eax=[iw], [p]+eax ; increment p by iw .endl endf ; OS-specific code to copy VGA/buffer ; to primary display... include 'vga.inc' |
|||
12 Nov 2012, 16:54 |
|
uart777 12 Nov 2012, 16:55
IMAGE.INC
Code: ; $$$$$$$$$$$$$$$ Z77 ASM LIBRARY $$$$$$$$$$$$$$$$ ; *************** SUNGOD SOFTWARE **************** ; ?????????????????? IMAGE.INC ??????????????????? include 'bmp.inc' include 'tga.inc' ; create.image image, w, h ; destroy.image image ; set.image.pixels image, p ; get.image.pixels image, p ; load.image image, file ; save.image image, file ; draw.image image ; draw.image.at image, x, y ; size.image image, w, h ; size.image.p image, p ; move.image image, x, y ; center.image image ; align.image image, b, a ; collide.image image.a, image.b ; set.image.key image ; set.image.alpha image, a ; convert.image.alpha image, source ; image.light image, n ; image.grayscale image ; image.color image, c, n ; image.invert image ; image.channel image, c macro IMAGE.X { VOID p NUMBER x, y, w, h, bpp=32 COLOR key, alpha } STRUCTURE IMAGE IMAGE.X ENDS ?image ?image.box equ ?image.x TEXT image.folder='IMAGE\',\ image.ext='.BMP', image.wild='*.BMP' VOID load.bitmap=!load.bmp,\ save.bitmap=!save.bmp ; note: image.p/ixels are stored logically, ; ARGB32; images are NOT upside down, colors ; are NOT backwards and there are NO pointless ; "junk bytes" after each row. images can be ; processed much faster with linear pixels ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; function create.image, image, w, h locals p, n let eax=[image], [p]=[?image.p+eax],\ ecx=[w], ecx<<2, ecx*[h], [n]=ecx allocate.x [p], [n] fail .error let eax=[image], [?image.p+eax]=[p],\ [?image.w+eax]=[w], [?image.h+eax]=[h],\ [?image.bpp+eax]=32 jmp @f ; return image address .error: let eax=0 @@: endf function destroy.image, image let eax=[image], eax=[?image.p+eax] .if true destroy eax memory.zero [image], IMAGE.$ .end endf function set.image.pixels, image, p let eax=[image],\ ecx=[?image.w+eax], edx=[?image.h+eax],\ ecx*edx, ecx<<2 memory.copy [?image.p+eax], [p], ecx endf function get.image.pixels, image, p let eax=[image],\ ecx=[?image.w+eax], edx=[?image.h+eax],\ ecx*edx, ecx<<2 memory.copy [p], [?image.p+eax], ecx endf function copy.image, a, b destroy.image [a] let eax=[b] create.image [a],\ [?image.w+eax], [?image.h+eax] let eax=[b], eax=[?image.p+eax] set.image.pixels [a], eax endf function load.image, image, file locals p try calla [load.bitmap], [file] let [p]=eax,\ eax=[image], [?image.p+eax]=[p],\ [?image.w+eax]=ecx, [?image.h+eax]=edx endf macro set.image.key image { let eax=image, ecx=[?image.p+eax],\ [?image.key+eax]=[ecx] } macro load.image.t image, file { load.image image, file set.image.key image } macro load.images [p] { forward make.txt eax, 'IMAGE\'#`p#'.BMP' load.image p#.i, eax set.image.key p#.i } function save.image, image, file, bpp let eax=[image] calla [save.bitmap], [file], [?image.p+eax],\ [?image.w+eax], [?image.h+eax], [bpp] endf macro set.image.alpha image, a { let eax=image, [?image.alpha+eax]=a } ; draw pixel array. see DRAW.INC function draw.image, image let eax=[image] draw.bitmap [?image.p+eax],\ [?image.x+eax], [?image.y+eax],\ [?image.w+eax], [?image.h+eax],\ [?image.key+eax], [?image.alpha+eax] endf macro draw.image.at image, x, y { move.image image, x, y draw.image image } function draw.image.box, image let eax=[image], edx=&[?image.box+eax] draw.bitmap [?image.p+eax],\ [?box.x+edx], [?box.y+edx],\ [?image.w+eax], [?image.h+eax],\ [?image.key+eax], [?image.alpha+eax] endf function draw.image.a, image, box, a let eax=[image], eax+?image.box align.box eax, [box], [a] endf macro draw.images [images] { forward calla !draw.image, images } ; draw image with 32BBP alpha. image.alpha ; applies to the entire image whereas this ; allows each pixel to have variable alpha. ; if image has no alpha or key, standard ; "draw.image" is faster (rep movsd) function draw.image.alpha, image let eax=[image] draw.bitmap.a [?image.p+eax],\ [?image.x+eax], [?image.y+eax],\ [?image.w+eax], [?image.h+eax] endf function move.image, image, x, y let eax=[image], [?image.x+eax]=[x],\ [?image.y+eax]=[y] endf function center.image, image let eax=[image], eax+?image.box center.b eax endf ; convert 32BPP image to alpha based on a ; grayscale source image (c&BLUE=alpha since ; R=G=B in B/W). to reverse B/W, use ; "image.invert" before and/or after ; destiny|=((source&BLUE)<<24) function convert.image.alpha, image, source push esi edi let esi=[source], esi=[?image.p+esi],\ edi=[image], eax=edi, edi=[?image.p+edi],\ ecx=[?image.w+eax], edx=[?image.h+eax], ecx*edx .convert: let eax=[esi], eax&0FFh, eax<<24,\ [edi]|eax, edi+4, esi+4, ecx-- jnz .convert pop edi esi endf ; does color exist in palette? return index ; or -1. colors are AA.RR.GG.BB function color.exists, palette, c, bpp locals i, n let eax=1, ecx=[bpp],\ eax<<cl, [n]=eax .loop [i]=0 to [n] let eax=[palette], ecx=[i],\ edx=[eax+ecx*4] .if [c]=edx return [i] .end .endl let eax=-1 endf macro .if.unique.color p, c, b { color.exists p, c, b .if eax=-1 } ; draw image from 2D graph of images - for ; sprites, projectiles, explosions, etc. ; cell is drawn at image.x/y. parameters ; x/y = cell offset inside image. ; w/h = cell size function draw.image.cell, image, x, y, w, h locals i, p, ix, iy, iw, ih, wb, b, key let eax=[image],\ [ix]=[?image.x+eax], [iy]=[?image.y+eax],\ [iw]=[?image.w+eax], [ih]=[?image.h+eax],\ [p]=[?image.p+eax], [key]=[?image.key+eax] ; image w in bytes let eax=[iw], eax<<2, [wb]=eax ; p=&image[(iw*h*y*4)+(x*w*4)] let eax=[iw], eax*[h], eax*[y], eax<<2,\ ecx=[x], ecx*[w], ecx<<2, eax+ecx,\ eax+[p], [p]=eax, ecx=[iy], ecx+[h], [b]=ecx .loop [i]=[iy] to [b] draw.scanline [p], [ix], [i], [w], [key], 0 let ecx=[p], ecx+[wb], [p]=ecx .endl endf ; create "scratchpad"; temporary image ; for size, mirror, rotate, effects. ; return [image.p] pixels address align 8 IMAGE scratch.i function scratch, w, h try create.image scratch.i, [w], [h] let eax=[scratch.i.p] endf ; when finished with scratchpad, use this to ; copy its pixels to image then deallocate it macro end.scratch image { copy.image image, scratch.i destroy.image scratch.i } ; size pixel array using "nearest neighbor" ; (accurate, interpolation is not). remember ; to backup original image: ; copy.image backup.i, original.i function size.image, image, w, h locals i, j, p, s, x1, y1, w1, h1, x2, y2 let eax=[image], [s]=[?image.p+eax],\ [w1]=[?image.w+eax], [h1]=[?image.h+eax] try [p]=scratch [w], [h] ; ratio=(size<<16)/size let eax=[w1], eax<<16, eax/[w], [x1]=eax,\ eax=[h1], eax<<16, eax/[h], [y1]=eax .loop [i]=0 to [h] .loop [j]=0 to [w] ; offset=(n*ratio)>>16 let eax=[j], eax*[x1], eax>>16, [x2]=eax,\ eax=[i], eax*[y1], eax>>16, [y2]=eax ; destiny[(i*w2)+j]=source[(y2*w1)+x2] let eax=[i], eax*[w], eax+[j], eax<<2,\ eax+[p], ecx=[y2], ecx*[w1], ecx+[x2],\ ecx<<2, ecx+[s], [eax]=[ecx] ; *p=*s .endl .endl end.scratch [image] endf ; size by percentage (integer) function size.image.p, image, p locals w, h, iw, ih let eax=[image],\ [iw]=[?image.w+eax], [ih]=[?image.h+eax],\ eax=[iw], eax*[p], ecx=100, eax/ecx, [w]=eax,\ eax=[ih], eax*[p], ecx=100, eax/ecx, [h]=eax size.image [image], [w], [h] endf ; mirror; flip 'h'orizontal, 'v'ertical ; or 'd'iagonal function mirror.image.h, image locals x, y, w, h, p, s let eax=[image], [s]=[?image.p+eax],\ [w]=[?image.w+eax], [h]=[?image.h+eax] try [p]=scratch [w], [h] .loop [y]=0 to [h] .loop [x]=0 to [w] ; p[x+(y*w)]=s[(w-x-1)+(y*w)] let edx=[w], edx-[x], edx-1, ecx=[y],\ ecx*[w], edx+ecx, edx<<2, edx+[s],\ eax=[x], eax+ecx, eax<<2, eax+[p],\ [eax]=[edx] .endl .endl end.scratch [image] endf function mirror.image.v, image locals x, y, w, h, p, s let eax=[image], [s]=[?image.p+eax],\ [w]=[?image.w+eax], [h]=[?image.h+eax] try [p]=scratch [w], [h] .loop [y]=0 to [h] ; memory.copy &p[y*w], &s[(h-y-1)*w], w*4 let edx=[h], edx-[y], edx-1, edx*[w],\ edx<<2, edx+[s], eax=[y], eax*[w],\ eax<<2, eax+[p], ecx=[w], ecx<<2 memory.copy eax, edx, ecx .endl end.scratch [image] endf function mirror.image, image, way .if [way]='h' mirror.image.h [image] .else.if [way]='v' mirror.image.v [image] .else.if [way]='d' mirror.image.h [image] mirror.image.v [image] .end endf function align.i, image, a let eax=[image], eax+?image.box align.b eax, [a] endf function align.image, image, box, a let eax=[image], eax+?image.box align.box eax, [box], [a] endf function draw.image.align, image, box, a align.image [image], [box], [a] draw.image [image] endf function collide.image, a, b let eax=[a], eax+?image.box,\ edx=[b], edx+?image.box collide.box eax, edx endf macro .if.select.image i { .if.select i#.x } ;;;;;;;;;;;;;;;; IMAGE OPERATIONS ;;;;;;;;;;;;;;; ; an "operation" is a function that contains a ; loop that processes the current pixel of an ; image. scroll down to see how useful this is macro operation name, [ps] { common function name, ps locals i, iw, p let eax=[image], ecx=[?image.p+eax],\ [p]=ecx, ecx=[?image.w+eax] imul ecx, [?image.h+eax] let [iw]=ecx .loop [i]=0 to [iw] ; scroll image pixels let eax=[image],\ eax=[?image.key+eax] test eax, eax ; if transparent jz @f let ecx=[p] ; current pixel cmp [ecx], eax ; =key? end loop je .el @@: let eax=[p] } macro endo { let ecx=[p], [ecx]=eax .el: add [p], 4 .endl endf } ; with previous macros, one can easily ; create/edit multiple image effects. ; see COLOR>operations operation image.light, image, n lightness [eax], [n] endo operation image.grayscale, image grayscale [eax] endo operation image.color, image, c, n colorize [eax], [c], [n] endo operation image.invert, image inversion [eax] endo operation image.channel, image, c channelize [eax], [c] endo purge operation, endo ;;;;;;;;;;;;;;;;;;; SCREENSHOT ;;;;;;;;;;;;;;;;;;; ; save vga/screen as image file. this is slow ; due to repetitive read/write API calls for ; each pixel. just one 1024x768x32 screen is ; 786,432*4 = 3,145,728 bytes! function screenshot, file calla [save.bitmap], [file], [vga],\ [screen.w], [screen.h], 24 endf |
|||
12 Nov 2012, 16:55 |
|
uart777 12 Nov 2012, 16:55
FONT.INC
Code: ; $$$$$$$$$$$$$$ Z77 ASM LIBRARY $$$$$$$$$$$$$$$$$ ; ************** SUNGOD SOFTWARE ***************** ; ?????????????????? FONT.INC ???????????????????? ; get.font f ; get current font ; set.font f ; set font style ; set.font.color c ; set font color ; set.font.c f, c ; set style and color ; load.font/s... ; load image/s to font/s ; load.all.fonts ; from /FONT/ to fonts array ; destroy.font f ; backup.font ; restore.font ; draw.c c, x, y ; draw 'c'haracter ; draw.c.a c, x, y ; aligned in box ; draw.text t, x, y ; draw 'text' ; draw.text.a t, b, a ; aligned in box ; text.w/h get the exact size of single or ; multi-line text in the current font. example: ; if font.w=20, text.w('ABC') will return 60. ; text.width/height get the size of text with ; insets applied: font.w/2, font.h/4. ; make.text.box creates a box that is the size ; of text with insets ; text.w t ; text.h t ; text.width t ; text.height t ; make.text.box t, box ; draw.caption t, x, y ; draw.caption.x t, x, y, style, c, fc, lc ; draw.caption.a t, a ; draw.caption.align t, box, a ; set.colors c, fc, lc ; set.graphics g ; set.justify j ; backup.theme ; restore.theme STRUCTURE FONT ; custom bitmap font TEXT name(32) ; example: "Console" NUMBER type ; FT_x NUMBER w, h ; glyph size. example: 16x24 COLOR color IMAGE image ; glyph images ENDS ?font powers FT_MONOSPACE, FT_VARIABLE, FT_RASTER,\ FT_IMAGE, FT_TEXTURE, FT_GRADIENT, FT_ALPHA numeric FT_DEFAULT=FT_MONOSPACE+FT_RASTER align 8 FONT font, font.backup TEXT font.folder='FONT\',\ font.ext='.BMP', font.wild='*.BMP' ;;;;;;;;;;;;;;;;;;; SYMBOLS ;;;;;;;;;;;;;;;;;;;;;; ; my default character arrangement: 95 symbols. ; includes all standard visible characters ; 0 1 2 3 4 5 6 7 8 9 A B C D E F G H I ; J K L M N O P Q R S T U V W X Y Z a b ; c d e f g h i j k l m n o p q r s t u ; v w x y z _ . ? ; : ' " , ~ ! @ # $ ; % ^ & * ( ) [ ] { } = + - < > / \ | ` ; symbol lookup table to convert 7BIT ASCII ; character to index. 63=ignore (spaces, etc) N_SYMBOLS=95 FONT_SYMBOLS: db \ 63,63,63,63,63,63,63,63, 63,63,63,63,63,63,63,63,\ 63,63,63,63,63,63,63,63, 63,63,63,63,63,63,63,63,\ 63,72,69,74,75,76,78,68, 80,81,79,87,70,88,64,91,\ 00,01,02,03,04,05,06,07, 08,09,67,66,89,86,90,65,\ 73,10,11,12,13,14,15,16, 17,18,19,20,21,22,23,24,\ 25,26,27,28,29,30,31,32, 33,34,35,82,92,83,77,62,\ 94,36,37,38,39,40,41,42, 43,44,45,46,47,48,49,50,\ 51,52,53,54,55,56,57,58, 59,60,61,84,93,85,71,63 ;;;;;;;;;;;;;;; GET/SET FONT/COLOR ;;;;;;;;;;;;;;; function get.font, f memory.copy [f], font, FONT.$ endf function set.font, f push [font.color] memory.copy font, [f], FONT.$ pop [font.color] endf function set.font.c, f, c memory.copy font, [f], FONT.$ let [font.color]=[c] endf macro set.font.color c { let [font.color]=c } function destroy.font, f let eax=[f] destroy [?font.image.p+eax] endf macro backup.font { get.font font.backup } macro restore.font { set.font font.backup } ;;;;;;;;;;;;;;; LOAD BITMAP FONT ;;;;;;;;;;;;;;;;; ; font.w=image.w/N_SYMBOLS, font.h=image.h (same) function load.font, font, file locals name, image, w, h let eax=[font],\ ecx=&[?font.name+eax], [name]=ecx,\ ecx=&[?font.image+eax], [image]=ecx text.copy [name], [file] remove.ext [name] text.upper [name] !if load.image, [image], [file] ; returns w/h let [w]=ecx, [h]=edx, eax=ecx,\ ; in ecx/edx ecx=N_SYMBOLS, eax/ecx, ecx=[font],\ [?font.w+ecx]=eax, [?font.h+ecx]=[h] set.image.key [image] .end set.font.c [font], WHITE endf ; load fonts by name macro load.fonts [p] { forward make.txt eax, 'FONT\'#`p#'.BMP' load.font p#.f, eax } ;;;;;;;;;;;;;;;;;; SYSTEM FONTS ;;;;;;;;;;;;;;;;;; macro define.system.fonts { FONT text.f, text2.f,\ code1.f, code2.f, code3.f, code4.f, code5.f, console.f, console2.f,\ type.f, type2.f } macro load.system.fonts { load.fonts text, text2,\ code1, code2, code3, code4, code5, console, console2,\ type, type2 } ;;;;;;;;;;;;;;;;;; FONT ARRAY ;;;;;;;;;;;;;;;;;;;; align 8 ARRAY _fonts(FONT.$), _font.files(1*KB) NUMBER font.index ; create dynamic array of FONT structures then ; load all fonts from \FONT\. this may be ; located in the current directory or 1-2 higher ; directories for all projects to share function load.all.fonts locals i, p let [font.index]=0 try where.is font.folder ; get filenames try find.files _font.files, font.wild .loop [i]=0 to [_font.files.n] ; load images @index [p]=_font.files[i] @expand _fonts load.font eax, [p] .endl reset.directory let eax=[_fonts] endf ; set.font i - set current font by index function set.font.i, i @index _fonts[i] set.font eax let [font.index]=[i] endf ; get font name by index function get.font.name, i @index _fonts[i] let eax+?font.name endf ; get font index by name or return -1 ; if doesn't exist function get.font.i, name locals i .loop [i]=0 to [_fonts.n] @index _fonts[i] let eax+?font.name .if.text.equal name, eax return [i] .end .endl let eax=-1 endf function destroy.fonts locals i .loop [i]=0 to [_fonts.n] @index _fonts[i] destroy.font eax .endl endf ;;;;;;;;;;;;;;;;; DRAW CHARACTER ;;;;;;;;;;;;;;;;; ; the heart of all draw text functions ; draw.c 'Z', 1, 1 function draw.c, ch, x, y locals p, iw, i, n let eax=FONT_SYMBOLS, eax+[ch] cmp byte [eax], 63 ; invisible? je .! try visible [x], [y], [font.w], [font.h] ; p=&image[symbols[ch]*font.w*4] let eax=FONT_SYMBOLS, eax+[ch],\ eax=>[eax], eax*[font.w], eax<<2,\ eax+[font.image.p], [p]=eax,\ [iw]=[font.image.w], [iw]<<2 ; draw font.h # scanlines .loop [i]=0 to [font.h] let ecx=[y], ecx+[i] draw.scanline.v [p], [x], ecx,\ [font.w], [font.color] let ecx=[p], ecx+[iw], [p]=ecx .endl let eax=[draw.c.p] endf ; current draw character function pointer. ; just redefine this for custom gradients ; and textures align 8 VOID draw.c.p=!draw.c function set.draw.c, a let [draw.c.p]=[a] endf ;;;;;;;;;;;;;;;;;;; DRAW TEXT ;;;;;;;;;;;;;;;;;;;; ; draw.text.t 'SunGod Software', 1, 1 function draw.text, t, x, y locals i, n, p let eax=[t],\ [p]=eax, [i]=0 .while byte [eax] ; draw all characters let ecx=[i],\ ; x=i*font.w+x ecx*[font.w],\ ecx+[x], eax=[p],\ ; get c eax=>[eax] .if eax=0Dh ; return? let [i]=0,\ ; reset x ecx=[font.h],\ [y]+ecx, [p]++,\ ; y+font.h [i]=0 jmp .next .end let edx=[y],\ ; get y+font.h edx-[font.h] cmp edx, [screen.h] ; off screen? jg .! ; return calla [draw.c.p],\ ; draw character eax, ecx, [y] let [i]++ .next: let [p]++, eax=[p] ; eax=p for while .endw endf ; literal 'text' version macro draw.text.t t, x, y { make.txt eax, t draw.text eax, x, y } ; set color then draw text macro draw.text.c t, x, y, c { set.font.color c draw.text t, x, y } ;;;;;;;;;;;;;;;;; TEXT/BOX SIZE ;;;;;;;;;;;;;;;;;; ; get width of 'text' in characters. if single ; line, w = text length. if multi-line, w = ; longest line function text.wc, t locals p, s, n, gw let [p]=[t], eax=[t] .if byte [eax]=0 ; no text return 0 .end ; which line has the greatest width? let [gw]=0 .line: ; get line let [s]=[p] get [p]=text.find \ ; find first/next 0Dh [p], 0Dh .if true ; multi-line? let eax-[s],\ ; length [n]=eax, [p]+2 .else ; single or last line? get [n]=text.n [s] ; length = until 0 .end let ecx=[n] .if ecx>[gw] ; greatest width? let [gw]=ecx .end .if [p] ; more lines? jmp .line .end let eax=[gw] endf ; get height in characters or # lines function text.hc, t locals n, p let [n]=0,\ eax=[t], [p]=eax .if not byte [eax] ; no lines let eax=0 escape .end .while [p] let [n]++ ; 1+ lines get [p]=text.find \ [p], 0Dh .if true let [p]+2 .end .endw let eax=[n] endf ; get exact size in pixels of single or ; multi-line 'text' in current font. ; w=longest.line*font.w. h=n.lines*font.h function text.w, t text.wc [t] let eax*[font.w] endf function text.h, t text.hc [t] let eax*[font.h] endf ; return exact size in memory variables. ; w/h are sent by reference function text.size, t, w, h text.w [t] push eax text.h [t] pop ecx let edx=[w], [edx]=ecx,\ edx=[h], [edx]=eax endf ; get text insets: font.w/2, font.h/4 function text.ix let eax=[font.w], eax>>1 endf function text.iy let eax=[font.h], eax>>2 endf ; return insets in memory variables. x/y are ; sent by reference function text.insets, x, y text.ix let ecx=[x], [ecx]=eax text.iy let ecx=[y], [ecx]=eax endf ; get size of 'text' with insets applied: ; w*font.w+(inset.x*2), h*font.h+(inset.y*2) function text.width, t text.wc [t] let ecx=[font.w], eax*ecx, eax+ecx endf function text.height, t text.hc [t] let ecx=[font.h], eax*ecx, ecx>>1, eax+ecx endf ; size of character with insets function font.width let eax=[font.w], ecx=eax, ecx>>1, eax+ecx endf function font.height let eax=[font.h], ecx=eax, ecx>>2, eax+ecx endf ; return box size in memory variables. ; w/h are sent by reference function text.box.size, t, w, h text.width [t] push eax text.height [t] pop ecx let edx=[w], [edx]=ecx,\ edx=[h], [edx]=eax endf ; create box to contain text with insets. ; used by draw.caption/x and controls function make.text.box, t, box text.width [t] push eax text.height [t] pop ecx let edx=[box],\ [?box.w+edx]=ecx, [?box.h+edx]=eax endf ; create box based on width in characters function make.text.box.w, box, w let eax=[box],\ ecx=[w], edx=[font.w], ecx*edx, ecx+edx,\ [?box.w+eax]=ecx,\ ecx=[h], edx=[font.h], ecx*edx, edx>>1,\ ecx+edx, [?box.h+eax]=ecx endf ; text is considered "multi-line" if ; it contains at least one 0Dh, 2+ lines. ; any beginning or ending returns should be ; removed in non-editable graphic text macro is.multi.line t { text.find t, 0Dh } ; get greatest w in literal text array function text.array.w, ta, n locals i, w let [w]=0 .loop [i]=0 to [n] let eax=[ta], ecx=[i] text.w [eax+ecx*4] .if eax>[w] let [w]=eax .end .endl let eax=[w] endf ;;;;;;;;;;; DRAW C/TEXT WITH ALIGNMENT ;;;;;;;;;;; ; draw c/text aligned inside of BOX (x/y/w/h). ; see BOX.INC alignment values: CENTER_X/Y, ; ALIGN_C/L/T/R/B/N/NE/E/SE/S/SW/W/NW, JUSTIFY_L/R BOX c.box, t.box function draw.c.a, c, b, a make.box c.box, [font.w], [font.h] align.box c.box, [b], [a] draw.c [c], [c.box.x], [c.box.y] endf function draw.text.a, t, b, a text.size [t], t.box.w, t.box.h align.box t.box, [b], [a] draw.text [t], [t.box.x], [t.box.y] endf function draw.text.in, t, b, a, nx, ny text.size [t], t.box.w, t.box.h align.box t.box, [b], [a] nudge.box t.box, [nx], [ny] draw.text [t], [t.box.x], [t.box.y] endf macro draw.text.t t, x, y { make.txt eax, t draw.text eax, x, y } macro draw.text.center t, b { draw.text.align t, b, CENTER } ;;;;;;;;;;;;;;;;;;;;; THEME ;;;;;;;;;;;;;;;;;;;;;; macro THEME.X { NUMBER graphics ; G_x style FONT font COLOR color,\ line.color,\ shade.color NUMBER justify } STRUCTURE THEME THEME.X ENDS ASSUME ?theme=THEME align 4 THEME theme, theme.backup macro set.colors c, fc, lc { let [theme.color]=c, [theme.font.color]=fc,\ [theme.line.color]=lc } macro set.default.colors { set.colors BLACK, WHITE, GRAY } macro set.graphics g { let [theme.graphics]=g } macro set.justify j { let [theme.justify]=j } function backup.theme memory.copy theme.backup, theme, THEME.$ let eax=theme, ecx=theme.backup endf function restore.theme memory.copy theme, theme.backup, THEME.$ endf ;;;;;;;;;;;;;;;;;;;; CAPTION ;;;;;;;;;;;;;;;;;;;;; ; "[Caption]"; a box/frame that contains text ; with insets and is drawn according to the ; current "theme" align 4 BOX ca.box, ct.box NUMBER _caption.w, _caption.h ; if G_STATIC function set.caption.size, w, h let [_caption.w]=[w], [_caption.h]=[h] endf function draw.caption, t, x, y locals i, n, p,\ w, h, ix, iy, graphics, justify let [graphics]=[theme.graphics],\ [justify]=[theme.justify] .if not [graphics] ; default set.graphics (G_DYNAMIC+G_COLOR+G_LINE+G_TEXT) let [graphics]=[theme.graphics] .end .if not [theme.justify] set.justify CENTER let [justify]=[theme.justify] .end .if [graphics]&G_STATIC ; get box size let [w]=[_caption.w], [h]=[_caption.h] .else.if [graphics]&G_DYNAMIC let eax=&[w], ecx=&[h] text.box.size [t], eax, ecx .end .if [graphics]&G_COLOR ; draw box? draw.box [x], [y], [w], [h],\ [theme.color], YES .end .if [graphics]&G_LINE ; outline? draw.box [x], [y], [w], [h],\ [theme.line.color], NO .end .if.n [graphics]&G_TEXT ; text? escape ; no? return .end ; create box to contain text let eax=&[ix], edx=&[iy] ; size of text+insets text.insets eax, edx create.box ca.box, [x], [y], [w], [h] create.box.inside ct.box, ca.box, [ix], [iy] set.font.color [theme.font.color] get [n]=text.hc [t] let [p]=[t] .loop [i]=0 to [n] ; draw each row/line... let eax=[p],\ edx=[?t] ; copy until return @@: let ecx=>[eax] test ecx, ecx ; or 0 jz @f cmp ecx, 0Dh je @f let cl=[eax], [edx]=cl, eax++, edx++ jmp @b @@: ; draw text aligned horizontally... let eax+2, [p]=eax, byte [edx]=0 create.box ca.box, [ct.box.x], [ct.box.y],\ [ct.box.w], [font.h] let eax=[font.h], [ct.box.y]+eax,\ ; move down eax=[ca.box.x], ecx=[ca.box.y] draw.text.a [?t], ca.box, [justify] .endl endf ; draw "[Caption]" in specified style and colors function draw.caption.x, t, x, y, style, c, fc, lc .if not [style] ; default let [style]=(G_DYNAMIC+G_COLOR+G_LINE+G_TEXT) .end set.graphics [style] set.colors [c], [fc], [lc] draw.caption [t], [x], [y] endf ; draw "[Caption]" aligned relative to ; the screen function draw.caption.s, t, a make.text.box [t], ca.box align.b ca.box, [a] draw.caption [t], [ca.box.x], [ca.box.y] endf ; draw "[Caption]" aligned inside of ; another box with optional nudge x/y function draw.caption.a, t, b, a make.text.box [t], ca.box align.box ca.box, [b], [a] draw.caption [t], [ca.box.x], [ca.box.y] endf function draw.caption.in, t, b, a, nx, ny make.text.box [t], ca.box align.box ca.box, [b], [a] nudge.box ca.box, [nx], [ny] draw.caption [t], [ca.box.x], [ca.box.y] endf |
|||
12 Nov 2012, 16:55 |
|
uart777 12 Nov 2012, 16:57
|
|||
12 Nov 2012, 16:57 |
|
JohnFound 12 Nov 2012, 16:57
uart777, isn't it better to pack these files to .zip file and to publish them this way? Together with explanation what is this and how to use it.
|
|||
12 Nov 2012, 16:57 |
|
uart777 12 Nov 2012, 16:58
JohnFound: Sorry. I intended to do that, but my hard drives went out
Any questions? Please ask. "vga" is a linear 32BPP pixel array. |
|||
12 Nov 2012, 16:58 |
|
uart777 12 Nov 2012, 17:06
Code: ; clear screen. copy w*h # dwords function clear.screen push edi let edi=[vga], eax=[screen.color],\ ecx=[screen.w], ecx*[screen.h] rep stosd pop edi endf |
|||
12 Nov 2012, 17:06 |
|
uart777 12 Nov 2012, 17:14
By the way, here's the oldest code I could find. Written in MASM in 97':
Code: ; MASM DirectX example .386 .model flat, stdcall option casemap: none includelib \masm32\lib\user32.lib includelib \masm32\lib\gdi32.lib includelib \masm32\lib\kernel32.lib includelib \masm32\lib\winmm.lib includelib \masm32\lib\ddraw.lib includelib \masm32\lib\dsound.lib include \masm32\include\windows.inc include \masm32\include\kernel32.inc include \masm32\include\user32.inc include \masm32\include\gdi32.inc include \masm32\include\winmm.inc include \masm32\include\ddraw.inc include \masm32\include\dsound.inc callp equ invoke ; IDirectDraw interface method offsets DDRELEASE equ 8 DDBLT equ 20 DDCREATESURFACE equ 24 DDFLIP equ 44 DDGETATTACHEDSURFACE equ 48 DDGETDC equ 68 DDSETCOOPERATIVELEVEL equ 80 DDSETDISPLAYMODE equ 84 DDLOCK equ 100 DDRELEASEDC equ 104 DDRESTORE equ 108 DDUNLOCK equ 128 ; DirectX object types LPDIRECTDRAW typedef ptr dword LPDIRECTDRAWSURFACE typedef ptr dword LPDIRECTDRAWCLIPPER typedef ptr dword LPDIRECTSOUND typedef ptr dword LPDIRECTSOUNDBUFFER typedef ptr dword MakeWindow proto WName: dword, WProc: dword WndProc proto W: dword, M: dword, WP: dword, LP: dword SetDirectDraw proto Clear proto CColor: dword Flip proto Release proto Object: dword LoadBMP proto FN: dword DrawImage proto SImage: dword, X: dword, Y: dword, W: dword, H: dword, TC: dword SetTransparent proto SImage: dword SetDirectSound proto LoadWAV proto FN: dword Play proto SoundP: dword, LoopS: dword Collide proto R: dword, R2: dword MoveImage proto ImageP: dword, Direction: dword, NPixels: dword Debug proto Number: dword Image struc X dd 0 Y dd 0 W dd ? H dd ? TC dd 0 ; (Unused but transparency works) I LPDIRECTDRAWSURFACE 0 Image ends UP equ 0 RIGHT equ 1 DOWN equ 2 LEFT equ 3 Zero macro M, N mov edi, M mov ecx, N xor eax, eax cld rep stosd endm ; ***************************** .data ******************************** .data WindowName db 'MASM DirectX Example. Move with cursor keys. Esc to exit', 0 ErrorMsg db 'Error', 0 BMPName db 'asm.bmp', 0 WAVName db 's.wav', 0 Instance dd 0 Window dd 0 Msg MSG <?> DC HDC ? Color dd 0 DirectDraw LPDIRECTDRAW 0 MainSurface LPDIRECTDRAWSURFACE 0 BackBuffer LPDIRECTDRAWSURFACE 0 BackBuffer2 LPDIRECTDRAWSURFACE 0 Clipper LPDIRECTDRAWCLIPPER 0 DDSCAPS dd ? DDBLTFX db 100 dup(?) DirectSound LPDIRECTSOUND 0 UpKey dd 0 RightKey dd 0 DownKey dd 0 LeftKey dd 0 TempR RECT <?> Start dd ? Time dd 10 ; Edit this DText db 30 dup(?) ; For Debug DFormat db '%d', 0 DNumber dd 0 MyImage Image <?> MySound LPDIRECTSOUNDBUFFER 0 ; ***************************** .code ******************************** .code start: callp MakeWindow, addr WindowName, addr WndProc test eax, eax jz Exit mov Window, eax ; Save HWND and instance mov Instance, edx call SetDirectDraw test eax, eax jz Exit call SetDirectSound test eax, eax jz Exit callp LoadBMP, addr BMPName mov MyImage.I, eax mov MyImage.W, edx mov MyImage.H, ecx mov MyImage.Y, 110 ;callp SetTransparent, MyImage.I callp LoadWAV, addr WAVName mov MySound, eax callp Play, MySound, 1 ; *************************** MessageLoop ****************************** MessageLoop: callp PeekMessage, addr Msg, 0, 0, 0, PM_REMOVE test eax, eax jz GameLoop ; No messages pending. Update game cmp Msg.message, WM_QUIT jz Exit callp TranslateMessage, addr Msg ; Convert VK_ keys callp DispatchMessage, addr Msg ; Send to WndProc jmp MessageLoop ; *************************** Game Loop ******************************** GameLoop: ; 1. Save start time call GetTickCount mov Start, eax ; 2. Clear back buffers callp Clear, Color ; 3. Update everything... callp DrawImage, MyImage.I, MyImage.X, MyImage.Y, MyImage.W, MyImage.H, 0 ; Last parameter = 1 if transparent ; Draw text. GDI drawing causes flicker callp GetDC, Window mov DC, eax callp TextOut, DC, 0, 0, addr WindowName, 56 callp ReleaseDC, Window, DC callp Debug, DNumber callp GetAsyncKeyState, VK_UP mov UpKey, eax callp GetAsyncKeyState, VK_RIGHT mov RightKey, eax callp GetAsyncKeyState, VK_DOWN mov DownKey, eax callp GetAsyncKeyState, VK_LEFT mov LeftKey, eax callp GetAsyncKeyState, VK_SPACE cmp eax, 0 jz NoSpace callp Play, MySound, 1 NoSpace: cmp UpKey, 0 jz IsRight callp MoveImage, addr MyImage, UP, 10 IsRight: cmp RightKey, 0 jz IsDown callp MoveImage, addr MyImage, RIGHT, 10 IsDown: cmp DownKey, 0 jz IsLeft callp MoveImage, addr MyImage, DOWN, 10 IsLeft: cmp LeftKey, 0 jz NoKey callp MoveImage, addr MyImage, LEFT, 10 NoKey: ; 4. Show back buffer. Do nothing while time not expired call Flip DoNothing: call GetTickCount sub eax, Start cmp eax, Time jbe DoNothing ; 5. Return to message loop jmp MessageLoop Exit: callp ExitProcess, Msg.wParam ; *************************** WndProc ********************************** WndProc proc W: dword, M: dword, WP: dword, LP: dword mov eax, M cmp eax, WM_KEYDOWN ; Most likely case jz OnKeyDown cmp eax, WM_KEYUP jz OnKeyUp cmp eax, WM_MOUSEMOVE jz OnMouseMove cmp eax, WM_LBUTTONDOWN jz OnLButtonDown cmp eax, WM_LBUTTONUP jz OnLButtonUp cmp eax, WM_PAINT jz OnPaint cmp eax, WM_CHAR jz OnChar cmp eax, WM_CREATE jz OnCreate cmp eax, WM_DESTROY jz OnDestroy jmp WPDefault ; Default Windows processing OnCreate: jmp WPExit OnPaint: jmp WPDefault OnKeyDown: cmp WP, VK_ESCAPE jnz NotEsc callp SendMessage, Window, WM_DESTROY, 0, 0 NotEsc: jmp WPExit OnKeyUp: jmp WPExit OnChar: jmp WPExit OnMouseMove: jmp WPExit OnLButtonDown: jmp WPExit OnLButtonUp: jmp WPExit OnDestroy: ; Images/sounds may be released anytime callp Release, MyImage.I callp Release, MySound callp Release, Clipper ; DirectX objects must be released in this order... callp Release, BackBuffer callp Release, BackBuffer2 callp Release, MainSurface callp Release, DirectDraw ; Don't release this first callp Release, DirectSound callp PostQuitMessage, 0 jmp WPExit WPDefault: callp DefWindowProc, W, M, WP, LP WPExit: ret WndProc endp ; ************************** MakeWindow *************************** ; Create and show Window. Parameters: Window name and procedure. ; Return: eax = HWND or 0 if error. edx = Instance MakeWindow proc WName: dword, WProc: dword local WC: WNDCLASSEX local ClassName: dword local WindowR: dword local InstanceR: dword mov eax, 11111111h ; Mark beginning mov ClassName, 00005A45h ; 'EZ', 0, 0 ; Save module handle callp GetModuleHandle, 0 mov InstanceR, eax ; Define and register Window class mov WC.cbSize, 30h mov WC.style, 0 push WProc pop WC.lpfnWndProc mov WC.cbClsExtra, 0 mov WC.cbWndExtra, 0 push InstanceR pop WC.hInstance mov WC.hbrBackground, 73Eh mov WC.lpszMenuName, 0 lea eax, ClassName mov WC.lpszClassName, eax callp LoadIcon, 0, IDI_APPLICATION mov WC.hIcon, eax mov WC.hIconSm, eax callp LoadCursor, 0, IDC_ARROW mov WC.hCursor, eax callp RegisterClassEx, addr WC test eax, eax jz MWError ; Create Window callp CreateWindowEx, WS_EX_TOPMOST, addr ClassName, WName, WS_VISIBLE or\ WS_POPUP, 0, 0, 640, 480, 0, 0, InstanceR, 0 test eax, eax jz MWError mov WindowR, eax ; Window setup callp ShowWindow, WindowR, SW_SHOWNORMAL callp UpdateWindow, WindowR mov eax, 99999999h ; Mark end mov eax, WindowR mov edx, InstanceR ret MWError: xor eax, eax ret MakeWindow endp ; *************************** SetDirectDraw ************************* SetDirectDraw proc local DDSURFACEDESC[108]: byte ; Create DirectDraw callp DirectDrawCreate, 0, addr DirectDraw, 0 ; SetCooperativeLevel push 11h ; Flags: FRONTBUFFER | CAPS push Window calldx DirectDraw, DDSETCOOPERATIVELEVEL ; SetDisplayMode push 16 push 480 push 640 calldx DirectDraw, DDSETDISPLAYMODE test eax, eax ; All DirectX methods return 0/DX_OK if success jnz DDError ; Create MainSurface lea eax, DDSURFACEDESC mov dword ptr [eax], 108 ; dwSize mov dword ptr [eax + 4], 21h ; dwFlags mov dword ptr [eax + 104], 218h ; dwCaps: PRIMARY, FLIP, COMPLEX mov dword ptr [eax + 20], 2 ; dwBackBufferCount push 0 push offset MainSurface lea eax, DDSURFACEDESC push eax calldx DirectDraw, DDCREATESURFACE test eax, eax jnz DDError ; Attach back buffer push offset BackBuffer mov DDSCAPS, 4 ; BACKBUFFER flag push offset DDSCAPS calldx MainSurface, DDGETATTACHEDSURFACE test eax, eax jnz DDError ; Attach back buffer 2 push offset BackBuffer2 mov DDSCAPS, 4 push offset DDSCAPS calldx MainSurface, DDGETATTACHEDSURFACE test eax, eax jnz DDError ; Create clipper. So, images can move outside screen boundaries push 0 push offset Clipper push 0 calldx DirectDraw, 16 test eax, eax jnz DDError ; Clipper > Set HWND push Window push 0 calldx Clipper, 32 test eax, eax jnz DDError ; Surface > SetClipper push Clipper calldx BackBuffer, 112 test eax, eax jnz DDError mov eax, 1 ret DDError: xor eax, eax ret SetDirectDraw endp ; ********************* Animation: Clear, Flip ************************* ; Clear. Fill screen with color Clear proc CColor: dword local BLTFX[100]: byte lea eax, BLTFX mov dword ptr [eax], 100 ; dwSize mov edx, CColor mov dword ptr [eax + 80], edx ; dwFillColor push eax ; EDIT push 1000400h ; Flags: COLORFILL | WAIT push 0 push 0 push 0 calldx BackBuffer, DDBLT ret Clear endp ; Show back buffer Flip proc push 1 ; DDFLIP_WAIT push 0 calldx MainSurface, DDFLIP ret Flip endp ; ****************************** Release ****************************** ; Free DirectX object Release proc Object: dword cmp dword ptr [Object], 0 ; If released, end jz ReleaseEnd calldx Object, DDRELEASE mov dword ptr [Object], 0 ReleaseEnd: ret Release endp ; ****************************** LoadBMP ******************************* ; Load .bmp. Return: eax = Image, LPDIRECTDRAWSURFACE or 0 if error. ; edx/ecx = Image width/height LoadBMP proc FN: dword local HBM: HBITMAP local BM: BITMAP local BMDC: HDC local SDC: HDC local ImageP: LPDIRECTDRAWSURFACE local DDSURFACEDESC[108]: byte ;mov I, 0 ; 1. Load .bmp callp LoadImage, 0, FN, 0, 0, 0, 2010h test eax, eax jz BMPError mov HBM, eax callp GetObject, HBM, 24, addr BM ; 2. Create surface image ; Setup DDSURFACEDES... lea edi, DDSURFACEDESC xor eax, eax mov ecx, 27 cld rep stosd lea eax, DDSURFACEDESC mov dword ptr [eax], 108 ; dwSize mov dword ptr [eax + 4], 7 ; dwFlags: CAPS, HEIGHT, WIDTH mov dword ptr [eax + 104], 840h ; dwCaps: OFFSCREENPLAIN, SYSTEMMEMORY mov edx, BM.bmWidth mov dword ptr [eax + 12], edx mov edx, BM.bmHeight mov dword ptr [eax + 8], edx ; Note: Images are created in system memory so the mysterious "lost surface" ; error never occurs push 0 ; DirectDraw > CreateSurface(DDSURFACEDES *, LPDIRECTDRAWSURFACE *, 0) lea eax, ImageP push eax lea eax, DDSURFACEDESC push eax calldx DirectDraw, DDCREATESURFACE test eax, eax ; CreateSurface returns zero if true jnz BMPError callp CreateCompatibleDC, 0 mov BMDC, eax callp SelectObject, BMDC, HBM ; 3. Get image DC lea eax, SDC ; Image > GetDC(DC *) push eax calldx ImageP, DDGETDC ; 4. Draw .bmp to surface image. Only do this once callp BitBlt, SDC, 0, 0, BM.bmWidth, BM.bmHeight, BMDC, 0, 0, SRCCOPY ; 5. Delete everything... push SDC ; Image > ReleaseDC calldx ImageP, DDRELEASEDC callp DeleteDC, BMDC callp DeleteObject, HBM mov eax, ImageP mov edx, BM.bmWidth ; Return size in edx, ecx mov ecx, BM.bmHeight ret BMPError: xor eax, eax ret LoadBMP endp ; *************************** SetTransparent *************************** ; Make image transparent by pixel at 0, 0 SetTransparent proc SImage: dword local DDCOLORKEY[8]: byte local DDSURFACEDESC[108]: byte local Value: dword ; Lock surface and get DESC... lea eax, DDSURFACEDESC mov dword ptr [eax], 108 ; dwSize ReLock: push 0 ; Surface > Lock push 0 lea ebx, DDSURFACEDESC push ebx push 0 calldx SImage, DDLOCK cmp eax, 08876021Ch ; DDERR_WASSTILLDRAWING jz ReLock test eax, eax jnz CKError ; Get color in upper left corner lea eax, DDSURFACEDESC mov eax, [eax + 36] ; lpSurface mov eax, [eax] ; Dereference push eax push 0 calldx SImage, DDUNLOCK pop eax lea ebx, DDCOLORKEY mov dword ptr [ebx], eax mov dword ptr [ebx + 4], eax mov Value, eax ; Set color key... push ebx push 8 ; DDCKEY_SRCBLT calldx SImage, 116 test eax, eax jnz CKError mov eax, 1 ret CKError: xor eax, eax ret SetTransparent endp ; ****************************** DrawImage ***************************** ; Draw image to back buffer. SImage: LPDIRECTDRAWSURFACE. TC = 1/0, transparent. ; For transparent images, SetTransparent and TC = 1 DrawImage proc SImage: dword, X: dword, Y: dword, W: dword, H: dword, TC: dword mov eax, X ; Setup RECT... mov TempR.left, eax add eax, W mov TempR.right, eax mov eax, Y mov TempR.top, eax add eax, H mov TempR.bottom, eax push 0 mov edx, 0 ; Default to no transparent cmp TC, 1 jnz DINo mov edx, 8000h ; SRCCOLORKEY DINo: push edx push 0 push SImage push offset TempR calldx BackBuffer, DDBLT cmp eax, 887601C2h ; DDERR_SURFACELOST jz Restore ret Restore: calldx SImage, DDRESTORE calldx MainSurface, DDRESTORE calldx BackBuffer, DDRESTORE calldx BackBuffer2, DDRESTORE ret DrawImage endp ; **************************** SetDirectSound ************************** SetDirectSound proc callp DirectSoundCreate, 0, addr DirectSound, 0 test eax, eax jnz DSError push 1 ; DSSCL_NORMAL push Window calldx DirectSound, 24 test eax, eax jnz DSError mov eax, 1 ret DSError: xor eax, eax ret SetDirectSound endp ; ******************************* LoadWAV ****************************** ; Load .wav. Return LPDIRECTSOUNDBUFFER or 0 if error LoadWAV proc FN: dword local WAV: dword local WAVData[20]: byte ; MMCKINFO local FMTData[20]: byte ; Same local WAVInfo[18]: byte ; WAVEFORMATEX local DSBUFFERDESC[20]: byte local SoundBuffer: dword ; LPDIRECTSOUNDBUFFER local Audio1: dword local Audio2: dword local Length1: dword local Length2: dword callp mmioOpen, FN, 0, 10000h ; MMIO_READ | MMIO_ALLOCBUF test eax, eax jz LWError mov WAV, eax lea ebx, WAVData Zero ebx, 5 mov dword ptr [ebx + 8], 45564157h ; fccType = 'WAVE' callp mmioDescend, WAV, ebx, 0, MMIO_FINDRIFF lea ebx, FMTData Zero ebx, 5 mov dword ptr [ebx + 8], 20746D66h ; fccType = 'fmt ' callp mmioDescend, WAV, ebx, addr WAVData, 0 callp mmioRead, WAV, addr WAVInfo, 18 lea ebx, WAVInfo cmp word ptr [ebx], WAVE_FORMAT_PCM ; Verify signature jnz LWError callp mmioAscend, WAV, addr FMTData, 0 lea ebx, FMTData mov dword ptr [ebx], 61746164h ; ckid = 'data ' callp mmioDescend, WAV, addr FMTData, addr WAVData, MMIO_FINDCHUNK lea ebx, DSBUFFERDESC mov dword ptr [ebx], 20 ; dwSize mov dword ptr [ebx + 4], 224 ; Flags. DSBCAPS_CTRLDEFAULT lea eax, [FMTData + 4] mov dword ptr [ebx + 8], eax ; dwBufferBytes = FMTData.cksize mov dword ptr [ebx + 12], 0 lea eax, WAVInfo mov dword ptr [ebx + 16], eax ; lpwfxWAVFormat = offset WAVInfo push 0 ; DSound > CreateSoundBuffer lea eax, SoundBuffer push eax push ebx calldx DirectSound, 12 test eax, eax jnz LWError mov Audio1, 0 ; Circular buffers mov Audio2, 0 push 0 ; IDirectSoundBuffer > Lock lea ebx, Length2 push ebx lea edx, Audio2 push edx lea ebx, Length1 push ebx lea edx, Audio1 push edx push dword ptr [FMTData + 4] push 0 calldx SoundBuffer, 44 ; Write sounds... cmp Audio1, 0 jbe LWNo ; unsigned callp mmioRead, WAV, Audio1, Length1 LWNo: cmp Audio2, 0 jbe LWNo2 callp mmioRead, WAV, Audio2, Length2 LWNo2: push Length2 ; IDirectSoundBuffer > Unlock push Audio2 push Length1 push Audio1 calldx SoundBuffer, 76 callp mmioClose, WAV, 0 mov eax, SoundBuffer ret LWError: xor eax, eax ret LoadWAV endp ; ******************************** Play ******************************* ; Play sound. It had to be named "Play". "PlaySound" is a reserved name. ; LoopS = 1/0 Play proc SoundP: dword, LoopS: dword push 0 calldx SoundP, 52 ; SetCurrentPosition push LoopS push 0 push 0 calldx SoundP, 48 ; IDirectSoundBuffer > Play ret Play endp ; ******************************* Collide ****************************** ; Detect collision. eax = 1/0. Send 2 RECT pointers Collide proc R: dword, R2: dword ; left, top, right, bottom lea eax, [R] ; cmp eax, [R2 + 8] jg CNo lea edx, [R + 4] cmp edx, [R2 + 12] jg CNo lea eax, [R + 8] cmp eax, [R2] jl CNo lea edx, [R + 12] cmp edx, [R2 + 4] jl CNo mov eax, 1 ret CNo: xor eax, eax ret Collide endp ; ***************************** MoveImage ***************************** ; Move direction, # pixels. Direction = 0/UP, 1/RIGHT, 2/DOWN, 3/LEFT MoveImage proc ImageP: dword, Direction: dword, NPixels: dword mov eax, ImageP assume eax: ptr Image mov ecx, NPixels mov edx, Direction cmp edx, UP jz MIUp cmp edx, RIGHT jz MIRight cmp edx, DOWN jz MIDown cmp edx, LEFT jz MILeft ret MIUp: sub dword ptr [eax].Y, ecx jmp MIEnd MIRight: add dword ptr [eax].X, ecx jmp MIEnd MIDown: add dword ptr [eax].Y, ecx jmp MIEnd MILeft: sub dword ptr [eax].X, ecx MIEnd: ret MoveImage endp MoveBox proc RectP: dword, Direction: dword, NPixels: dword mov eax, RectP mov ecx, NPixels mov edx, Direction cmp edx, UP jz MRUp cmp edx, RIGHT jz MRRight cmp edx, DOWN jz MRDown cmp edx, LEFT jz MRLeft ret MRUp: sub dword ptr [eax + 4], ecx ret MRRight: add dword ptr [eax], ecx ret MRDown: add dword ptr [eax + 8], ecx ret MRLeft: sub dword ptr [eax + 12], ecx ret MoveBox endp ; ******************************* Debug ******************************* ; View value of number Debug proc Number: dword push Number push offset DFormat push offset DText call wsprintfA callp GetDC, Window callp TextOut, eax, 0, 100, addr DText, 30 callp ReleaseDC, Window, DC ret Debug endp ; ***************************** GAME OVER ***************************** end start |
|||
12 Nov 2012, 17:14 |
|
uart777 14 Nov 2012, 15:14
JohnFound: Please understand that I'm on an Android phone, not a standard laptop/desktop, and there are other reasons for mistakes in my posts that I definitely don't want to talk about (ie, multiple legal prescriptions).
I apologize for not presenting code the way you think I should, but this post is about HL MACROS, NOT font tags, site designs and unrelated things. I will be serious and stay on subject if everyone else does. Thanks. PS: LANGUAGE.INC is commented with examples and the files were only included to demonstrate how to use them. Last edited by uart777 on 17 Nov 2012, 06:07; edited 1 time in total |
|||
14 Nov 2012, 15:14 |
|
uart777 15 Nov 2012, 01:19
One more thing: Some people come here and post one little macro that doesn't work. I just now posted about 100+ macros/functions so there may be errors or unfinished or untested code.
|
|||
15 Nov 2012, 01:19 |
|
pool 03 Jan 2013, 16:41
..
Last edited by pool on 17 Mar 2013, 12:21; edited 1 time in total |
|||
03 Jan 2013, 16:41 |
|
uart777 04 Jan 2013, 04:25
pool: Hi. typedef is not needed. fix can create alternative names for HL variable types, functions, macros, etc. Since fix renames everything that follows it, be careful and only use it sparingly. Example:
Code: integer fix NUMBER string fix TEXT void fix VOID strlen fix text.n strcpy fix text.copy strcmp fix text.compare strcat fix text.attach strchr fix text.find strstr fix text.search malloc fix allocate realloc fix allocate.p free fix destroy memset fix memory.set memcpy fix memory.copy HL structures are like typedef struct in C. Example: Code: STRUCTURE IMAGE VOID p NUMBER x, y, w, h, bpp COLOR key, alpha ENDS TYPE NAME = TEXT first(32), middle(32), last(32) TYPE ADDRESS = TEXT country(32), street(64),\ city(64), state(32), zip(16) STRUCTURE PROFILE IMAGE image TEXT about(256), interests(256), quote(256) ENDS STRUCTURE USER TEXT username(32), password(32) NAME name ADDRESS address NUMBER age, gender, race, status,\ height, weight COLOR eye.color, hair.color PROFILE profile ENDS |
|||
04 Jan 2013, 04:25 |
|
pool 04 Jan 2013, 04:51
..
Last edited by pool on 17 Mar 2013, 12:21; edited 1 time in total |
|||
04 Jan 2013, 04:51 |
|
TmX 04 Jan 2013, 07:51
How can I use the macros?
It would be nice if you provide some small working examples |
|||
04 Jan 2013, 07:51 |
|
uart777 04 Jan 2013, 14:28
pool: Yes, it's like a miniature HL compiler within FASM
TmX wrote: Quote: How can I use the macros? VARIABLES: BYTE, NUMBER, TEXT, VOID Code: BYTE a, b='$', c=' ' NUMBER n VOID p ; 32 or 64BIT TEXT title='My Application', buffer(256) TEXTS fruits[]= 'Apple', 'Banana', 'Blueberry', 'Cherry',\ 'Grape', 'Lemon', 'Lime', 'Orange', 'Peach', 'Watermelon' TEXTS registers.32[8](4)=\ ; with alignment, size=4 bytes each 'eax', 'ecx', 'edx', 'ebx',\ 'esp', 'ebp', 'esi', 'edi' OPERATIONS: LET, GET, TRY let performs HL assignments and operations. Think of it as the inverse of _asm {} block in C. Example: Code: let \ ; extract r/g/b components ecx=eax, ecx>>16, ecx&0FFh, [sr]=ecx,\ ecx=eax, ecx>>8, ecx&0FFh, [sg]=ecx,\ ecx=eax, ecx&0FFh, [sb]=ecx,\ ecx=edx, ecx>>16, ecx&0FFh, [dr]=ecx,\ ecx=edx, ecx>>8, ecx&0FFh, [dg]=ecx,\ ecx=edx, ecx&0FFh, [db]=ecx let \ ; calculate deltas: (((s-d)*a)/256)+d eax=[sr], eax-[dr], eax*[n], eax>>8, eax+[dr],\ ecx=[sg], ecx-[dg], ecx*[n], ecx>>8, ecx+[dg],\ edx=[sb], edx-[db], edx*[n], edx>>8, edx+[db] let \ ; construct RGB eax<<16, ecx<<8, eax|ecx, eax|edx Note: let is derived from the original version of BASIC (Dartmouth) in 1964. LANGUAGE.INC contains classic syntaxes that were dug up from the past and revised. get calls a function then assigns its return value. Example: Code: get [n]=strlen t get [dice]=random 6 get [color]=rgb [x], [y], [z] ; output... push t call !text.n mov [n], eax push 6 call !random mov [dice], eax push [z] push [y] push [x] call !rgb mov [color], eax try calls a function then returns 0 (jmp to return label) if it does. Optionally, it can assign a variable like get: Code: try open [file] try [p]=allocate 64*KB try read [p], [n] ; output... push [file] call !open test eax, eax jz .! push 65536 call !allocate mov [p], eax test eax, eax jz .! push [n] push [p] call !read test eax, eax jz .! STRUCTURES STRUCTURE is an extension of FASM's \MACRO\STRUCT.INC that's easier to use. Optional ?name after ENDS creates a virtual structure to add to a base address or register: let [?image.x+eax]=0. Example: Code: STRUCTURE HUMAN TEXT name(32) NUMBER age, gender, height, weight TEXT address(256), phone(16), email(64) ENDS ?human Multiple instances can be created on the same line as in HL languages: Code: HUMAN me, you, him, her TYPE is a shortcut to create small structures. All members are of the same type: Code: TYPE POINT = NUMBER x, y TYPE LINE = POINT a, b TYPE SIZE = NUMBER w, h TYPE BOX = NUMBER x, y, w, h TYPE RECT = NUMBER left, top, right, bottom TYPE RGB = NUMBER a, r, g, b WINDOWS Some common Windoze definitions and structures (copy and paste): Code: STRUCTURE MSG NUMBER hwnd, message, wParam, lParam,\ time, pt.x, pt.y ENDS STRUCTURE WNDCLASSEX NUMBER cbSize=48, style, lpfnWndProc,\ cbClsExtra, cbWndExtra, hInstance, hIcon,\ hCursor, hbrBackground, lpszMenuName,\ lpszClassName, hIconSm ENDS ?wc numeric \ ; window messages WM_CREATE=1, WM_DESTROY=2, WM_MOVE=3,\ WM_SIZE=5, WM_SETFOCUS=7, WM_KILLFOCUS=8,\ WM_GETTEXT=0Dh, WM_SETTEXT=0Ch,\ WM_GETTEXTLENGTH=0Eh, WM_PAINT=0Fh,\ WM_CLOSE=10h, WM_QUIT=12h, WM_CUT=300h,\ WM_COPY=301h, WM_PASTE=302h, WM_CLEAR=303h,\ WM_SETFONT=30h, WM_COMMAND=111h, WM_TIMER=0113h numeric \ ; window styles WS_POPUP=80000000h,\ WS_MINIMIZE=20000000h, WS_VISIBLE=10000000h,\ WS_MAXIMIZE=1000000h, WS_CAPTION=0C00000h,\ WS_BORDER=800000h, WS_DLGFRAME=400000h,\ WS_VSCROLL=200000h, WS_HSCROLL=100000h,\ WS_SYSMENU=80000h, WS_THICKFRAME=40000h,\ WS_MINIMIZEBOX=20000h, WS_MAXIMIZEBOX=10000h,\ WS_BLANK=WS_VISIBLE+WS_POPUP,\ WS_DEFAULT=WS_VISIBLE\ +WS_CAPTION+WS_MINIMIZEBOX+WS_SYSMENU numeric \ ; keyboard messages WM_KEYDOWN=100h, WM_KEYUP, WM_CHAR, WM_DEADCHAR,\ WM_SYSKEYDOWN, WM_SYSKEYUP, WM_SYSCHAR numeric \ ; mouse messages WM_MOUSEMOVE=200h, WM_LBUTTONDOWN, WM_LBUTTONUP,\ WM_LBUTTONDBLCLK, WM_RBUTTONDOWN, WM_RBUTTONUP,\ WM_RBUTTONDBLCLK, WM_MBUTTONDOWN, WM_MBUTTONUP,\ WM_MBUTTONDBLCLK, WM_MOUSEWHEEL ; virtual key codes. function keys=(6Fh+N). ; example: F1=70h (6Fh+1) numeric \ VK_LEFT=25h, VK_UP=26h,\ VK_RIGHT=27h, VK_DOWN=28h,\ VK_ESCAPE=1Bh, VK_SPACE=20h,\ VK_DELETE=2Eh, VK_LCONTROL=0A2h,\ VK_RCONTROL=0A3h, VK_LALT=0A4h,\ VK_RALT=0A5h, VK_BACK=8, VK_TAB=9,\ VK_RETURN=0Dh, VK_END=23h, VK_HOME=24h HDC fix VOID HFONT fix VOID HBITMAP fix VOID SRCCOPY=00CC0020h STRUCTURE PAINTSTRUCT NUMBER hdc, fErase RECT rcPaint NUMBER fRestore, fIncUpdate BLOCK rgbReserved(32) ENDS ?paint.struct STRUCTURE BITMAP NUMBER bmType, bmWidth, bmHeight,\ bmWidthBytes WORD bmPlanes, bmBitsPixel VOID bmBits ENDS ?bitmap STRUCTURE BITMAPINFOHEADER NUMBER biSize, biWidth, biHeight WORD biPlanes, biBitCount NUMBER biCompression, biSizeImage,\ biXPelsPerMeter, biYPelsPerMeter,\ biClrUsed, biClrImportant ENDS STRUCTURE BITMAPINFO BITMAPINFOHEADER h DWORD bmiColors ENDS ?bitmap.info STRUCTURE BITMAPFILEHEADER WORD bfType NUMBER bfSize, bfReserved, bfOffBits ENDS STRUCTURE LOGFONT NUMBER nHeight, nWidth, nEscapement,\ nOrientation, fnWeight, fdwItalic,\ fdwUnderline, fdwStrikeOut, fdwCharSet,\ fdwOutputPrecision, fdwClipPrecision,\ fdwQuality, fdwPitchAndFamily TEXT lpszFace(32) ENDS ?log.font numeric FW_LIGHT=300, FW_NORMAL=400,\ FW_MEDIUM=500, FW_BOLD=700, FW_HEAVY=900 numeric DEFAULT_QUALITY, DRAFT_QUALITY,\ PROOF_QUALITY, NONANTIALIASED_QUALITY,\ ANTIALIASED_QUALITY STRUCTURE CHOOSECOLOR NUMBER lStructSize, hwndOwner, hInstance,\ rgbResult, lpCustColors, Flags, lCustData,\ lpfnHook, lpTemplateName ENDS ?choose.color numeric CC_RGBINIT=1, CC_FULLOPEN=2 STRUCTURE CHOOSEFONT NUMBER lStructSize, hwndOwner, hDC, lpLogFont,\ iPointSize, Flags, rgbColors, lCustData,\ lpfnHook, lpTemplateName, hInstance, lpszStyle WORD nFontType, wReserved NUMBER nSizeMin, nSizeMax ENDS ?choosefont numeric CF_SCREENFONTS=1, CF_PRINTERFONTS=2,\ CF_BOTH=3, CF_INITTOLOGFONTSTRUCT=40h,\ CF_EFFECTS=100h STRUCTURE OPENFILENAME NUMBER lStructSize, hwndOwner, hInstance,\ lpstrFilter, lpstrCustomFilter,\ nMaxCustFilter, nFilterIndex, lpstrFile,\ nMaxFile, lpstrFileTitle, nMaxFileTitle,\ lpstrInitialDir, lpstrTitle, Flags WORD nFileOffset, nFileExtension NUMBER lpstrDefExt, lCustData,\ lpfnHook, lpTemplateName ENDS ?openfilename numeric OFN_READONLY=1, OFN_OVERWRITEPROMPT=2,\ OFN_HIDEREADONLY=4, OFN_ALLOWMULTISELECT=200h,\ OFN_PATHMUSTEXIST=800h, OFN_FILEMUSTEXIST=1000h,\ OFN_CREATEPROMPT=2000h FILE I/O Code: ; example... include 'z.inc' TEXT t(128),\ f='EXAMPLE.TXT',\ s='EXAMPLE TEXT DATA' n=s.$ code create f ; create file write s, n ; write to current file close ; close after create open f ; reopen read t, n ; read to t say t ; display text close ; close after open execute f ; ShellExecute maximize exit ; ExitProcess 0 "WHY USE LET?" * let translates directly to pure X86 instructions so there is absolutely NO overhead. What you see is what you get. Please view the disassembly and see for yourself * =/=&/+/-/<</etc are just shortcut symbols to mov/lea/add/sub/shl/etc * Unlike HL infix expressions, you specify BOTH destination AND source operands and there is NO compiler making random decisions behind the scenes about which spare registers to use for sub/expressions * let does NOT alter ANY registers except specified destination/"lvalue": let eax=ecx * let supports the SAME operands as the instructions so you MUST know ASM well in order to use it properly. Example: x<<y must be written as: let eax=[x], ecx=>[y], eax<<cl (PS: Only one exception: let [x]=[y] is push then pop. = is the only one that allows m,m) * let can be written with all registers and it produces exactly what you'd write in pure ASM: .convert: let eax=[esi], eax&0FFh, eax<<24, [edi]|eax, edi+4, esi+4, ecx-- jnz .convert ; would be 5 times longer if it were written on separate lines. That's a difference between 2,000 and 10,000 lines! * let improves readability, makes code compact and easier to manage * let can be edited to output FPU and other CPU cores - ARM, Java, etc - whatever you want it to. In FASM, you have 100% control of output code * Easy translation to/from equations/expressions with symbols. Example: align n+(((p-1)-(n+p-1))&(p-1)) = let ecx=[p], ecx-1, edx=[n], edx+ecx, eax=ecx, eax-edx, eax&ecx, ecx=eax, edx=[n], eax+edx * Easy conversion to/from HL languages Any questions? Ask. "My style is the best way for me personally and the best way that I know of currently but I'm always open-minded to the possibility that there is a better way" |
|||
04 Jan 2013, 14:28 |
|
< Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.