• Please review our updated Terms and Rules here

Some info about EGA and sprites

Mills32

Experienced Member
Joined
Sep 25, 2018
Messages
149
Location
Spain
I want to test some ideas in EGA video card but I can't find a lot of info about it.

For the moment I can load images to vram in mode 0D, to create a background, and now I want to draw sprites on top of it.

I know how to copy and restore the background every time a sprite is redrawn, but I don't really know whant's the fastest way to "paste" a sprite with transparent parts on top of the background.

In VGA I found some "compiled sprites" functions to draw the sprite, but I can't find anything like that for EGA.

Thanks.
 
I suggest you track down and read Michael Abrash's Zen of Graphics as it goes into this exactly, in easy to understand (relatively speaking) terms. A lot of people recommend Michael Abrash’s Graphics Programming Black Book, because it has a lot of duplicated sections, however the latter doesn't cover EGA at all, whereas the former does.

If you come up short and don't want to buy a copy, send me a PM.
 
Yeah, I can't recommend Abrash enough for this. If you're specifically targetting EGA/VGA planar modes, about the only thing the hardware doesn't do is wrap up its masking/copying capability up in nice, convenient block operations.
 
I'd suggest Ferrara's "Programmers Guide to the EGA/VGA" as it does a great job explaining blitting operation using the masks, and how to manipulate the parallel bit-planes.

BIG thing to remember on EGA is that it's not colour packed, it's 4 separate memory planes of monochrome bitmaps. It's like having four separate 640 pixel wide CGA modes with each one assigned a colour component.

You can mask off bit-planes for read/write, and set the latches so that you can AND or OR your writes to the existing values. This can be cool for sprites as you can perform your mask 8 pixels in one memory write, and write single colour sprites in another write. Where it sucks is multi-color is you oft have to treat each plane as its own write.

But even then done properly writing white (all bit planes on) tops out at 8 pixels for four bytes of writing.

Been decades since I played with that though. I think the last time I did so was actually on 16 color VGA where I tweaked up to 720x480 and created a program that did anti-aliased fonts. Been meaning to revisit that code as I have a crazy idea for 640x350x4 on EGA with two pages using the 16 color mode. Rather than moving the memory offset to page flip, change the palette to ignore two of the bit planes.

I often have crazy ideas that work, are fun to play with, but really aren't useful for anything.
 
I really need to revisit the documentation, but I recall being pretty sure that you could do 8-pixel VRAM-VRAM copies with single-byte reads and writes. Been ages since I looked into it, though.
 
Speaking of Abrash, maybe this will be helpful. Sample implementation of an EGA (and CGA) sprite engine with MASM source and a detailed writeup:

https://archive.org/details/PC_Tech_Journal_vol04_n08/page/n127/mode/2up

It is for CGA, but it can also be useful, gathering info from all book and sources posted here, I think I have an idea of how to to it.

From the books I got how to properly activate planes and also the AND/OR write modes (but they don't seem very clear of hoaw to use them to paste "sprites"). From this last link, I got read you have to AND a mask to delete (set to black) the pixels the sprite is going to destroy, then you have to OR the bits from the actual sprite, so that they are inserted without disturbing the background bits.

I could not make it work because I don't really know much about the EGA, and I'm surelly doing things wrong, anyway this is what I tried:

Code:
//First go into mode 0D (320x200 16 colours)
//Copy some "tile data" to VRAM[0]
//Generate a square tile at VRAM[84] by moving bytes from"tile data"

//Now try to paste some data on top of the tile

asm{
	//enable write to all planes
	mov dx,003c4h
	mov ax,0F02h
	out dx,ax
	mov dx,003ceh
	mov ax,008h		
	out dx,ax

	//set write mode = 2
	mov DX,3ceh
	mov AL,5	
	mov AH,0
	out	DX,AX

	//Set bit mask
	mov DX,3ceh
	mov AL,8	
	mov AH,01010101b //some bit mask pattern to see if it works, it should produce an alternating patterns in all the 8 pixels?
	out	DX,AX

	//set AND mode for mask
	mov DX,3ceh
	mov AL,3
	mov	AH,00001000b //bits 3-4 = 1, AND mode
	out DX,AX
}

//This should produce a black pixels pattern to 8 pixels
vram[84+42+42+42+42+42] = 0x00;

egatest_000.png

It kind of works... But only for the last pixels...

If this first part worked, the only thing left to do, would be to paste a byte from the sprite, on top of the black pixels.
 
Last edited:
It works!

Code:
	//Sprite = DS:SI
	//VRAM = ES:DI
	mov	al,00000111b	//A sample mask
	mov	dx,03CEH+1	//setup bit mask
	out	dx,al			//al = mask

	mov	dx,03C4H+1
	mov	al,01h
	out	dx,al			//select plane 0
	mov	al,es:[di]		//load latches from VRAM es:di to  al
	lodsb			//byte from DS:SI(sprite) to AL, INC SI
	mov	es:[di],al		//write color plane 0 to VRAM
		
	mov	dx,03C4H+1
	mov	al,02h
	out	dx,al			//select plane 1
	mov  al,es:[di]		//load latches from VRAM es:di to  al
	lodsb			//byte from DS:SI(sprite) to AL, INC SI
	mov	es:[di],a		//write color plane data to VRAM
	
	//the same for plane 3 and 4

Sprite data is stored in a way that each byte contains the data for a bit plane, so "lodsb" will read the array.

Now I'll have to process data to paste the sprite in any x position. I hope it is not very slow.
 
Remember, for arbitrary X positions, the EGA not-quite-a-blitter can actually shift the written data up to 7 pixels (i.e. anywhere within a byte) all on its own as part of the read/modify/write mode.
 
Last edited:
Remember, for arbitrary X positions, the EGA not-quite-a-blitter can actually shift the written data up to 7 pixels (i.e. anywhere within a byte) all on its own as part of the read/modify/write mode.

I konw, that's the next step. But I think i'll have to shift data in ram, because the EGA will rotate the bits, so using for example a 16x16 pixel sprite, will result in weird things, I'll have to shift two bytes at once using the cpu.

I found that code in a sprite demo, it looks similar to the code from the books, but it is a bit different. Also it shifts the sprite in ram, and does not use the rotate settings of the EGA... so I'll try to optimize it.
 
Wait, does it seriously do a rotate? That's...eccentric.

That's what I read... Anyway, I calculated the ram for the 8 copies (needed for every frame of animation), plus an extra column (to shift the 8 pixels) and It is very low, even If I want to use a 64x64 sprite. As I'm targeting 8088 8086... I think it is the fastest way.
 
I really need to poke around with this a bit myself...I read up on it years ago, but never got around to doing any serious test cases. I'd like to think it's not a true rotate, simply because I can't fathom the use for such a function in this context, but the documentation I've read does refer to the bitfield in that register as "Data Rotate," so who knows...
 
So, I think this is the only way of drawing sprites on EGA:

Code:
//This is a "sprite", 8 pixels defined with 4 bytes.
unsigned char bitmap[4] = {
	0x55,//01010101
	0x33,//00110011
	0x0F,//00001111
	0x00,//00000000
};

asm{
	lds	si,[bitmap]		//DS:SI
	mov	ax,0A000h
	mov	es,ax						
	mov	di,scr_offset		//ES:DI destination vram
				
	mov	al,es:[di]		//load latches from VRAM destination es:di
	mov	al,10101010b		//setup bit mask
	mov	dx,03CEH+1       		
	out	dx,al			//al = mask from sprite data
				
	mov	dx,03C4H+1
	mov	al,01h
	out	dx,al			//select plane 0 DX = 03C4H+1
	movsb				//DS:SI to ES:DI, inc SI and DI.		
	dec	di
	mov	al,02h
	out	dx,al			//select plane 1
	movsb
	dec	di
	mov	al,04h
	out	dx,al			//select plane 2
	movsb
	dec	di
	mov	al,08h
	out	dx,al			//select plane 3
	movsb
}

Is there any other way? :confused:, It's too much work to draw just 8 pixels :(
 
Back
Top