flat assembler
Message board for the users of flat assembler.

Index > DOS > Simple sprite editor

Author
Thread Post new topic Reply to topic
lutetia



Joined: 21 Oct 2012
Posts: 5
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


Description:
Download
Filename: sprite05.zip
Filesize: 19.89 KB
Downloaded: 818 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: 1178
Location: Unknown
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
Post 15 Dec 2012, 20:19
View user's profile Send private message Reply with quote
DOS386



Joined: 08 Dec 2006
Posts: 1900
DOS386 16 Dec 2012, 12:26
> 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
lutetia 17 Dec 2012, 00:51
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: 1900
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)
Post 17 Dec 2012, 03:58
View user's profile Send private message Reply with quote
lutetia



Joined: 21 Oct 2012
Posts: 5
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    
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: 1900
DOS386 17 Dec 2012, 05:22
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
  ;----

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



Joined: 08 Dec 2006
Posts: 1900
DOS386 17 Dec 2012, 06:26
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: 1389
Location: Piraeus, Greece
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.
Post 18 Dec 2012, 10:34
View user's profile Send private message Visit poster's website Reply with quote
AsmGuru62



Joined: 28 Jan 2004
Posts: 1619
Location: Toronto, Canada
AsmGuru62 18 Dec 2012, 15:50
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
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? 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.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 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: 1900
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.
Post 20 Dec 2012, 02:35
View user's profile Send private message Reply with quote
lutetia



Joined: 21 Oct 2012
Posts: 5
lutetia 20 Dec 2012, 18:54
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
baldr 21 Dec 2012, 05:43
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
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.
Post 27 Dec 2012, 00:16
View user's profile Send private message Reply with quote
lutetia



Joined: 21 Oct 2012
Posts: 5
lutetia 28 Jan 2013, 13:50
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


Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.