flat assembler
Message board for the users of flat assembler.
 Home   FAQ   Search   Register 
 Profile   Log in to check your private messages   Log in 
flat assembler > DOS > Simple sprite editor

Author
Thread Post new topic Reply to topic
lutetia



Joined: 21 Oct 2012
Posts: 5

Simple sprite editor

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


Description:
Download
Filename: sprite05.zip
Filesize: 19.89 KB
Downloaded: 158 Time(s)



Last edited by lutetia on 28 Jan 2013, 13:48; edited 3 times in total
Post 15 Dec 2012, 20:17
View user's profile Send private message Reply with quote
HaHaAnonymous



Joined: 02 Dec 2012
Posts: 1171
Location: Unknown

Stupid post removed.


Last edited by HaHaAnonymous on 28 Feb 2015, 22:11; edited 1 time in total
Post 15 Dec 2012, 20:19
View user's profile Send private message Reply with quote
DOS386



Joined: 08 Dec 2006
Posts: 1904

> This is my first dos program in fasm

Welcome and COOL, it does something (see shot) Smile

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
Post 16 Dec 2012, 12:26
View user's profile Send private message Reply with quote
lutetia



Joined: 21 Oct 2012
Posts: 5

Thank you for your guidance.
*So does .asm and .inc file names have to be dos style not more than 8 symbols long?
*Those 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.
*"buffers should be outside". Do you mean instead of:
buffer1 db 1600d
i should do something different?
Post 17 Dec 2012, 00:51
View user's profile Send private message Reply with quote
DOS386



Joined: 08 Dec 2006
Posts: 1904


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)
Post 17 Dec 2012, 03:58
View user's profile Send private message Reply with quote
lutetia



Joined: 21 Oct 2012
Posts: 5

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

is not meant to be overwritten? Lets say

Code:
MOV [xCoord], 39d

Post 17 Dec 2012, 04:56
View user's profile Send private message Reply with quote
DOS386



Joined: 08 Dec 2006
Posts: 1904


lutetia wrote:
I'll keep updating it.

...
...
...



COOL ... COOL ... COOL ... COOL ... COOL Smile


Quote:
So memory location defined as

Code:
xCoord DB 40d

is not meant to be overwritten? Lets say

Code:
MOV [xCoord], 39d




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
  ;----

xcoorddb 40
ycoorddb 40

procblahpush ax

...

  MOV al39
  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
Post 17 Dec 2012, 05:22
View user's profile Send private message Reply with quote
DOS386



Joined: 08 Dec 2006
Posts: 1904

Image

Seems most BUG's are gone Smile
Post 17 Dec 2012, 06:26
View user's profile Send private message Reply with quote
Picnic



Joined: 05 May 2007
Posts: 1230
Location: Underwater

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.
Post 18 Dec 2012, 10:34
View user's profile Send private message Reply with quote
AsmGuru62



Joined: 28 Jan 2004
Posts: 1388
Location: Toronto, Canada

I miss those sprite games from DOS...
Post 18 Dec 2012, 15:50
View user's profile Send private message Send e-mail Reply with quote
uart777



Joined: 17 Jan 2012
Posts: 369

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? Wink

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.vgawh
if OS='w'
 try [vga.hbm]=CreateBitmap \
  [screen.w], [screen.h], 321, [vga]
 calla !memory.zerovga.bmi.hBITMAPINFOHEADER.$
 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.bmi0
 draw.bitmap.w [vga.hbm], 00, [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.rect0
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.bmpfile
locals imagepxywh,\
bppnsizerowawb,\
paletten.colorspalette.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.header54
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 ecxbmp.bpp     ; BPP
let [bpp]=ecxeax=[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 eax4
  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]=ecxecx*[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.bmpfileimagewhbpp
locals pxyrowanwbsize
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 eax4
  let [a]=ecx
.else
  let [a]=0
.end
let [wb]=eax,\
eax*[h], [size]=eax
memory.zero bmp.header54
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.header54
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 Smile 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 Smile
Post 19 Dec 2012, 04:35
View user's profile Send private message Reply with quote
DOS386



Joined: 08 Dec 2006
Posts: 1904


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.
Post 20 Dec 2012, 02:35
View user's profile Send private message Reply with quote
lutetia



Joined: 21 Oct 2012
Posts: 5


uart777 wrote:


Just one question: Why did you choose DOS? Do you not have good Windows code? Or are you an old-school 90s programmer? Wink

You can draw directly to linear memory VGA/buffer (vga[x]=COLOR) then copy it to primary display using BitBlt/StretchBlt. Something like this:

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!):



DOS looks easier. Eventually I'd like to graduate in windows.
Thank you for these examples.
Post 20 Dec 2012, 18:54
View user's profile Send private message Reply with quote
baldr



Joined: 19 Mar 2008
Posts: 1651


DOS386 wrote:
Note that BMP always (?) stores lines from bottom to the top.

BITMAPINFOHEADER.biHeight < 0 indicates top-down bitmap (OS/2 legacy IIRC). Some restrictions apply (it can't be compressed, e.g.)
Post 21 Dec 2012, 05:43
View user's profile Send private message Reply with quote
uart777



Joined: 17 Jan 2012
Posts: 369


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.imageimagewh
locals ijpsx1y1w1h1x2y2
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<<16eax/[w], [x1]=eax,\
 eax=[h1], eax<<16eax/[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<<2ecx+[s], [eax]=[ecx; *p=*s
  .endl
.endl
end.scratch [image]
endf

; size by percentage (integer)

function size.image.pimagep
locals whiwih
let eax=[image],\
 [iw]=[?image.w+eax], [ih]=[?image.h+eax],\
 eax=[iw], eax*[p], ecx=100eax/ecx, [w]=eax,\
 eax=[ih], eax*[p], ecx=100eax/ecx, [h]=eax
size.image [image], [w], [h]
endf

; mirror; flip 'h'orizontal, 'v'ertical
; or 'd'iagonal

function mirror.image.himage
locals xywhps
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+ecxedx<<2edx+[s],\
    eax=[x], eax+ecxeax<<2eax+[p],\
    [eax]=[edx]
  .endl
.endl
end.scratch [image]
endf

function mirror.image.vimage
locals xywhps
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<<2edx+[s], eax=[y], eax*[w],\
  eax<<2eax+[p], ecx=[w], ecx<<2
  memory.copy eaxedxecx
.endl
end.scratch [image]
endf

function mirror.imageimageway
.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.imageimageway
locals xywhpscolrow
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>>1edx+ecx,\
 ecx=[h], ecx>>1edx-ecx, [?image.x+eax]=edx,\
 edx=[?image.y+eax], ecx=[h], ecx>>1edx+ecx,\
 ecx=[w], ecx>>1edx-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.
Post 27 Dec 2012, 00:16
View user's profile Send private message Reply with quote
lutetia



Joined: 21 Oct 2012
Posts: 5

Added BMP support finally.
Post 28 Jan 2013, 13:50
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >

Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Main index   Download   Documentation   Examples   Message board
Copyright © 2004-2018, Tomasz Grysztar.
Powered by rwasa.