/* 

SCREEN.C -- package of routines for direct screen writes

*/

#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <dos.h>
#include "screen.h"

typedef unsigned char BYTE;
typedef unsigned short USHORT;
typedef unsigned long ULONG;
typedef unsigned long REALPTR;

#define VIDEO               0x10
#define SCROLL_UP           0x06
#define GET_VIDEO_MODE      0x0F

static REALPTR vid_mem = {0};

void __stdcall WriteRealMem(REALPTR, void *, unsigned);
void __stdcall ReadRealMem(void *, REALPTR, unsigned);

#define SCR(y,x)            (((y) * 160) + ((x) << 1))

int video_mode(void)
{

    _asm mov ah, GET_VIDEO_MODE
    _asm int 10h
    _asm and eax, 0FFh

}

unsigned get_vid_mem(void)
{

    int vmode = video_mode();
    unsigned vid_seg;
    unsigned vid_ofs = 0;

    if (vmode == 7)
        vid_seg = 0xB000;
    else if ((vmode == 2) || (vmode == 3))
        vid_seg = 0xB800;
    else
        return 0;

    return vid_seg;

}

int video_init(void)
{
    vid_mem = get_vid_mem() << 16;
}

void wrt_str(int y, int x, ATTRIB attr, unsigned char *p)
{

    REALPTR v = vid_mem + SCR(y, x);
    char lbuff[80 * 2], *q;
    int ok;

    q = lbuff;
    ok = 0;
    while (ok < 80 && *p)
    {
        *q++ = *p++;
	*q++ = attr;
        ++ok;
    }
    WriteRealMem(v, lbuff, ok);

}

void wrt_printf(int y, int x, ATTRIB attr, char *fmt, ...)
{
    static char buf[128] = {0};
    va_list marker;

    va_start(marker, fmt);
    vsprintf(buf, fmt, marker); 
    va_end(marker);
    wrt_str(y, x, attr, buf);

}

void wrt_chr(int y, int x, ATTRIB attr, unsigned char c)
{

    REALPTR v = vid_mem + SCR(y, x);
    USHORT ch_attr;
 
    ch_attr = (attr << 8) + c;
    WriteRealMem(v, &ch_attr, 2);

}

void set_attr(int starty, int startx, int endy, int endx, ATTRIB attr)
{

    int x, y;

    for (y=starty; y<=endy; y++)
    {
        REALPTR v = vid_mem + SCR(y, startx);
        for (x=startx; x<=endx; x++)
        {
	    WriteRealMem(v + 1, &attr, 1);
	    v += 2;
        }
    }

}

void fill(int starty, int startx, int endy, int endx, unsigned char c,
    ATTRIB attr)
{

    USHORT ch_attr;
    REALPTR v = vid_mem;
    int x, y;

    ch_attr = (attr << 8) + c;	
    for (y=starty; y<=endy; y++)
        for (x=startx, v=vid_mem+SCR(y, startx); x<=endx; x++)
        {
	    WriteRealMem(v, &ch_attr, 2);
	    v += 2;
        }

}

void clear(int starty, int startx, int endy, int endx, ATTRIB attr)
{
    _asm mov ax, 0600h
    _asm mov bh, byte ptr attr
    _asm mov ch, byte ptr starty
    _asm mov cl, byte ptr startx
    _asm mov dh, byte ptr endy
    _asm mov dl, byte ptr endx
    _asm int 10h
}

void cls(void)
{
    clear(0, 0, 24, 79, NORMAL);
}

static char brd[2][6] = {
    179, 196, 218, 191, 192, 217,       /* single box chars */
    186, 205, 201, 187, 200, 188        /* double box chars */
    } ;

void border(int starty, int startx, int endy, int endx, ATTRIB attr, int dbl)
{
    REALPTR v;
    char *b;
    register int i;
    USHORT ch_attr;
    
    b = brd[(dbl-1) & 1];
    
    for (i=starty+1; i<endy; i++)
    {
        wrt_chr(i, startx, attr, *b);
        wrt_chr(i, endx, attr, *b);
    }
    b++;
    ch_attr = (attr << 8) + *b;
    for (i=startx+1, v=vid_mem+SCR(starty, startx+1); i<endx; i++)
    {
        WriteRealMem(v, &ch_attr, 2);
	v += 2;
        // equivalent to wrt_chr(starty, i, attr, *b);
    }
    for (i=startx+1, v=vid_mem+SCR(endy, startx+1); i<endx; i++)
    {
        WriteRealMem(v, &ch_attr, 2);
	v += 2;
        // equivalent to wrt_chr(endy, i, attr, *b);
    }
    b++;
    wrt_chr(starty, startx, attr, *b++);
    wrt_chr(starty, endx, attr, *b++);
    wrt_chr(endy, startx, attr, *b++);
    wrt_chr(endy, endx, attr, *b);
}

void cursor(int on)
{
    static short old_curs = 0;
    if (on && old_curs)
    {
        _asm mov cx, old_curs
        _asm mov ah, 1
        _asm int 10h
    }
    else if (! (on || old_curs))
    {
        _asm mov ah, 3
        _asm mov bh, 0
        _asm int 10h
        _asm mov old_curs, cx
        _asm mov cx, 2000h
        _asm mov ah, 1
        _asm int 10h
    }
}

void center(int y, ATTRIB attr, char *s)
{
    wrt_str(y, 40 - (strlen(s) >> 1), attr, s);
}

void save_screen(unsigned short *buf)
{

	ReadRealMem(buf, vid_mem, 2000 * sizeof(USHORT));

}

void restore_screen(unsigned short *buf)
{

	WriteRealMem(vid_mem, buf, 2000 * sizeof(USHORT));

}
