|
|
|||||||||
|
|||||||||
| |||||||||
|
|
|
| |||||||||
![]() |
|
|
«
Previous Thread
|
Next Thread
»
|
Thread Tools | Search this Thread | Rate Thread | Display Modes |
|
|
|
Stay one step ahead of the competition. Evaluate and give feedback
on some of the hottest web development tools on the market today.
Make your opinion heard! Click
Here
|
|
#1
|
|||
|
|||
|
Drawing a square
Hey guys. I'm DOS programming in 16-bit, using INT 10H.
So I know how to create a line, basically by drawing a pixel, and creating a loop to continue drawing pixels beside each other. But I don't know how to create a square. Does anybody have any ideas how I could create a square? I could create a procedure to repeat the code that draws a line, to produce a bunch of lines that are on top of each other, which would look like a square. I don't think this is the most efficient way, and could cause me more problems down the road as I try to move the square around the screen. Anyways, any help would be really appreciated. Thanks. Last edited by Treymac : April 1st, 2008 at 12:25 AM. Reason: typo |
|
#2
|
|||
|
|||
|
G'day.
That is how you do it, just be sure to use a function that only draws horizontal lines, as opposed to a generic line algo. The optimizations available depend on the language you're using and the screen mode you're in. If you're using mode 0x13h (320x200x256 cols) and doing it in assembly I've got some routines that are fairly speedy. Part of the trick is to write to the screen memory directly, and in a loop - as opposed to calling a Pixel function. as an (ashamedly, rather rough) example, to draw a square that's 4x4 in the top left corner of the screen, using color 10d: Code:
; To assemble and link from within WinAsm Studio, you must have a special 16-bit linker,
; such as the one in the archive at this URL- http://win32assembly.online.fr/files/Lnk563.exe
; Run the archive to unpack Link.exe, rename the Link.exe file to Link16.exe and copy it
; into the \masm32\bin folder.
;
; To produce a .COM file, .model must be tiny, also you must add /tiny to the linker command line
.model tiny
.data
.code
.startup
mov ax, 013h ; SetVidMode(0x13)
int 010h
mov ax, 0A000h ;segment of screen mem for this mode (and some others)
mov ds, ax
xor si, si ; point to pixel 0,0
mov ax, 0A0Ah ; 10d, 10d
mov cx, 4 ; want to do a 4 pixel side-length square
mov bx, 2 ; doing two pixels at once, need to move SI forwards by 2 each time
lineloop:
mov ds:[si], ax
add si, bx
mov ds:[si], ax ; look ma! two pixels at once (we can do more)
add si, 318
dec cx ; decrement our loop counter
jnz lineloop ; and go back for more, while loop counter <> 0
mov ah,0 ; getch()
int 16h
mov ax, 03h ; SetVidMode(0x03)
int 010h
.exit
end
Another tip worth pointing out is that bit-shift operations were quicker than multiply instructions last time I looked. So, assuming you were using mode 13h, if you wanted to draw a pixel at 10,30 using C you'd simply have a pointer that pointed to screen memory, and just use it like any other array Screen[30*200 + 10] = colour; But there's a quicker way than 30*200. It's 30*8 + 30*64 + 30*128. Now, while that may seem like a contradiction, 8, 64 and 128 are all powers of 2, so you can use the bit shift operations to calculate them. e.g offset = 30<<3 + 30<<6 + 30<<7; [EDIT] should have been: offset = (30<<3 + 30<<6 + 30<<7) + 10; [/EDIT] For clarity's sake I've done the full shift each time, but using the registers, you can simply accumulate the previous result. This is also unoptimized, for clarity's sake. e.g Code:
mov ax, 30 ; we want to draw on line 30 shl ax, 3 ; ax = 8*30 mov bx, ax ; bx = 8*30 shl ax, 3 ; ax = 64*30 add bx, ax ; bx = 8*30 + 64*30 shl ax, 1 ; ax = 128*30 add bx, ax ; bx = 8*30 + 64*30 + 128*30 mov si, bx ; si = 8*30 + 64*30 + 128*30 ----> 200 * 30 [EDIT - I forgot] mov ax, 10 add si, ax [/EDIT] It's more instructions than a simple MUL, but with pipelining taken into account you can run several of them per clock cycle. When I was last playing with ASM (486 era) A mul took many more cycles than that little snippet. Once you've got your index into the array that's screen memory, all you have to do is write a byte to ds:[si], then increment si to point at the next pixel. MUCH quicker than going through the whole operation of calculating an offset for each pixel. Last edited by SimonB2 : April 25th, 2008 at 05:33 AM. Reason: missed a couple of instructions |
![]() |
| Viewing: Dev Shed Forums > Programming Languages - More > Other Programming Languages > Drawing a square |
| Thread Tools | Search this Thread |
| Display Modes | Rate This Thread |
|
|
|
|