#include <stdio.h>
#include <conio.h>
#include <i86.h>
#include <graph.h>
#include <malloc.h>

/*
This shows how I'm drawing sprites in Open Watcom C for DOS. It is just a testing program. Attempting to force page flipping in mode 12h.
It creates a mask for the sprite to make transparency work. It currently has to grab the sprite off the screen cause of watcom
limitations. I will later make a program to convert bitmap to the native watcom _putimage format so that I don't need to draw to the
screen first like in QBASIC. For now just experimenting with how to make the page flipping work. Once I figure this, it will be ready
for a game engine.
*/

#define SCREEN_WIDTH_IN_BYTES 80
#define PAGE_0_START 0
#define PAGE_1_START (480 * SCREEN_WIDTH_IN_BYTES)

typedef unsigned char  byte;
typedef unsigned short word;
word *my_clock=(word *)0x0000046C;

const int CAPPY_WIDTH = 20;
const int CAPPY_HEIGHT = 20;
const unsigned char cappy[] = {
    14,14,00,00,00,00,00,12,12,12,12,12,00,00,00,00,00,00,14,14,
    14,00,00,00,00,00,12,12,12,12,12,12,12,00,00,00,00,00,00,14,
    00,00,00,00,00,12,12,04,04,04,04,04,12,12,00,00,00,00,00,00,
    00,00,00,00,12,12,15,15,15,04,15,15,15,12,12,00,00,00,00,00,
    00,00,00,12,12,04,15,00,15,04,15,00,15,04,12,12,00,00,00,00,
    00,15,12,12,04,04,15,15,15,12,15,15,15,04,04,12,12,15,00,00,
    00,15,12,12,04,04,04,04,04,12,04,04,04,04,04,12,12,15,00,00,
    00,15,12,12,04,04,00,04,04,04,04,04,00,04,04,12,12,15,00,00,
    00,00,00,12,12,04,04,00,15,00,15,00,04,04,12,12,00,00,00,00,
    00,00,00,00,12,12,04,04,00,00,00,04,04,12,12,02,00,00,00,00,
    00,00,00,00,02,12,12,04,04,04,04,04,12,12,02,02,02,00,00,00,
    00,00,00,02,02,02,12,12,12,12,12,12,12,02,02,02,02,00,00,00,
    00,00,02,02,02,02,00,12,12,12,12,12,00,00,02,02,02,00,00,00,
    00,01,01,01,01,01,00,00,00,00,00,00,00,00,02,02,02,00,00,00,
    00,01,01,01,01,01,00,00,00,00,00,00,00,00,02,02,02,00,00,00,
    00,00,00,00,00,00,00,00,00,00,00,00,00,00,02,02,02,00,00,00,
    00,00,00,00,00,00,00,00,00,00,00,00,00,00,02,02,02,00,00,00,
    00,00,00,00,00,00,00,00,00,00,00,00,00,01,01,01,01,01,00,00,
    14,00,00,00,00,00,00,00,00,00,00,00,00,01,01,01,01,01,00,14,
    14,14,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,14,14
};

void draw_mask()
{
    int x,y;
    int c = 0;
    for (y = 0; y < CAPPY_HEIGHT; y++)
    {
        for (x = 0; x < CAPPY_WIDTH; x++)
        {
            if (cappy[c] == 0)
                _setcolor(15);
            else
                _setcolor(0);
            _setpixel(x, y);
            c++;
        }
    }
}

void draw_sprite()
{
    int x,y;
    int c = 0;
    for (y = 0; y < CAPPY_HEIGHT; y++)
    {
        for (x = 0; x < CAPPY_WIDTH; x++)
        {
            _setcolor(cappy[c]);
            _setpixel(x, y);
            //putpixel(x + xpos, y + ypos, cappy[c]);
            c++;
        }
    }
}

void main()
{
    int x,y,c;
    int randX,randY;
    word i;
    char *cappyBuf;
    char *cappyMask;
    FILE *fp;

    long sizeOBuf;

    srand(*my_clock);
    _setvideomode(_VRES16COLOR);

    /* Flip to page 1 */
    outpw(0x3D4, 0x0C | (((PAGE_1_START * 2) >> 8) << 8));

    sizeOBuf = _imagesize(0, 0, 19, 19);
    cappyMask = (char*) malloc(sizeOBuf);
    _getimage(0, 0, 19, 19, cappyMask);

	/* We save the empty sprite (before drawing to it) to a file for analysis of the format */
    fp = fopen("empty.spr", "w");
    if (fp != NULL)
    {
        for (i = 0; i < sizeOBuf; i++)
            fputc(cappyMask[i], fp);
        fclose(fp);
    }

	/* We try to draw our mask on the offscreen page (not exactly right) */
    draw_mask();
    _getimage(0, 0, 19, 19, cappyMask);

	/* Save the actual mask for analysis */
    fp = fopen("mask.spr", "w");
    if (fp != NULL)
    {
        for (i = 0; i < sizeOBuf; i++)
            fputc(cappyMask[i], fp);
        fclose(fp);
    }

    getch();
    
    draw_sprite();

    getch();

	/* Grab our real sprite from the screen */
    sizeOBuf = _imagesize(0, 0, 20, 20);
    cappyBuf = (char*) malloc(sizeOBuf);
    _getimage(0, 0, 20, 20, cappyBuf);

	/* Save for analysis */
    fp = fopen("cappy.spr", "w");
    if (fp != NULL)
    {
        for (i = 0; i < sizeOBuf; i++)
            fputc(cappyBuf[i], fp);
        fclose(fp);
    }

    /* Flip to page 0
	LOOK THOSE SPRITES WE DREW ARE NOW AT 0,0 */
    outpw(0x3D4, 0x0C | ((PAGE_0_START >> 8) << 8));
    
	/* Draw a few sprites back on the main page again just to see performance
	eventually this should happen on the second page to test the flip */
    for (i = 0; i < 5; i++)
    {
        randX = rand() % 640;
        randY = rand() % 480;
        _putimage(randX, randY, cappyMask, _GAND);
        _putimage(randX, randY, cappyBuf, _GOR);
    }

    getch();
    
	/* Even more sprites - note the transparency */
    for (i = 0; i < 50000; i++)
    {
        randX = rand() % 640;
        randY = rand() % 480;
        _putimage(randX, randY, cappyMask, _GAND);
        _putimage(randX, randY, cappyBuf, _GOR);
    }
    getch();
}