flat assembler
Message board for the users of flat assembler.
Index
> DOS > Simple sprite editor |
Author |
|
lutetia 15 Dec 2012, 20:17
This is my first dos program in fasm. Source might be useful to someone.
It's pixel editor in 320x200 video mode. You can make sprites from 3x3 to 40x40 in size and save it. Runs fine on all windows xp machines that I tried. More info in readme.txt
Last edited by lutetia on 28 Jan 2013, 13:48; edited 3 times in total |
|||||||||||
15 Dec 2012, 20:17 |
|
HaHaAnonymous 15 Dec 2012, 20:19
[ Post removed by author. ]
Last edited by HaHaAnonymous on 28 Feb 2015, 22:11; edited 1 time in total |
|||
15 Dec 2012, 20:19 |
|
DOS386 16 Dec 2012, 12:26
> This is my first dos program in fasm
Welcome and COOL, it does something (see shot) BUG's: * filenames are too long * doesn't restore screen at exit * your graphics files should not have an extension ".TXT" as they are not text, maybe ".LSE" instead, and even better hold a Sigi like "!LSE!",0,$FF,$1A (why???) * besides your private file format, you could support some of existing (bad) formats like (a subset of) BMP * the binary is bloated - buffers should be outside * absurdly high numbers (see shot) - uninitialized var's ? * size is obscure/invisible - how is it supposed to work ? * binary depends from some ".TXT" files and doesn't whine if they are not found - better include the data into the binary * you call both BIOS and DOS to write onto the graphics screen - better parse the font yourself * no way to exit by keypress (for example <ALT>-<X>) EDIT : deleted obsolete bugshot _________________ Bug Nr.: 12345 Title: Hello World program compiles to 100 KB !!! Status: Closed: NOT a Bug Last edited by DOS386 on 17 Dec 2012, 06:17; edited 1 time in total |
|||
16 Dec 2012, 12:26 |
|
DOS386 17 Dec 2012, 03:58
lutetia wrote: .asm and .inc file names have to be dos style not more than 8 symbols long? This would be cool in DOS stuff. > absurdly high numbers probably are from me assuming that > eax register initially is zero. Since I deal with ax only and then > output numbers on the screen that are in eax easy to fix > "buffers should be outside". Do you mean instead of: > buffer1 db 1600d > i should do something different? 1. Use always "rb" and never "db" for buffers (writable locations), at program start, clear them all, and then set non-ZERO values (like the two "40") 2. Put all rb's at program end rather than in the middle, that way, they will not bloat the binary (see HEX dump of your COM binary) seems you updated the attach (untested) |
|||
17 Dec 2012, 03:58 |
|
lutetia 17 Dec 2012, 04:56
I'll keep updating it.
Added program exit on escape key press. Fixed program exit code. Changed graphics file extensions to .lse Added binary dependent files missing at loading time error message. Hopefully those high numbers are fixed too. Fixed names. I didn't know that rb at the end of file won't bloat the binary, thank you. So memory location defined as Code: xCoord DB 40d Code: MOV [xCoord], 39d |
|||
17 Dec 2012, 04:56 |
|
DOS386 17 Dec 2012, 05:22
lutetia wrote: I'll keep updating it. COOL ... COOL ... COOL ... COOL ... COOL Quote: So memory location defined as You can overwrite it and it will work ... and you will find much old (MASM) code doing that way ... but it's a bad habit for multiple reasons: 1. it (usually) doesn't work in protected mode 2. you risk corrupting your code rather than "only" corrupting your data - harder to debug ... Code: ... ret ;---- xcoord: db 40 ycoord: db 40 procblah: push ax ... MOV al, 39 MOV [yCoord], al ; OK ... MOV [yCoord], ax ; !!! BUG !!! > I didn't know that rb at the end of file won't bloat the binary, thank you Make sure to "manually" clear all those buffers then (REP STOSW). _________________ Bug Nr.: 12345 Title: Hello World program compiles to 100 KB !!! Status: Closed: NOT a Bug |
|||
17 Dec 2012, 05:22 |
|
DOS386 17 Dec 2012, 06:26
Seems most BUG's are gone |
|||
17 Dec 2012, 06:26 |
|
Picnic 18 Dec 2012, 10:34
My objection is about the file format, i mean i can't use the creations elsewhere outside the editor. BMP support would be useful.
Nevertheless is a fine program lutetia. |
|||
18 Dec 2012, 10:34 |
|
AsmGuru62 18 Dec 2012, 15:50
I miss those sprite games from DOS...
|
|||
18 Dec 2012, 15:50 |
|
uart777 19 Dec 2012, 04:35
Excellent work, lutetia!
Just one question: Why did you choose DOS? Do you not have good Windows code? Or are you an old-school 90s programmer? You can draw directly to linear memory VGA/buffer (vga[x]=COLOR) then copy it to primary display using BitBlt/StretchBlt. Something like this: Code: macro os.define.vga { if OS='w' HBITMAP vga.hbm BITMAPINFO vga.bmi RECT vga.rect end if } function os.create.vga, w, h if OS='w' try [vga.hbm]=CreateBitmap \ [screen.w], [screen.h], 32, 1, [vga] calla !memory.zero, vga.bmi.h, BITMAPINFOHEADER.$ let [vga.bmi.h.biSize]=BITMAPINFOHEADER.$,\ [vga.bmi.h.biWidth]=[os.w],\ eax=[os.h], neg eax,\ [vga.bmi.h.biHeight]=eax,\ [vga.bmi.h.biBitCount]=32,\ [vga.bmi.h.biPlanes]=1 ShowCursor 0 end if endf function os.show.vga if OS='w' SetDIBits [_dc], [vga.hbm], 0, [screen.h],\ [vga], vga.bmi, 0 draw.bitmap.w [vga.hbm], 0, 0, [os.w], [os.h] let [vga.rect.left]=0, [vga.rect.top]=0,\ [vga.rect.right]=[os.w], [vga.rect.bottom]=[os.h] InvalidateRect [_hwnd], vga.rect, 0 end if endf I agree with Picnic, it should support a standard format (ie, .BMP) and that's very easy to do (ASM is easy, life is HARD!): Code: ; $$$$$$$$$$$$$$ Z77 ASM LIBRARY $$$$$$$$$$$$$$$$$ ; ************** SUNGOD SOFTWARE ***************** ; ?????????????????? BMP.INC ????????????????????? bmp.header db 54 dup(0) bmp.sign equ word [bmp.header] bmp.file.size equ dword [bmp.header+2] bmp.offset equ dword [bmp.header+10] bmp.fourty equ dword [bmp.header+14] ; 40 bmp.w equ dword [bmp.header+18] bmp.h equ dword [bmp.header+22] bmp.n.planes equ word [bmp.header+26] ; 1 bmp.bpp equ word [bmp.header+28] bmp.compress equ dword [bmp.header+30] bmp.image.size equ dword [bmp.header+34] bmp.n.colors equ dword [bmp.header+46] TEXT bmp.ext='.BMP' ; load 8*/24/32BPP .BMP to 32BPP image. ; if success, return allocated image address ; in eax and w/h in ecx/edx. return 0 if error. ; (* 8BPP has not been fully tested) function load.bmp, file locals image, p, x, y, w, h,\ bpp, n, size, row, a, wb,\ palette, n.colors, palette.size let [image]=0,\ [p]=[?t], [palette]=0 text.copy [p], [file] change.ext \ [p], bmp.ext open [p] ; open and read header fail .error read bmp.header, 54 cmp bmp.sign, 'BM' ; verify signature jne .error let ecx=bmp.w,\ ; dimensions edx=bmp.h,\ [w]=ecx, [h]=edx,\ ecx*edx, [n]=ecx,\ ; # pixels ecx<<2, [size]=ecx ; size in bytes in memory movsx ecx, bmp.bpp ; BPP let [bpp]=ecx, eax=[w] .if ecx=32 ; width in bytes in file let eax<<2 .else.if ecx=24 let eax*3 .else.if ecx=8 ; w=w .else ; not supported yet jmp .error .end .if eax&3 align.n eax, 4 let [a]=ecx .else let [a]=0 .end get [image]=\ allocate [size] ; allocate image pointer fail .error .if [bpp]<=8 ; create/load palette? let eax=1,\ ecx=[bpp], eax<<cl,\ [n.colors]=eax,\ eax<<2,\ [palette.size]=eax get [palette]=\ allocate [palette.size] let [p]=[palette] .loop [x]=0 to [n.colors] read [p], 4 add [p], 4 .endl .end .loop [y]=0 to [h] let ecx=[h],\ ; row=h-y-1 (upside down) ecx-[y], ecx-1,\ [row]=ecx, ecx*[w],\ ecx<<2,\ ; ecx=row*w*4 eax=[image],\ ; line address = eax+ecx, [p]=eax ; &(image+(h-y-1)*w*4) .loop [x]=0 to [w] .if [bpp]=32 ; 32BPP read [p], 4 .else.if [bpp]=24 ; 24BPP let eax=[p],\ dword [eax]=0 read [p], 3 ; read BGR24 as RGB24 .else.if [bpp]=8 ; 8BPP read.c ; read palette+index*4 let eax<<2,\ eax+[palette],\ edx=[p],\ ecx=[eax],\ [edx]=ecx .end add [p], 4 ; advance pointer .endl .if [a] ; skip alignment after seek.r [a], YES .end .endl destroy [palette] close let eax=[image],\ ; return image ecx=[w], edx=[h] ; and w/h in ecx/edx escape .error: close let eax=0 endf ; save .BMP. "image" is pixel array function save.bmp, file, image, w, h, bpp locals p, x, y, row, a, n, wb, size let [p]=[?t] text.copy [p], [file] change.ext [p], bmp.ext create [p] fail .error let ecx=[bpp], eax=[w] .if ecx=32 ; width in bytes in file let eax<<2 .else.if ecx=24 let eax*3 .else.if ecx=8 ; w=w .end .if eax&3 align.n eax, 4 let [a]=ecx .else let [a]=0 .end let [wb]=eax,\ eax*[h], [size]=eax memory.zero bmp.header, 54 let \ bmp.sign='BM',\ ecx=[w], bmp.w=ecx,\ ecx=[h], bmp.h=ecx,\ ecx=[bpp], bmp.bpp=cx,\ bmp.offset=54,\ bmp.fourty=40,\ bmp.n.planes=1,\ ecx=[size],\ bmp.image.size=ecx write bmp.header, 54 let eax=[image],\ [p]=eax ; write image pixels... .loop [y]=0 to [h] let ecx=[h],\ ecx-[y], ecx-1,\ ; row=h-y-1 (upside down) [row]=ecx,\ ecx*[w], ecx<<2,\ ; line address = eax=[image],\ ; &(image+(h-y-1)*w*4) eax+ecx, [p]=eax .loop [x]=0 to [w] ; write pixels .if [bpp]=24 write [p], 3 .else.if [bpp]=32 write [p], 4 .end add [p], 4 ; advance pointer .endl .loop [n]=0 to [a] ; skip alignment after write.c 0 .endl .endl close let eax=1 jmp @f .error: close let eax=0 @@: endf Guru: Me too Love the old-school games, especially Commodore64 International Karate. Anyone remember this? Me and my dad - who was an electronics engineer who specialized in robotics - used to play the thinking games like 7th guest and 11th hour. lutetia: Thanks for sharing |
|||
19 Dec 2012, 04:35 |
|
DOS386 20 Dec 2012, 02:35
Code: ; load 8*/24/32BPP .BMP to 32BPP image. ; if success, return allocated image address ; in eax and w/h in ecx/edx. return 0 if error. ; (* 8BPP has not been fully tested) The code runs in 8 bpp mode so far: http://wiki.multimedia.cx/index.php?title=BMP Note that BMP always (?) stores lines from bottom to the top. |
|||
20 Dec 2012, 02:35 |
|
lutetia 20 Dec 2012, 18:54
uart777 wrote:
DOS looks easier. Eventually I'd like to graduate in windows. Thank you for these examples. |
|||
20 Dec 2012, 18:54 |
|
baldr 21 Dec 2012, 05:43
DOS386 wrote: Note that BMP always (?) stores lines from bottom to the top. |
|||
21 Dec 2012, 05:43 |
|
uart777 27 Dec 2012, 00:16
Quote: DOS looks easier. Eventually I'd like to graduate in windows. Mode 13h is a good place to start. Ultimately, you may decide to move onto VESA for high color/resolution. In art programs, 8BPP is not enough colors to represent the VGA and all images (unless all palette registers are grayscale or intensities of one color). High/true color (15/16/24) is required for image effects (example, adjust lightness, hue, saturation, etc) and artistic brush styles (example, airbrush, textures, smear). All you need for drawing/animation is linear VGA, images and timer (in BIOS, A0000000h = VGA memory and 0000046Ch = 18.2 MHZ clock) and it's possible to simulate these in any OS. You can still write your own graphics and define portable custom controls - by drawing lines, rectangles, images and raster text - without using OS-specific code. IMAGE SIZE, MIRROR, ROTATE Code: ; size pixel array using "nearest neighbor" ; (accurate, interpolation is not) 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--, 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--, 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 ; rotate 'r'ight (90) or 'l'eft (270) function rotate.image, image, way locals x, y, w, h, p, s, col, row let eax=[image], [s]=[?image.p+eax],\ [w]=[?image.w+eax], [h]=[?image.h+eax] try [p]=scratch [h], [w] ; w/h reversed .if [way]='r' ; right, 90 let eax=[h], eax--, [col]=eax .loop [y]=0 to [h] .loop [x]=0 to [w] let eax=[x], eax*[h], eax+[col], eax<<2,\ eax+[p], edx=[y], edx*[w], edx+[x], edx<<2,\ edx+[s], [eax]=[edx] .endl let [col]-- .endl .else.if [way]='l' ; left, 270 let [col]=0 .loop [y]=0 to [h] let eax=[w], eax--, [row]=eax .loop [x]=0 to [w] let eax=[row], eax*[h], eax+[col], eax<<2,\ eax+[p], edx=[y], edx*[w], edx+[x], edx<<2,\ edx+[s], [eax]=[edx], [row]-- .endl let [col]++ .endl .end end.scratch [image] let eax=[image],\ ; adjust location edx=[?image.x+eax], ecx=[w], ecx>>1, edx+ecx,\ ecx=[h], ecx>>1, edx-ecx, [?image.x+eax]=edx,\ edx=[?image.y+eax], ecx=[h], ecx>>1, edx+ecx,\ ecx=[w], ecx>>1, edx-ecx, [?image.y+eax]=edx endf Ultimate HL features: http://board.flatassembler.net/topic.php?t=14768 lutetia: Wish there was a site for modern ASM graphics programmers. |
|||
27 Dec 2012, 00:16 |
|
lutetia 28 Jan 2013, 13:50
Added BMP support finally.
|
|||
28 Jan 2013, 13:50 |
|
< Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.