Failing to preserve dx across int 10h call
One serious problem that you have is that you are not pushing the value of dx prior to executing int 10h. If int 10h changes the value of dx then when you set currentbank to dx, it is not what you expect it to be. This in itself is incurring that on every pixel your program is bankswitching, even when it does not need to. Make sure you preserve dx across the int 10h call.
Don't check for screen boundaries
Also do not check for the screen boundaries. These checks will slow the entire system down since it will check this for every pixel. Check for this in another functions such as a clipping function. If you are only doing 2D graphics then you probably have no choice but to do those checks both on GetPixel. PutPixel need not check boundaries. Assume that the programmer knows that he or she should not try to get the color of a pixel that does not exist. Similar to C's error checking. It is the programmer's responsibility to be aware of what he or she is doing. This will save a lot of cycles since you do not have to babysit for the programmer.
Problem with 24-bit modes
Salem is right in that in 24 bit mode their will be a time in which half a pixel lies in the next bank. This only happens in 24 bit modes. Very annoying.
This is for 16-bit modes only, 24-bit was way too slow in DOS and not worth the hassle of the bank problem.
This can be altered to GetPixel with a few minor changes.
Code:
void PlotPixel(long poffset,WORD color)
{
//16 bit color offset
register int aoffset=poffset & 0xFFFF;
register int curbank=poffset>>16;
asm {
START:
mov ax,[curbank]
cmp ax,[bank]
jz PLOTPIXEL
SWITCHBANKS:
mov ax,4f05h
mov bx,0
mov dx,curbank
push dx //Preserve dx across int 10h
int 10h
pop dx //Get previous dx off the stack
UPDATEBANK:
mov [bank],dx
PLOTPIXEL:
mov ax,0a000h
mov es,ax
mov di,WORD [aoffset]
mov ax,color
stosw
}
}
It would be even faster to do a STOSD instead of STOSW but Borland does not allow that instruction. You absolutely must push dx prior to int 10h.
Code two separate functions for VESA and non-VESA
I would code two different functions for VESA and non-VESA modes. Use function overrides so that the compiler chooses which one it will use - that way you do not have to waste cycles checking which one to use.
void PlotPixel(long offset,BYTE color);
void PlotPixel(long offset,WORD color);
WORD GetPixel(long offset);
BYTE GetPixel(long offset);
You are checking to see if you are in VESA mode on every pixel. Once you set the mode, you know you are - so to check on each pixel is a waste of precious cycles.
Compute offset elsewhere or do not use x and y coords
Also, do not, if you can help it, compute the pixel offset within the PlotPixel/GetPixel function. You could #define the conversion function or better yet you could set up your graphics to use continuing offsets into the buffer instead of x and y coords. This will take some careful planning and effort on your part, but it will be well worth it.
You can alter my above PlotPixel function to do the reverse op or GetPixel still using stosw - though I've not converted it yet. Also your checks for the RGB stuff will slow the system down. Simply have your function retrieve the word. Then create a function that will take a WORD and return RGB in a struct. You want your pixel retrieval function to just retrieve the pixel - extract the RGB's later.
Here is a slower example of a getpixel function w/o using stosw and converting from word to RGB.
This assumes 565 RGB.
Code:
RGB GetPixel(DWORD offset)
{
register int aoffset=offset & 0xFFFF;
register int curbank=offset>>16;
WORD color=0;
asm {
START:
mov ax,[curbank]
cmp ax,[bank]
jz GETPIXEL
SWITCHBANKS:
mov ax,4f05h
mov bx,0
mov dx,curbank
push dx
int 10h
pop dx //Get previous dx
UPDATEBANK:
mov [bank],dx
GETPIXEL:
mov ax,0a000h
mov es,ax
mov bx,WORD [aoffset]
mov ax,es:[bx]
mov [color],ax
}
//Should be elsewhere
RGB temp;
temp.grn=(color &0x7e0)>>6;
temp.red=(color &0xF800)>>11;
temp.blu=(color & 0x1f);
return temp;
}
This does work on my machine and it does not crash.
Hope this helps. Not sure why yours is crashing. Just gave some tips on how to speed it up.
For PlotPixel you can get some speed gains by doing this.
Code:
//These are global or in a struct - your choice
BYTE REDS[32];
BYTE BLUS[32];
BYTE GRNS[32];
for (int i=0;i<32;i++)
{
REDS[i]=i<<11;
GRNS[i]=i<<6;
BLUS[i]=i;
}
#define RGBTOWORD (r,g,b) (WORD)((REDS[r])+(GRNS[g])+(BLUS[b]))
WORD color=RGBTOWORD(red,grn,blu);
Your assembly looks pretty tight, though. Let me know when you are ready to chuck this bank switching stuff and move to protected mode.
Questions? PM me and I'll be glad to help. Is this for your new library? Looks good.