Frederic Cambus

Blog · Git · Contact

Character and color cycling effect in C on DOS

C DOS

As mentioned in my previous post about playing with DJGPP and GCC 10 on DOS, I have been redoing my small character and color cycling effect in text mode. The original version in JavaScript can be seen here.

Cycling effect

To understand why we can't access video memory directly and need to use the DPMI service to create a selector to access the required real-mode segment address, please refer to section 18.4 of the DJGPP FAQ.

The effect can be downloaded here. Sadly, the resulting binary is quite large (104K stripped!), and it requires CWSDPMI to run.

Here is the code:

#include <conio.h>
#include <dpmi.h>
#include <go32.h>
#include <pc.h>

void
wait_vbl()
{
	while(inp(0x3da) & 0x08);
	while(!(inp(0x3da) & 0x08));
}

int
main()
{
	short video = __dpmi_segment_to_descriptor(0xb800);
	unsigned char buffer[4000];

	int character = 0, color = 0;

	/* Define character and color arrays */
	char characters[] = { 0x5c, 0x7c, 0x2f, 0x2d };
	char colors[] = { 0xf, 0xb, 0x9, 0x1, 0x9, 0xb, 0xf };

	while (!kbhit()) {
		for (size_t offset = 0; offset < 4000; offset += 2) {
			/* Write character and color data */
			buffer[offset] = characters[character];
			buffer[offset + 1] = colors[color];

			/* Increment the color index */
			color = color + 1 < sizeof(colors) ? color + 1 : 0;
		}

		/* Increment the character index */
		character = character + 1 < sizeof(characters) ?
		    character + 1 : 0;

		/* Copy the buffer into text mode video memory */
		movedata(_my_ds(), (unsigned)buffer, video, 0, 4000);

		/* Wait for VBL */
		wait_vbl();
		wait_vbl();
		wait_vbl();
		wait_vbl();
		wait_vbl();
	}
}