Hello guys,
i was having some fun trying to display graphics in all kinds of different graphics mode for DOS.
So far, i've been able to try out CGA, EGA and (ofc) VGA, including the various Mode-X resolutions.
Just recently, i managed to find out how to support and write pixels for the IBM 8514. (I'll talk about it in another post)
However, i encountered some issues. The IBM 8514 is supposed to work with an IBM AT, which comes with a 80286 and that processor is 16-bits.
Making matters worse, arrays/segment cannot be bigger than 64k, even if you have enough memory.
(and even if you are using protected mode, as i found out later. Not to mention, its full of bugs)
Also, IBM never released hardware documentation for it. It only released documentation for AI, a software layer.
And that software layer is very unsuitable for pixel drawing and framebuffer access.
That adapter supports a resolution of 1024x768 with 256 colors. And the only thing i can do is to draw one pixel at a time.
The picture i want to display is that resolution and its like 768kb big.
You can see where this is going...
Here's the relevant C code for it.
typedef struct tagBITMAP /* the structure for a bitmap. */
{
word width;
word height;
byte *data;
} BITMAP;
BITMAP *bmp;
void drawquad(unsigned long col, short x, short y, unsigned short w, unsigned short h)
{
static HRECT_DATA quad;
quad.coord.x_coord = x;
quad.coord.y_coord = y;
quad.width = w;
quad.height = h;
hscol_data.index = (long) col;
HSCOL(&hscol_data); /* set supplied colour */
HBAR(); /* begin area */
HRECT(&quad); /* draw quadrilateral */
HEAR(&hear_data); /* end area */
}
void draw_pict(BITMAP *bmp,int x,int y)
{
unsigned short i,j;
for(i=0;i<bmp->height;i++)
{
for(j=0;j<bmp->width;j++)
{
drawquad(bmp->data[i+(j*bmp->width)], i, j, 1, 1);
}
}
}
void load_bmp(const char *file,BITMAP *b)
{
FILE *fp;
long index;
word num_colors;
int x;
/* open the file */
if ((fp = fopen(file,"rb")) == NULL)
{
printf("Error opening file %s.\n",file);
exit(1);
}
/* check to see if it is a valid bitmap file */
if (fgetc(fp)!='B' || fgetc(fp)!='M')
{
fclose(fp);
printf("%s is not a bitmap file.\n",file);
exit(1);
}
/* read in the width and height of the image, and the
number of colors used; ignore the rest */
fskip(fp,16);
fread(&b->width, sizeof(word), 1, fp);
fskip(fp,2);
fread(&b->height,sizeof(word), 1, fp);
fskip(fp,22);
fread(&num_colors,sizeof(word), 1, fp);
fskip(fp,6);
/* assume we are working with an 8-bit file */
if (num_colors==0) num_colors=256;
/* try to allocate memory */
if ((b->data = (byte *) malloc((word)(b->width*b->height))) == NULL)
{
fclose(fp);
printf("Error allocating memory for file %s.\n",file);
exit(1);
}
/* Ignore the palette information for now.
See palette.c for code to read the palette info. */
fskip(fp,num_colors*4);
/* read the bitmap */
for(index=(b->height-1)*b->width;index>=0;index-=b->width)
for(x=0;x<b->width;x++)
b->data[(word)index+x]=(byte)fgetc(fp);
fclose(fp);
}
So with the 286's limitation of 64k for arrays, i am stuck.
Actually i thought of several solutions, none of which worked or are ideal :
- Separate the picture into several parts. This would work but it's a huge inconvenience.
- Call the 80286 a brain dead chip (thanks billy) and make it 32-bits only.
The problem is that AI comes with a small bit of assembly and i was unable to make it work in protected mode.
Plus, it wouldn't work on a stock IBM AT.
I looked at the only game for the 8514,
Mah Jong -8514-, and it is also using AI.
I played the game and i noticed its drawings graphics like it would do with vector graphics.
So yeah, not a good example.
So what did programmers do at the time ? And if you don't know, what would you suggest ?
And no please, i don't intend to spit each picture into several parts unless you tell me a good reason why i should do that.
Also, AI only allows you to draw a pixel at best. (Using the rectangle function)
They did fix that later with XGA but that function is not backward compatible with the 8158.