PDA

View Full Version : CGA graphic lib



JoJo_ReloadeD
March 19th, 2014, 12:14 PM
Hello everyone,

I am trying to create a C CGA graphic library, and so far I have:

- plotting in 320 mode (asm)
- plotting in 160 mode (asm)
- line drawing in 320 mode (c)
- palette change (asm)


I need to optimize them (lookup tables), and to create blitting functions for every mode. Does anybody know of docs or one library itself ?

Also, if anybody knows of the same, but for EGA it would be nice.

Thanks!

sergey
March 19th, 2014, 12:58 PM
Have you looked at Borland Graphics Interface (BGI) (http://en.wikipedia.org/wiki/Borland_Graphics_Interface)?
There is an open source (http://openbgi.sourceforge.net/) version of it, but it looks like it only works under Windows...

JoJo_ReloadeD
March 20th, 2014, 01:17 AM
Have you looked at Borland Graphics Interface (BGI) (http://en.wikipedia.org/wiki/Borland_Graphics_Interface)?
There is an open source (http://openbgi.sourceforge.net/) version of it, but it looks like it only works under Windows...

Yes, I know of it, but my goal is to make a fast library, the BGI one it's known for being super slow...

Trixter
March 20th, 2014, 10:31 AM
I started the same thing but never finished it, but you're welcome to pilfer anything you can use: ftp://ftp.oldskool.org/pub/misc/code/CGA.rar

About the only things in there that are worth anything is the MC6845.PAS which has the 6845 very well mapped out and documented, and WILT*.INC which contains near optimal line-drawing for 320/640x200 (and I think my modifications for 160x200x16 as well). There are some tweak modes (160x100x16, 40x50, 40x100, 80x50, 80x100) but that code is generic, I never got around to optimizing it. Also, some of the example programs (TEST*.PAS) do not work with the latest version of the library, but TESTPIX and TESTLINE do and that should be enough for you to compile and run everything.

In ftp://ftp.oldskool.org/pub/misc/code/ is some other code you might be interested in, including TINTERRUP.PAS which includes code to simulate a vertical retrace interrupt for CGA cards (only).

JoJo_ReloadeD
March 20th, 2014, 02:20 PM
I started the same thing but never finished it, but you're welcome to pilfer anything you can use: ftp://ftp.oldskool.org/pub/misc/code/CGA.rar

About the only things in there that are worth anything is the MC6845.PAS which has the 6845 very well mapped out and documented, and WILT*.INC which contains near optimal line-drawing for 320/640x200 (and I think my modifications for 160x200x16 as well). There are some tweak modes (160x100x16, 40x50, 40x100, 80x50, 80x100) but that code is generic, I never got around to optimizing it. Also, some of the example programs (TEST*.PAS) do not work with the latest version of the library, but TESTPIX and TESTLINE do and that should be enough for you to compile and run everything.

In ftp://ftp.oldskool.org/pub/misc/code/ is some other code you might be interested in, including TINTERRUP.PAS which includes code to simulate a vertical retrace interrupt for CGA cards (only).

Thank you so much! :D

deathshadow
March 20th, 2014, 06:41 PM
One trick I've used that might help you speed things up a bit -- instead of wasting time trying to pass the color as 0..3 in color modes, pass it as a populated pixel-packed. For example:
color 0 = 0x00
color 1 = 0x55
color 2 = 0xAA
color 3 = 0xFF

Instead of doing shifts to come up with your mask, you can make a simple 4 byte array to XLAT into:
maskArray : array[0..3] of byte = ( $03, $0C, $30, $C0 );

then for a putpixel you'd


{ assumes es:di is video byte }
mov bx, OFFSET maskArray
mov ax, xCoord
and al, 3
xlat
mov ah, al
not al
and al, es:[di]
and ah, color
or al, ah
stosb

It's easier to take your mask then AND it to the pixel-packed color byte then use a NOT copy of the mask to AND the video location against, than it is to sit there playing with shl al, cl. I'm basically doing the same thing with my font output routines for 160x100 in my current WIP faster 160x100 engine.

Also, if you want more code to look at, you're welcome to look at my 160x100 code from paku paku. It's mostly inline assembler so should'nae be too hard to move over to C.
http://www.deathshadow.com/pakuPaku

The full source for the game is in the archive. The video card detection code might be useful to you -- the sprite functions probably not so much since they are very 'engine specific'.

JoJo_ReloadeD
March 21st, 2014, 01:13 AM
Thanks deathshadow, will try that later :)

deathshadow
March 22nd, 2014, 07:12 PM
I was digging through some old code, and remembered about my trick for CGA address calculation.


mov cl, 2
mov ax, yCoord
ror ax, 1
xor bx, bx
xchg bh, ah
shr bx, cl
mov di, bx
shr ax, cl
add di, ax
shr ax, cl
add di, ax
mov ax, xCoord
mov bx, ax
xchg ah, al
shr bx, cl
add di, bx
mov bx, OFFSET maskTable
and al, $03
xlat

Sneaky trick, the rotate moves that bottom yCoord bit into the upper byte, move that into BX and shift it twice, and you have either 0x2000 or 0x0000 as the result, so set DI to that. clearing BX and using XCHG to isolate that means another shift 2 on AX and we have trunc(yCoord/2)*64, so add that to DI, then shift two more times for *16 and we have our *80. xCoord is simpler since it's just a load it into AX and BX, shift BX to get our X offset and add that to DI, and AL by $03 to get our xlat index value.

The use of CL for those 2x shifts might seem odd since it's a slower operation (8+4n, so 16!), but it's two less memory bytes fetched and the execution time lets the BUI fill up, meaning on a 8088 it's actually faster than unrolling them overall -- the extra execution time means the next 4 bytes of opcodes will have no load penalty, and it's two less bytes for the opcodes themselves. Sounds strange, but it works. The conventional wisdom of unrolling shifts doesn't always jive with real world, especially when they're all the same shift amount.

Trixter
March 22nd, 2014, 09:42 PM
and we have our *80

Or, burn 400 bytes for a translation table.