/*	OXEGE6.C
**
**	Higher-level window, fill, and outline routines
**
*/

#include "a:stdio.h"
#include "b:oxege.h"

char *w0, *w1, *w2, *w3, *w4;

#ifndef	SMALL
extern void fasm(), mmov();
#endif

savewindow( top, left, bottom, right, function, wnumber )
	int top, left, bottom, right, function, wnumber;
	{
	char *chptr1, *chptr7, *atptr1, *atptr7, *window;
	int l, size;
	if ( function != NULL )
		{
		switch ( wnumber )
			{
			case 0:	window = w0;
				break;
			case 1:	window = w1;
				break;
			case 2:	window = w2;
				break;
			case 3:	window = w3;
				break;
			case 4:	window = w4;
				break;
			}
		}
	else 
		{
		window = malloc( ((bottom-top+1)*2)*(right-left+1) );
		switch( wnumber )
			{
			case 0:	w0 = window;
				break;
			case 1:	w1 = window;
				break;
			case 2:	w2 = window;
				break;
			case 3:	w3 = window;
				break;
			case 4:	w4 = window;
				break;
			}
		}
	chptr1 = window;
	atptr1 = window + ( (bottom-top+1) * (right-left+1) );
	l = top;

	bank( 7 );
	size = (right-left)+1;
	while ( l <= bottom )
		{
		chptr7 = VIDEO_RAM + (l * 128) + left;
		atptr7 = VIDEO_ATT + (l * 128) + left;

		if (function == NULL )
			{
			memmov( chptr7, chptr1, size );
			memmov( atptr7, atptr1, size );
			}
		if (function == 1 )
			{
			memmov( chptr1, chptr7, size );
			memmov( atptr1, atptr7, size );
			}
		chptr1 += size;
		atptr1 += size;
		++l;
		}


	if( function == 1)
		{
		free( window );
		} 
	bank( 1 );
	}

char FIch, FIat;
int  FItop, FIleft, FIbot, FIright, FIfc, FInl;

fill( top, left, bottom, right, character, attribute )
	int top, left, bottom, right, character, attribute;
	{
	FIch = character;
	FIat = attribute;
	FItop = top;
	FIleft = left;
	FIbot = bottom+1;
	FIright = right+1;
	FIfc = (top*128)+left;
	FInl = 128-(right+1)+left;
#ifdef	SMALL 
#asm
	.Z80
		ld	a,65		; bank 7 reference
		out	(0),a		; enter bank 7
		ld	hl,FIleft	; hl = pointer to column
		ld	d,(hl)		; now d = column counter
		ld	hl,FItop	; hl = pointer to line
		ld	e,(hl)		; now e = line counter
		ld	ix,0c000h	; video character RAM
		ld	iy,0d000h	; video attribute RAM
		ld	bc,(FIfc)	; bc = first character offset
		add	ix,bc		; add f.c. offest to character pointer
		add	iy,bc		; add f.c. offset to line pointer		
		ld	hl,FIch		; hl = pointer to character
		ld	b,(hl)		; now b = character
		ld	hl,FIat	 	; hl = pointer to attribute
		ld	c,(hl)		; 
	loop:	ld	(ix),b		; poke character
		ld	(iy),c		; poke attribute
		inc	ix		; increment character pointer
		inc	iy		; increment attribute pointer
		inc	d		; increment column counter
		ld	hl,(FIright)	; right column in l
		ld 	a,d		; current column to a register
		cp	l		; is it right column?
		jp	z,nextl		; then next line
		jp	loop		; else loop
	nextl:	inc	e		; increment line counter
		ld	hl,(FIbot)	; bottom line in l
		ld	a,e		; load a with line counter
		cp	l		; is it the bottom?
		jp	z,done		; then we're done
		ld	hl,FIleft	; hl = pointer to left column
		ld	d,(hl)		; d = column counter
		push	bc		; save bc for math operation
		ld	bc,(FInl)	; bc = count to next line
		add	ix,bc		; add it to character pointer
		add	iy,bc		; add it to attribute pointer
		pop	bc		; restore bc after math
		jp	loop		; and do the next line
	done:	ld	a,1		; bank 1 reference
		out	(0),a		; enter bank 1
	.8080
#endasm
#else
	fasm();
#endif
	}

outline( top, left, bottom, right, character, attribute )
	int top, left, bottom, right, character, attribute;
	{
	fill( top, left+1, top, right-1, character+2, attribute);
	cpoke( top, right, character+5, attribute );
	fill( top+1, right, bottom-1, right, character+1, attribute );
	cpoke( bottom, right, character+7, attribute );
	fill( bottom, left+1, bottom, right-1, character+3, attribute );
	cpoke( bottom, left, character+6, attribute );
	fill( top+1, left, bottom-1, left, character, attribute );
	cpoke( top, left, character+4, attribute );
	}

char *MMfrom, *MMto;
int   MMsize;

memmov( from, to, size )
	char *from, *to;
	int size;
	{
	MMfrom = from;
	MMto = to;
	MMsize = size;
#ifdef	SMALL
#asm
	.z80
	ld	hl,(MMfrom)
	ld	de,(MMto)
	ld	bc,(MMsize)
	ldir
	.8080
#endasm
#else
	mmov();
#endif
	}
fdef	SMALL
#asm
	.z80
	ld	hl,(MMfrom)
	ld	de,(MMto)
	ld	