Jump to content

  • Log In with Google      Sign In   
  • Create Account

We're offering banner ads on our site from just $5!

1. Details HERE. 2. GDNet+ Subscriptions HERE. 3. Ad upload HERE.


Vector graphics programming under Dos


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
15 replies to this topic

#1 Zoltar26   Members   -  Reputation: 103

Like
0Likes
Like

Posted 31 August 2011 - 04:57 AM

Hi,

I'm interested in developing a 2d platform game under Dos operating system with vector graphics not bitmap (pixel).
There were several games back in the days with such graphics like "Another World", "Prince of Persia" and etc.
I'm programming with C language under Windows 3.11 with Visual Studio 1.5 .
I don't know what are the C libraries or framework to implement such graphics and animation.
Any light on this topic would be appreciated.
Thanks in advance.

Sponsor:

#2 Ashalah   Members   -  Reputation: 113

Like
0Likes
Like

Posted 31 August 2011 - 05:13 AM

Why in all that is holy would you want to create DOS software in ... *checks calendar*... 21st century?
/edit: you can definitely make dos-look-alike games using modern technology

#3 Zoltar26   Members   -  Reputation: 103

Like
0Likes
Like

Posted 31 August 2011 - 05:28 AM

Why in all that is holy would you want to create DOS software in ... *checks calendar*... 21st century?


Well, i'm interested in gaining knowledge on some technical concepts in game programming but from the beginning.
Besides, there's the DosBox emulator so why not develope for Dos.
I believe that a good game is not only a fancy fancy graphics but rather a good idea and there are still
hobbiests for such games. call me an old schooler but this is me. like i said i'm after knowledge.

#4 szecs   Members   -  Reputation: 2185

Like
0Likes
Like

Posted 31 August 2011 - 06:24 AM

You can make the graphics as "fancy" as you want.

Anyhoo, what do you mean by "vector graphics"? What makes you think Prince of Persia has "vector graphics"? Because it is NOT vector graphics....
Asteroids IS vector graphics. Maybe you could clarify what you mean by "vector graphics".

Programming graphics for Windows or for emulator is lots of fun, especially if it either screws your desktop resolution (run directly in Windows) or it screws your mouse in the game (run inside DosBox)...

I was programming for Dos for several years (after 2004). My only excuse was that I couldn't code for Windows, which was a pretty week excuse IMHO.

Well, i'm interested in gaining knowledge on some technical concepts in game programming but from the beginning.


You can also do it with more ""modern"" operating systems, like with Windows. It's not any "higher level" programming-wise, if you're afraid of that.

#5 SuperVGA   Members   -  Reputation: 1118

Like
0Likes
Like

Posted 31 August 2011 - 06:29 AM

You can make the graphics as "fancy" as you want.

Anyhoo, what do you mean by "vector graphics"? What makes you think Prince of Persia has "vector graphics"? Because it is NOT vector graphics....
Asteroids IS vector graphics. Maybe you could clarify what you mean by "vector graphics".

Programming graphics for Windows or for emulator is lots of fun, especially if it either screws your desktop resolution (run directly in Windows) or it screws your mouse in the game (run inside DosBox)...

I was programming for Dos for several years (after 2004). My only excuse was that I couldn't code for Windows, which is a pretty week excuse IMHO.

The animations of the lead character in POP, AW/OOTW and FB are all very smooth... I'm not sure about POP,
but the OOTW character animations could have been made with vector transformations. Notice the characters here:
Posted Image



#6 Ashalah   Members   -  Reputation: 113

Like
0Likes
Like

Posted 31 August 2011 - 06:30 AM

That's nice but you can do all those oldie-like games without being stuck in 16 bits and 4MB of RAM. Might as well be using punch cards ...
I started a Commander Keen remake in XNA a few years ago but got sidetracked on other stuff.

#7 undead   Members   -  Reputation: 320

Like
1Likes
Like

Posted 31 August 2011 - 06:33 AM

Hi,

I'm interested in developing a 2d platform game under Dos operating system with vector graphics not bitmap (pixel).
There were several games back in the days with such graphics like "Another World", "Prince of Persia" and etc.
I'm programming with C language under Windows 3.11 with Visual Studio 1.5 .
I don't know what are the C libraries or framework to implement such graphics and animation.
Any light on this topic would be appreciated.
Thanks in advance.

I'll try not to write a long reply but there's a lot of stuff to consider so I'm sorry if I'll get tedious.

NOTE: I ASSUME YOU WANT TO DO THINGS THE OLD WAY, MEANING THE DOS EMULATOR WILL RUN AT ORGINAL 386/486/PENTIUM CLOCK SPEED.
If you want to use the power of a modern CPU to do things the old way then what I am going to write won't be accurate, performance-wise.


From my pov the toolchain is your first problem. Back at that time none would ever use visual studio to develop a game/demo.

So first question you have to answer is: do I want to setup a toolchain for a game as old as prince of persia or for something as old as doom?
The point being older games were written in real mode and I suggest getting a copy of Borland Turbo C/C++, version 3.0.
Games like doom were written in protected mode with the much more modern watcom compiler.

I remember when I switched from Turbo C 3.0 I started using watcom 10.5 and 11 and except for some linking bug it was ok.

http://en.wikipedia.org/wiki/Turbo_C
http://en.wikipedia.org/wiki/Watcom_C/C%2B%2B_compiler

In brief the difference between real mode and protected mode is:
- real mode can make you access pages via a segment/offset, each offset being exactly 64kb (dos is a 16-bit OS, remember). You are limited to this kind of addressing because that's the way a x86 CPU used to work in 16-bit... real mode addressing in assembly is just ds:si cs:ip ss:sp etc.
- protected mode allows you to create bigger pages, overcoming the 64kb limitation effectively creating pages up to 4GB (actually protected mode is an extension giving you the power of 32-bit CPUs inside a host 16-bit OS like DOS). And here of course the assembly addressing takes advantage of 32-bit indices, esi eip esp etc.

The extender sold with watcom compilers was DOS4GW, a de facto standard at that time for games.
http://en.wikipedia.org/wiki/DOS4GW

The only alternative I know about (and used) was PMODEW, very popular in the demoscene because of its reduced size making it the only viable solution for a scener.
http://en.wikipedia.org/wiki/PMODE

As weird as it sounds, given those alternatives, you have to decide first which resolution you want to target. Three options here
- Standard VGA 320x200 8bit single buffer
- Custom modex VGA 256x256/320x200/320x240/etc 8bit double/triple buffer
- Standard multires VESA up to 24bit

If you plan to use VESA then the only solution is protected mode as any decent VESA resolution goes beyond 64kb so when rendering you have to change the segment. And since 64kb = 65536 bytes switching will occur in the middle of a line. Not easy and not fast.
If you plan to use standard VGA things are simple (320*200 = 64000 less than 64kb) but remember there's only one buffer so you have to synch to your monitor vertical retrace and be very careful about performance because framerate will instantly drop by half everytime you break a performance barrier unless you consider tearing acceptable.
As for modex it's a very tricky way to configure a video card using all 256kb available on standard VGAs and supporting hardware scrolling or double buffering. This was very popular... probably one of the first games using it was epic pinball (epic... yes the guys of unreal engine 3). Even in this case you might need protected mode but the problem with this system is on some resolutions bytes aren't addressed sequentially.
For four buffer that would mean:
byte 0 maps to pixel 0 buffer 0
byte 1 maps to pixel 0 buffer 1
byte 2 maps to pixel 0 buffer 2
byte 3 maps to pixel 0 buffer 3
byte 4 maps to pixel 1 buffer 0

http://en.wikipedia.org/wiki/Mode_X

Also get prepared to do some assembly work... I worked with tasm (turbo assembler) and wasm (watcom assembler) hated masm (microsoft assembler).
I suggest giving a try to NASM if you want to start writing stuff on a standard VGA resolution quick.

http://www.nasm.us/

As a final note to writing to video memory on a VGA using asm in DOS is very simple.

;setup the video mode, saving 13h as a parameter in ax register and call the video mode switch interrupt service (10h)
mov ax,13h
int 10h

;make es segment point at video memory
mov ax,0xa000h
mov es,ax

;reset the offset inside video memory using xor (saves 1 or 2 bytes)
xor di,di

So now you can write or read to video memory. If you want to fill the screen with a color all you need is this

mov al,colornum
mov cx,64000
rep stosb

rep repeats stosb as many times as specified in cx (64000 = 320x200)
stosb copies the content of al (your 8-bit color) into es:di (your video pointer) and adds 1 to di after copy.

Just remember colornum must be in the range 0..255 and the video mode is palettized so the default color list is fixed (you can find the default VGA palette here http://en.wikipedia.org/wiki/File:VGA_palette_with_black_borders.svg ). Palette can be changed via interupts or (better) outptting data to ports.

Hope this was helpful for a start. :)

#8 szecs   Members   -  Reputation: 2185

Like
0Likes
Like

Posted 31 August 2011 - 06:59 AM


You can make the graphics as "fancy" as you want.

Anyhoo, what do you mean by "vector graphics"? What makes you think Prince of Persia has "vector graphics"? Because it is NOT vector graphics....
Asteroids IS vector graphics. Maybe you could clarify what you mean by "vector graphics".

Programming graphics for Windows or for emulator is lots of fun, especially if it either screws your desktop resolution (run directly in Windows) or it screws your mouse in the game (run inside DosBox)...

I was programming for Dos for several years (after 2004). My only excuse was that I couldn't code for Windows, which is a pretty week excuse IMHO.

The animations of the lead character in POP, AW/OOTW and FB are all very smooth... I'm not sure about POP,
but the OOTW character animations could have been made with vector transformations. Notice the characters here:
Posted Image



The animations of the main character in POP are not that smooth. It seems to be smooth and life-like, because the sprites where drawn using real videos of a guy doing those moves.

(AFAIK)

#9 SuperVGA   Members   -  Reputation: 1118

Like
0Likes
Like

Posted 31 August 2011 - 07:12 AM



Anyhoo, what do you mean by "vector graphics"? What makes you think Prince of Persia has "vector graphics"? Because it is NOT vector graphics....

The animations of the lead character in POP, AW/OOTW and FB are all very smooth... I'm not sure about POP,
but the OOTW character animations could have been made with vector transformations. Notice the characters here:

The animations of the main character in POP are not that smooth. It seems to be smooth and life-like, because the sprites where drawn using real videos of a guy doing those moves.
(AFAIK)

Yep, that's probably true. I read an interview on it some years ago, and now that you mention it, the interview explained sprites drawn from filmed movement.
-Also, it's easier to achieve "smooth" hand-drawn animations on lower resolutions. I just remembered the Quake animations,
and they always seemed pretty coarse...

#10 BigJim   Members   -  Reputation: 142

Like
0Likes
Like

Posted 31 August 2011 - 07:55 AM

Back in the day I had this book:

http://www.droberts.com/pcgpex/pcgpex.htm

If you can find a copy, it supplies a basic library for modeX/Y/13H stuff for use with Borland C++ 3/4ish (which is probably a reasonable choice cos at least you can run the IDE on window!)

#11 pulpfist   Members   -  Reputation: 528

Like
0Likes
Like

Posted 31 August 2011 - 10:37 AM

I haven't done that in a few years now but I seem to remember the Borland C++ 3.1 compiler could simulate a dos environment on Windows 98 and earlier versions.
It doesn't matter much which compiler you use though, as long as it allows inline assembly you can easily get into Mode 13H with a couple of instructions.
Mode 13H is a 320x200 graphic mode which should be a good place to start.
Google it for more info



#12 Zoltar26   Members   -  Reputation: 103

Like
0Likes
Like

Posted 31 August 2011 - 10:25 PM




Anyhoo, what do you mean by "vector graphics"? What makes you think Prince of Persia has "vector graphics"? Because it is NOT vector graphics....

The animations of the lead character in POP, AW/OOTW and FB are all very smooth... I'm not sure about POP,
but the OOTW character animations could have been made with vector transformations. Notice the characters here:

The animations of the main character in POP are not that smooth. It seems to be smooth and life-like, because the sprites where drawn using real videos of a guy doing those moves.
(AFAIK)

Yep, that's probably true. I read an interview on it some years ago, and now that you mention it, the interview explained sprites drawn from filmed movement.
-Also, it's easier to achieve "smooth" hand-drawn animations on lower resolutions. I just remembered the Quake animations,
and they always seemed pretty coarse...


This technic is called: Rotoscoping
Now, my question is how to achieve this graphics under Dos ?
do i need any special drawing / animation software for Dos and does it require any special routines in C language ?

#13 szecs   Members   -  Reputation: 2185

Like
0Likes
Like

Posted 01 September 2011 - 12:09 AM

In Dos, you can use standard libraries and drivers (egavga.bgi for example). Usually there's a "graphics.h" with your IDE/compiler (Borland C++ for example), there are a lot of drawing routines in that. Like lines, rectangles, polygons, circles, text drawing etc. These routines are the interfaces for the device driver (clarification needed).

Ant the beginning of the program, you have to initialize the device driver, set the display mode (resolution for example), that's usually a few lines of specific code (by calling routines from graphics.h). Then you simply call the appropriate draw routines, which immediately draw the stuff on the screen (at least in mode 13h and 256 indexed color modes).

I don't know about true color or any other RGB color modes, I could only set up indexed color modes, and cannot, for the life set up RGB modes (or whatever the hell the proper terms/names are).

#14 undead   Members   -  Reputation: 320

Like
0Likes
Like

Posted 01 September 2011 - 02:55 AM

In Dos, you can use standard libraries and drivers (egavga.bgi for example). Usually there's a "graphics.h" with your IDE/compiler (Borland C++ for example), there are a lot of drawing routines in that. Like lines, rectangles, polygons, circles, text drawing etc. These routines are the interfaces for the device driver (clarification needed).

In DOS there was nothing like a device driver, all video cards just had to comply to the VGA standard. You submit commands using interrupts, ports and pointers... and nothing else. I remember I had a tseng labs et-4000 with special features and it was just a matter of outputting to the proper ports.

Those libraries were very very slow and as far as I can remember drawing a sprite on a 386 was already a pain.

Ant the beginning of the program, you have to initialize the device driver, set the display mode (resolution for example), that's usually a few lines of specific code (by calling routines from graphics.h). Then you simply call the appropriate draw routines, which immediately draw the stuff on the screen (at least in mode 13h and 256 indexed color modes).

I wouldn't draw onscreen, that would result in a lot of tearing (no backbuffer).

Since the OP wants to use C/C++, I suggest starting with something like this:
1- Create a backbuffer the dirty way.
unsigned char m_aBackBuffer[64000];
2- Write a routine getting a pointer to it.
unsigned char * GetBackBuffer()
{
return &m_aBackBuffer[0];
}
3- write a set of common functions for clearing/copying the backbuffer, inlining asm via the _asm directive (best solution write all low level routines into an external assembly file). Never never never use memset or memcpy. When copying or cleaning always use the fastest cpu instruction available (movsd/stosd operating on DWORDs).
4- if your game has a background, store the main background in another buffer and use your lowlevel copy function to do two jobs with one call: clear the backbuffer while drawing the background.
5- Since it's a platform game, write a low level routine to copy platforms (non transparent elements). The trick is to use movsd for an entire platform line, then skip to the following line in backbuffer adding (screenxresolution-platformxsize), copy the following line and repeat for platformysize.
6- as for sprites the problem is transparency which is a performance killer. Basicly you can't take advantage of movsd because it copies 4 pixels, so you have to manually check every pixel. Even reading a pixel from a sprite, check transparency and then decide if writing it or skipping it is a performance killer on a 286/386. So how did they manage to do something like prince of persia? Since none of the two games had scrolling my guess is they use one of the following techniques (or maybe both):
1- update only the rectangular portion of the screen that changed since the last frame, saving bandwith.
2- take advantage of compiled sprites, that is... compile your sprites into code.

More details about compiling sprites here:

http://www.nondot.or...ro/sprite4.html

The part about jack jazzrabbit, one of the first games released by epic megagames, is very enlighting about how things were done back at the time.

look at the game "Jazz the Jackrabbit" published by Epic Software. It uses compiled sprites exclusively for the background tiles and the characters in it. If you have played it, you may have noticed a number of lens effects. This is because the sprites are not simple compiled bitmaps, they read the data already on the screen and rearrange it to apear like a lens is sitting on it. Other applications are endless.

If I'm allowed to say that, Tim Sweeney was already kicking a***s around!

#15 szecs   Members   -  Reputation: 2185

Like
0Likes
Like

Posted 01 September 2011 - 03:34 AM

Then what is egavga.bgi? And all the other BGI? Sure, you can rewrite everything from scratch using only interrups and inline assembly code and no standard library stuff at all.

But the OP was asking for libraries, as far as I can remember.....

#16 undead   Members   -  Reputation: 320

Like
0Likes
Like

Posted 01 September 2011 - 04:58 AM

Then what is egavga.bgi? And all the other BGI? Sure, you can rewrite everything from scratch using only interrups and inline assembly code and no standard library stuff at all.

But the OP was asking for libraries, as far as I can remember.....

Egavga.bgi is a graphics library from borland. As far as I can remember it has no support for sprites or anything even remotely related to game programming.

http://www.cs.colora.../~main/bgi/doc/

From what I see except functions for windows (marked with WIN) there's only one function to output an image on screen: putimage
Putimage doesn't support transparency so you have to use putpixel and that is a performance killer.

I assume we are talking about DOS programming on a DOS emulator for a target machine whose clock speed is between 25 and 66Mhz. If a 1Ghz CPU is required to run a DOS game then there's something I'm clearly missing. Also there's a grey area between writing the most inefficient code possible and writing code running as fast as tim sweeney's one.

Honestly I can't see so much difference between calling:

color = getpixel(xsprite,ysprite)
if( color != TRANSP_COLOR )
putpixel(x,y,color);

and:

color = m_aMSprite[ysprite*SPRITE_WIDTH+xsprite] ;
if( color != TRANSP_COLOR )
m_aBackBuffer[y*320+x] = color;

Or even better calculate starting pixels outside a double for loop this way:

pBackBuffer = &m_aBackBuffer[y*320+x];
pSprite = &m_aMSprite[ysprite*SPRITE_WIDTH+xsprite] ;

and inside the two for loops:

if( *pSprite != TRANSP_COLOR)
*pBackBuffer = color;
pBackBuffer++;
pSprite++;


Even if these are just four lines of code it is likely on a 386 they run a lot faster. Because function calls are killers when it comes down to realtime graphics on a 386 using an old C/C++ compiler.

Let me do the math on an extreme case: you copying a full screen buffer on screen using putpixel or stosw (I don't have stosd timing on my 386 manual but I assume it's the same). Just to make it clear how slow those machines were when it comes down to function calls.

A simple pair of PUSHA/POPA (needed to preserve registers for a function call) takes a lot of cycles.

I have an old 286/386 manual referencing clock cycles needed for each x86 op:

PUSHA 18 cycles
POPA 24 cycles
MOV takes between 2 and 22 cycles.

So every function call has to push and pop all general registers and make 2 movs to read and write the pixel color.
18+24+2+2 = 46 cycles per pixel.
And you'll surely need other 2 movs to configure es and ds and other 2 for di and si.
If we assume MOV takes 2 cycles (which is NOT always the case) then it's 54 cycles per pixel.
And you have a function call (CALL) taking 3-275 clock cycles and a return instruction (RET) taking 10-68 clock cycles!!!!!!!!!!!!!!
Suppose everything is superfast, so let's add just 13 cycles. I'm not even counting the for loop.

64000*67 = 4288000

Best case: more than four million cycles. That means on a 25Mhz 80386 CPU, performing 25 million cycles per second, there's no way you can get more than 5-6FPS just for copying a background if you use borland's putpixel. Extreme case, I know.

On the other hand with stosw you copy two pixels at a time so it's 32000 stosw operations for a 320x200 screen.

Configure es and ds, si and di = same 8 cycles (4 MOVs) but you do it once.
MOV cx, 32000 other 2 cycles we are at 10 cycles for configuring our copy.
And now
rep stosw
stosw is 4 cycles on a 386, 3 cycles on a 286.
rep is 5 cycles for config and 9 cycles for each iteration.

So we end up with:

15 cycles for configuration
13 cycles every 2 pixels for 32000 times.

Total cycles = 32000*13+15 = 416015 cycles.

In performance that would mean:
putpixel = 5,83 FPS
asm = 60,09 FPS

Assuming stosd still takes 4 cycles (which might be the case as stosw and stosb take the same amount of clock cycles), we have 16000*13+15 = 208015

A stosd can copy the back buffer at a 120,2 FPS rate... 24x faster than any putpixel you can write, no matter how skilled you are, at the cost of inlining 10 lines of asm code!

Also, you get an extra bonus: with rep and stosd the timing is 100% predictable just the setup can vary from 13 to 500 clock cycles.
The same doesn't apply to mov, ret and call ops as you could end up spending up to 500-600 clock cycles for some pixels!!!!!

The reason why libraries weren't so popular is the CPU was so slow you had to do it yourself everytime as even the cost of calling a function many times on a 386 is too high for a realtime application.

I think trying to do proper DOS programming in 21st century is worthy exactly for this reason: doing things the old school way people can learn programming with a different mindset.

:)




Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS