Please Help me!!!!

Discuss coding, porting and creating games
Post Reply
kika
Less than a nibble
Posts: 1
Joined: September 4th, 2009, 4:04 am

Please Help me!!!!

Post by kika »

Now, I use turbo C++ and Dosbox.
However, I want to uses graphics.h, how can I use 256 color in setcolor().
Gadien
Less than a nibble
Posts: 1
Joined: November 18th, 2009, 1:12 am

Re: Please Help me!!!!

Post by Gadien »

Wish I could help you buddy. I'm more trying to learn how to program in C
User avatar
deathshadow
Classic Game Author
Posts: 35
Joined: February 8th, 2011, 5:42 pm

Re: Please Help me!!!!

Post by deathshadow »

graphics.h much like Turbo Pascal's graph unit uses BGI drivers, which to my knowledge didn't come with support for the VGA's 320x200x256 mode... There are some attempts at making them, but the BGI is notoriously slow and not really suited for doing anything serious in a graphics mode (which is why few if any games EVER used it).

If you want to program that mode seriously, I suggest writing your own routines to handle it. INT $10 to set the mode, video memory is byte per pixel in that mode at $A000:0000 -- it's probably the simplest video mode to program.

This is ASM in C, not sure if it would compile in Borland C++

Code: Select all

init320x200x8() { asm {
  mov  al,$13
  int  $10
}}

putPixel(int screenX; byte screenY,color) { asm {
	mov  ax,$A000
	mov  es,ax
	mov  di,screenX
	mov  ah,screenY
	xor  al,al
	add  di,ax
	shr  ax,1       
	shr  ax,1
	add  di,ax
	mov  al,color
	mov  es:[di],al
}}

byte getPixel(int screenX; byte screenY) { asm {
	mov  ax,$A000
	mov  es,ax
	mov  di,screenX
	mov  ah,screenY
	xor  al,al
	add  di,ax
	shr  ax,1       
	shr  ax,1
	add  di,ax
	mov  al,es:[di] /* assumes language lets you pass result in AL */
}}
The byte high load and two shifts are many times faster than doing a MUL.
If everyone is thinking the same, somebody isn't thinking.
developertn
9-bit ubernerd
Posts: 833
Joined: March 23rd, 2015, 4:23 pm

Re: Please Help me!!!!

Post by developertn »

kika wrote:Now, I use turbo C++ and Dosbox.
However, I want to uses graphics.h, how can I use 256 color in setcolor().
It depends on which programming package you have.

Borland C++ 2.0 with built in assembler is a workable package. So is Borland Turbo C 2.01 and Borland Turbo Assembler 4.1. However with both packages you do need your own routines to access VGA 256 color modes.

Here is the complete code to set 256 color mode without graphics.h.

void setvideo()
{
asm push ax;
asm push bx;
asm push cx;
asm push dx;
asm push ds;
asm push si;
asm push es;
asm push di;

asm mov al, 013h;
asm mov ah, 0;
asm int 10h;

asm pop di;
asm pop es;
asm pop si;
asm pop ds;
asm pop dx;
asm pop cx;
asm pop bx;
asm pop ax;
}

The above only sets the 256 vga color mode. In future discussions I will give the code to return it to text mode if needed. Then I will give the code to plot pixels directly to the screen if you want.

I have developed these codes myself.

The push and pop is necessary because there are interrupts that does not preserve the values needed after a program call. Even when you return from a call to a routine you want to be right where you left off instead of having your values messed with.
developertn
9-bit ubernerd
Posts: 833
Joined: March 23rd, 2015, 4:23 pm

Re: Please Help me!!!!

Post by developertn »

kika wrote:Now, I use turbo C++ and Dosbox.
However, I want to uses graphics.h, how can I use 256 color in setcolor().
Now this is what you do after you have set the video mode to 256 color vga mode.

The following code will plot a pixel on the screen with the dot being the color of your choice.
Even though 256 colors are possible, it is best to limit them to between 0 and 15.
In computer form, 0 is also a color. It is black in vga mode.

Here are some off the top of my head.

1 - dark blue
7 - dark grey
8 - light grey
10 - light green
12 - pink
14 - yellow
15 - white

The reason you want to limit your colors is because you need to move them elsewhere later. The file saving and loading routines encounters a control number that causes system operations. That is why you need to move the colors elsewhere above number 200 then move them back when loaded.

For instance 10 is the command for nextline. So if you read a color from the file with 10 it will not read it since it prints to the nextline. So you have to trick the system into thinking it is not a control command.

Well here is the code to put a dot on the screen.

void plotpixel(int vgacolor, int xposition, int yposition)
{
asm push ax;
asm push bx;
asm push cx;
asm push dx;
asm push ds;
asm push si;
asm push es;
asm push di;

asm mov ax, SEG (0a000h:0);
asm mov es, ax;
asm mov ax, OFFSET (0a000h:0);
asm mov di, ax;

asm mov ax, yposition;
asm mov bx, 320;
asm mul bx;
asm mov bx, xposition;
asm clc;
asm adc ax, bx;
asm mov bx, di;
asm clc;
asm adc ax, bx;
asm mov di, ax;

asm cld;
asm mov ax, vgacolor;
asm mov ah, 0;
asm stosb;

asm pop di;
asm pop es;
asm pop si;
asm pop ds;
asm pop dx;
asm pop cx;
asm pop bx;
asm pop ax;
}
developertn
9-bit ubernerd
Posts: 833
Joined: March 23rd, 2015, 4:23 pm

Re: Please Help me!!!!

Post by developertn »

Now, I will end this for the time being with the final codes to put it all together. These codes work in Borland C++ 2.0 with built in Borland Turbo Assembler 2.51. They also work with Borland Turbo C 2.01 and Borland Turbo Assembler 4.1.

This code below will return the video back to text mode instead of VGA 256 color mode.

void returnvideo()
{
asm push ax;
asm push bx;
asm push cx;
asm push dx;
asm push ds;
asm push si;
asm push es;
asm push di;

asm mov al, 3;
asm mov ah, 0;
asm int 10h;

asm pop di;
asm pop es;
asm pop si;
asm pop ds;
asm pop dx;
asm pop cx;
asm pop bx;
asm pop ax;
}

Now the following code will make use of the three codes with have built so far.

int main()
{
unsigned long pause;

setvideo();
plotpixel(15, 1, 1);

for(pause = 0; pause < 12000; pause++)
{
asm nop;
}

returnvideo();

return(0);
}

So that is how you do it. You call setvideo with the half open and half close circle and the semicolon.

The program will run so fast that the dot just flashes if you do not pause it somehow.
So if it goes too fast to see, just increase the value of 12000 to a greater number.
I usually just keep adding 0 one at a time until it is slow enough.

If you add too many 0 it may be too slow and lock up.
User avatar
DOSGuy
Website Administrator
Posts: 1063
Joined: September 2nd, 2005, 8:28 pm
Contact:

Re: Please Help me!!!!

Post by DOSGuy »

developertn wrote:
Here is the complete code to set 256 color mode without graphics.h.

void setvideo()
{
asm push ax;
asm push bx;
asm push cx;
asm push dx;
asm push ds;
asm push si;
asm push es;
asm push di;

asm mov al, 013h;
asm mov ah, 0;
asm int 10h;

asm pop di;
asm pop es;
asm pop si;
asm pop ds;
asm pop dx;
asm pop cx;
asm pop bx;
asm pop ax;
}
That's a pretty slow way to do it. You can push all eight registers in one instruction with pusha, and pop them all back with popa. (That's not really necessary in this case since INT 10H with AH=0 will only destroy the AH and AL registers, so you could just push and pop AX.) You can set AH and AL at the same time by setting AX. That whole code block can be reduced to:

Code: Select all

void setvideo()
{
asm pusha;

asm mov ax, 13h;
asm int 10h;

asm popa;
}
Ditto to return to Mode 3.

Code: Select all

void returnvideo()
{
asm pusha;

asm mov ax, 3;
asm int 10h;

asm popa;
}
Running a loop of 12000 NOPs isn't a great way to set a pause because you can't predict how long it will take on any computer other than your own. A slower computer will take longer than you intended, and a faster computer will take less time than you intended. We used to do those kinds of loops in BASIC in the early days of PCs, but what took 2 seconds on your 286 took less than a second on a 386 and took no time at all on a Pentium. Borland dealt with that problem by benchmarking your computer at the beginning of the program to figure out, for instance, how many loops it could run per second. Then if they wanted a two second pause, they could say:

Code: Select all

for (pause = 0; pause < cyclespersec * 2; pause++)
{
 asm nop;
}
That's where you run into a problem if you declare too small a variable for cyclespersec. Borland programs started failing when your CPU got to about 200 MHz because the benchmarking result got too large to fit in the variable and caused an overflow error. Still, this allowed you to declare a length of time for events in milliseconds in Turbo Pascal, rather than having to create loops and pick a number of cycles that would be the right length of time for you, but no one else in the world. If the ability to set lengths of time in milliseconds isn't a native part of your compiler, there must be third-party code that you could find to do this for you.
Today entirely the maniac there is no excuse with the article.
developertn
9-bit ubernerd
Posts: 833
Joined: March 23rd, 2015, 4:23 pm

Re: Please Help me!!!!

Post by developertn »

DOSGuy wrote:
developertn wrote:
Here is the complete code to set 256 color mode without graphics.h.

void setvideo()
{
asm push ax;
asm push bx;
asm push cx;
asm push dx;
asm push ds;
asm push si;
asm push es;
asm push di;

asm mov al, 013h;
asm mov ah, 0;
asm int 10h;

asm pop di;
asm pop es;
asm pop si;
asm pop ds;
asm pop dx;
asm pop cx;
asm pop bx;
asm pop ax;
}
That's a pretty slow way to do it. You can push all eight registers in one instruction with pusha, and pop them all back with popa. (That's not really necessary in this case since INT 10H with AH=0 will only destroy the AH and AL registers, so you could just push and pop AX.) You can set AH and AL at the same time by setting AX. That whole code block can be reduced to:

Code: Select all

void setvideo()
{
asm pusha;

asm mov ax, 13h;
asm int 10h;

asm popa;
}
Ditto to return to Mode 3.

Code: Select all

void returnvideo()
{
asm pusha;

asm mov ax, 3;
asm int 10h;

asm popa;
}
Running a loop of 12000 NOPs isn't a great way to set a pause because you can't predict how long it will take on any computer other than your own. A slower computer will take longer than you intended, and a faster computer will take less time than you intended. We used to do those kinds of loops in BASIC in the early days of PCs, but what took 2 seconds on your 286 took less than a second on a 386 and took no time at all on a Pentium. Borland dealt with that problem by benchmarking your computer at the beginning of the program to figure out, for instance, how many loops it could run per second. Then if they wanted a two second pause, they could say:

Code: Select all

for (pause = 0; pause < cyclespersec * 2; pause++)
{
 asm nop;
}
That's where you run into a problem if you declare too small a variable for cyclespersec. Borland programs started failing when your CPU got to about 200 MHz because the benchmarking result got too large to fit in the variable and caused an overflow error. Still, this allowed you to declare a length of time for events in milliseconds in Turbo Pascal, rather than having to create loops and pick a number of cycles that would be the right length of time for you, but no one else in the world. If the ability to set lengths of time in milliseconds isn't a native part of your compiler, there must be third-party code that you could find to do this for you.

Those are good points. There is one exception, for some reason pusha and popa does not work on my chip. You actually have to do each one manually. Even though the AH and AL registers seem to be the only one effected it is better safe than sorry for me to do it this way. Faster is not necessarily better than safe.

As for the cycles per second you can estimate it by waiting for the time to reach the next "brand new" minute increment. After that see how many loops can be done within the minute after that. This is kind of slow benchmarking however worth quite a bit especially when moving codes between machines that vary in mhz.
developertn
9-bit ubernerd
Posts: 833
Joined: March 23rd, 2015, 4:23 pm

Re: Please Help me!!!!

Post by developertn »

Well, here in my demo is an inspired work from God.

It contains a code of my very own making to approximate the cycles of a cpu.

It is written in Borland Turbo C 2.01 mixed with inline Borland Turbo Assembler 4.1.

http://www.mediafire.com/download/xb96k ... enonmh.zip
Post Reply